Data Entry Sentry Postmortem
Having just released The Last Rocket I wasn’t sure I had the energy to participate in this weekend’s Ludum Dare. But looking back on the last one I remembered what an enjoyable (grueling) and reinvigorating (exhausting) experience it was. So about an hour an a half before they announced the theme I decided to do it. You can play the result, Data Entry Sentry (looks best in browsers that support the CSS3 image-rendering property, like the Webkit Nightly, but plays best on the iPad), or continue reading for the postmortem.
This time the theme was Escape!. Like last time I came up with three ideas and slept on them before starting any work:
- Farmbreak!: You place obstacles to prevent animals from escaping their pens. Different animals have different abilities (ram, jump, burrow, fly) and each requires a different type of barrier to contain. Yawn.
- Escape from Zombie Hall: Sort of a Space Invaders/Smash TV mashup. A first-year dorm resident of Zombinski Hall is trapped in a zombie outbreak. In the first part of each stage the player moves left and right blasting back the oncoming zombie horde with a shotgun (Space Invaders). One zombie is holding the key to the exit which is behind the player. When that zombie is blasted the key pops out and the player must rush in with a 360 chainsaw attack (Smash TV), collect the key and make it back to the exit in one piece. The only thing less inventive than a clone plus zombies is a clone plus ninjas.
- Data Entry Sentry: Can you make a game about escaping data? Can you make it fun? You can certainly try. Chunks of data slide down multiple conveyors towards a parser and buffer. Some of the data chunks are gremlins. If a gremlin hits the parser it eats all the data between it and its pair. The goal is to fill the buffer without overflowing.
Waking up Saturday morning, Data Entry Sentry seemed the most interesting, unique option. So where do I start? For my first Ludum Dare entry, Breathing Room, I used Flixel. I’m really not a fan of keyboard and mouse games and really enjoyed the simplicity of tapping in The Last Rocket. I wanted to make a game that I could play on the iPad. So Flash was out.
The framework is pretty simple (view source on the game). The primary class is Surface which can have a parent and children Surfaces, has a rectangle for size and position and knows how to render and update itself. Surface is meant to be extended but is also useful for grouping elements at a given zIndex. The GameSystem class extends Surface and is responsible for creating the canvas element and is used as the System singleton so that the Texture and Rectangle classes can draw to the screen. An InputManager class is used by other objects to register to receive input events. Everything else extends Surface. State automatically takes the dimensions defined when initializing GameSystem. Rectangle draws colored rectangles. Tile draws individual tiles in a tilesheet. Wallpaper repeats a single image. SurfaceY is just a Surface that sorts (and renders) its children by y coordinate instead of zIndex.
By the end of the first day I had an ugly, playable prototype. By noon on Sunday I had a design and simple animations I was happy with:
One of the trickier elements of the design was the level numbers. Because of the perspective, the tens and ones columns require two different sets of numbers. I created a special LevelNumber class to properly render the text from a tilesheet containing numbers drawn in both perspectives.
The remainder of Sunday was spent rewriting PlayState to use the new Chunk class and integrate the graphics and complicated zIndexing and stacking behavior. The bulk of the game logic lives in the PlayState update method. Chunks, a subclass of Surface, are moved between different Surfaces (conveyor, stack, Chomplies and dying) and behave differently depending on which Surface they inhabit. Initially this was done as an easy way to manage Chunk zIndexes but ended up being really useful for implementing the behaviors unique to each section of the game board.
As an aside, in The Last Rocket, instead of subclassing subclasses of Surfaces and adding behavior I have an Entity class (which has a little less overhead than a Surface) that has one or more Surfaces. States then iterate over entities which are responsible for the behavior of their Surfaces.
If I had more time I would have liked to create some 8-bit tunes and sound effects to complement the graphics but HTML5 audio still seems to be a tricky proposition on iOS.