I moved to a new URL! Check it out!

posts tagged with: otter

Quick Explosion Stuff

Quick Explosion Stuff
Last night I had the opportunity to talk about explosions in front of a group of game developers. I ended up doing a live demo of making an explosion effect from scratch. Here's what I ended up with after about 45 minutes:

Image


Not my best work but not bad for having to come up with something on the fly in front of a bunch of people. I ended up using Photoshop for animations, ShoeBox to spit out sprite sheets, and Otter to implement the effects.

Image


One of the fun things of the presentation was adding suggestions from the audience which included spawning more explosions from the first explosion. This is why the whole screen briefly fills up with explosions and then calms down again. It uses a quick recursion to make the explosions chill out after a couple of booms.

Image


I had a lot of fun doing this and I want to turn it into some kind of screen cast or stream. I didn't end up recording it since I didn't want to really complicate the set up at the last minute. Running a live demo is already scary enough.

The full source code is available here. The assets needed are uploaded here. If I do a more full version of this talk I'll be sure to post it here!

Otter Surface Example

Otter Surface Example
Just a quick post going over how I usually use Surfaces in Otter. A surface is basically a render texture, or render target. The idea of calling it a surface mostly comes from Game Maker.

By default Otter will render all of the graphics to the main surface. However you can make your own surfaces and use them in various ways. The main point of this quick example is to show how to separate HUD elements and gameplay onto different surfaces. The big advantage of doing this is you can now freely rotate and zoom the camera and the HUD will be unaffected.

Alright let's check out the codes!
class Program {
static void Main(string[] args) {
// Create a new game to play.
var game = new Game();

// Set the scroll of the surfaces to 0 so they never scroll on the camera.
Global.SurfaceGameplay.Scroll = 0;
Global.SurfaceHud.Scroll = 0;

// Start the game with a new GameScene.
game.Start(new GameScene(1000, 1000));

}
}

class GridBackground : Entity {
public GridBackground() : base() {
Layer = 10;
Surface = Global.SurfaceGameplay;
}

public override void Added() {
base.Added();

// Just render a simple grid background so when the camera scrolls we can see it.
AddGraphic(new Grid(Scene.Width, Scene.Height, 40, 40, Color.Cyan));
Graphic.Alpha = 0.4f;
}
}

class Player : Entity {
public Player(float x, float y) : base(x, y) {
// Add a basic red box for the graphic.
AddGraphic(Image.CreateRectangle(20, 20, Color.Red));
Graphic.CenterOrigin();

// Assign this entity to render to Global.SurfaceGameplay instead of the default game surface.
Surface = Global.SurfaceGameplay;

// Set up a collider for movement.
var collider = AddCollider(new BoxCollider(20, 20));

// Set up the rest of the movement stuff.
var axis = AddComponent(Axis.CreateWASD());
var movement = AddComponent(new BasicMovement(400, 400, 30));
movement.Axis = axis;
movement.Collider = collider;
}
}

class PlayerHud : Entity {
public PlayerHud() : base() {
// Basic hud test with just some text.
AddGraphic(new Text("This is the HUD!", 20));

Surface = Global.SurfaceHud;
}
}

class GameScene : Scene {
public GameScene(int width, int height) : base(width, height) {
// Add the entities to the scene when the scene is created.
Add(new Player(HalfWidth, HalfHeight));
Add(new GridBackground());
Add(new PlayerHud());
}

public override void UpdateLast() {
base.UpdateLast();

// Set the scene's camera to follow the player.
var player = GetEntity<Player>();
CenterCamera(player.X, player.Y);

// Set the surface's camera to follow the scene's camera.
Global.SurfaceGameplay.CameraX = CameraX;
Global.SurfaceGameplay.CameraY = CameraY;

// Zoom the surface up and down with the arrow keys.
if (Input.KeyDown(Key.Down)) {
Global.SurfaceGameplay.CameraZoom -= 0.005f;
}
if (Input.KeyDown(Key.Up)) {
Global.SurfaceGameplay.CameraZoom += 0.005f;
}
}

public override void Render() {
base.Render();

// Render the surfaces.
Draw.Graphic(Global.SurfaceGameplay);
Draw.Graphic(Global.SurfaceHud);
}
}

class Global {
// Keep global references to the surfaces used for rendering the game.
public static Surface SurfaceHud = new Surface(640, 480);
public static Surface SurfaceGameplay = new Surface(640, 480, Color.Gray);
}
The full version is available on pastie.

I have a simple player class, and background class which both render to the surface designated for gameplay. Then the player HUD class is assigned to render to the hud surface. The scene will then take care of rendering both of those surfaces to the game's main surface. I render in the scene's Render method because that will be the very last thing that renders in the frame.

I know some people have been having trouble understanding surfaces fully and how to use them so I hope this example helps. Surfaces can be really powerful especially when you start getting into shaders and one of my main goals for Otter was to make using surfaces as painless as possible.

Otter Updates

Otter Updates
I finally merged in all of my pending changes into the main branch of Otter! If you've been using the dev branch for the past few months not much has changed, but things finally stabilized enough to the point where I felt comfortable updating the main branch.

Afterwards I've done some minor adjustments and fixes:

* Using Game.EnableAltF4 now checks for either Alt key on the keyboard.

* The RandomElement() function in NaturalLanguage now uses Otter's Rand class to ensure consistency if you're using a preset random seed.

* Added Snake.AddAllVertebraeToScene()

* Axis and Button keys, joysticks, mousebuttons, etc, are now public accessible.

* Renamed Button.AddButton to AddJoyButton.

* Axis and Buttons can now add keys, buttons, etc, from other Axes and Buttons. Useful if you want to copy a button or axis.

* GridCounter now has MoveUp(), MoveDown(), MoveLeft(), and MoveRight()

Slowly and surely moving towards a 1.0 version!

Dev Log: Menus n More

Dev Log: Menus n More
I've been jamming on Super Sky Sisters a lot these past few days getting it ready to show off during Game Developers Conference! I also had a good deadline for tonight which was our monthly Phoenix IGDA meeting. It's always a blast to see two people play the game together, especially if they don't know each other and if both of them have never played before.

I put in a bunch of new menu screens last minute, but so far they're turning out pretty well.

Image


Image


Image


I also added a better title screen that rotates screen shots of the game so that people kind of have an idea of what to expect before they push start.

Image


I should note that a lot of these menus are built for demo builds in public venues. I have some ideas of how I want to make the final menus that involves some more polish and artwork, but for now I'm just making the bare minimum I need for showing off the game.

Every time I code up a menu I always think "I should really look into using some sort of UI framework, or make a generic reusable UI framework!" but then I never end up doing either of those things. Otter does have some remnants of a UI system that I was working on, but that's so old and clunky now compared to my current style of coding.

I can never decide if it's worth coding with a UI framework or system especially for UIs that are all controller and keyboard based. Whenever I look into using some sort of framework it always seems like it's way too much for what I'm looking for, and a lot of it seems to be based on mouse interaction which is not what I'm usually doing in my games. If I ever end up with something cool though I'll definitely add it to Otter for other people to (try to) use as well.

Dev Log: Super Sky Sisters Screenshots

Dev Log: Super Sky Sisters Screenshots
Sorry about the silence on my blog lately but I've been pretty heads down getting a lot of stuff done on Super Sky Sisters, my two player action co-op game! I'm planning on having the game totally playable by the time the Game Developers Conference rolls around early next month, so I've been pretty focused on it.

Here's what it's been looking like lately:

Image


Image


Image


Image


I'm planning on going into a bit more detail on some things like how I'm rendering particles and the sky background for this game because I have some cool shader stuff going on. Also rendering those big red spiky blocks (or stamps as someone has called them) involves a neat shader trick as well. Back to work!

Dev Log: Otter Updates!

Dev Log: Otter Updates!
In case you didn't know I have a free to use open source 2d game making framework named Otter. It's built on top of SFML.NET and uses C#. Here are some recent changes available in the dev branch!

* Color.AddCustom() and Color.Custom() added. This is a handy way to define custom colors by Enum and later retrieve them. I didn't like making my own static colors class for each project to keep track of my custom colors, so I added some functionality to the Color class.

* BitmapFonts have been almost finalized. They should be usable now for the most part and you should be able to import fonts from a handful of different editors. You can check out what editors are supported in the class itself with the Enum BitmapDataType.

* RichText has been updated and fixed once again. I guess I've been doing kerning wrong all this time and I think I finally have it corrected. RichTextCharacters also have some new values to play with like their X and Y offset positions, scale and rotation and more.

* Added Enum.HasFlag() as an extension method. This is a handy way to check if an Enum with a [Flags] attribute contains a specific flag. I guess you can use this if you're not comfortable looking at the bitwise operators or whatever they're called (I sure am not!)

* Shader.AddParameter() is now available to register your shader parameters as an Enum. Now you can just define it once and use the Enum everywhere which should reduce pesky typos when working with shaders.

* StateMachine has been scrapped and StateMachine<> has been upgraded a little bit. It's now possible to use a stack of States in a StateMachine<> and it will run the top most state. Also now if you call ChangeState (or if you push and/or pop states) during a StateMachine's update function the StateMachine will wait until the update has finished before applying the state change!

* Fixed a typo in the Shader class whoops (SetParamter?)

* Surfaces now have their Display() function exposed. This is crucial in using a Surface that doesn't render at all, like if you're using a Surface as input to a Shader. Without calling Display() the texture will be upside down.

* Updated Collider and Entity and Graphics with more stuff like SetPosition(), SetOrigin(), and other handy stuff.

* Surface.SaveToFile() will now automatically save with a timestamp file name as a png if you don't specify an output file path. Handy for taking a bunch of screenshots during a session.

* NineSlice has some new utility functions like SetBorderPadding. I found it easier to define the areas of a NineSlice object in this way instead of trying to figure out what the bounds of the rectangle inside the texture was.

* RichText now will always round its origin since setting the origin to a 0.5f value results in blurry text!

* Fixed a bad bug in the PolygonCollider which resulted in the collider not using the transformed polygon for collision checks.

* Added 3D Audio support thanks to Fruckert.

* Lots of little bug fixes and tuning changes here and there.

Once again this is all available on the dev branch. I'll be pushing a whole bunch of changes to main branch as soon as I can sit down and write some documentation up for the new and changed stuff.