Your Story Postmortem

Max WilliamsOct 15, 2011

uDevGames 2011 Entry

  • 3rd place Overall
  • 3rd place Gameplay
  • 2nd place Audio

Overview

Your Story is a 2D platform game created for uDevGames 2011. It took third place overall and scored highly in gameplay, graphics, and audio. Max Williams and Scott Lembcke made it in three months’ evenings and weekends.

Cave Story was my main inspiration for gameplay. The game has three large areas, with a few smaller junction areas. There are two types of enemy to fight and two weapons you can use. There are collectible items which can unlock a secret ending.

Level data is stored in tilemaps, with collision geometry being automatically generated from the tiles’ alpha channels. A level can have multiple layers of tiles, with one layer being interactive and the rest decorative, in the foreground or background. Layers can be drawn with parallax.

The graphics are handled by OpenGL. Quads aren’t drawn immediately; textures keep a list of vertex data which game classes can add to. Then at the end of the frame each texture draws its data. We used OpenAL for audio, playing Ogg Vorbis files created by sfxrX. The project was written in Objective-C.

Decisions

There were a few tricky design decisions to be made early on.

Tile-based levels

There’s no technical need to use tiles with today’s hardware. They do have a ‘retro feel’, but that’s not the main reason I chose to use them. It’s because it breaks down the artwork into manageable 16×16 chunks. Scott was confident that we could easily cope with large freeform levels, but I’d have found working on a blank canvas overwhelming. The sixteen pixel grid makes everything less scary.

It did mean that I had to write an editor, instead of being able to just paint levels in Photoshop. I ended up with something that was reliable and useable, but quirky and missing features – I spent a lot of time manually flood-filling areas or replacing random tiles with alternate versions.

Chipmunk physics

I had used Chipmunk before, but I wasn’t sure about using it for a platformer. Cave Story physics has little in common with Chipmunk’s default behaviour, and it takes a good amount of work to get it to feel right. I went with it anyway, and planned to make the game use only vehicles if I couldn’t get the character working how I wanted. Luckily when Scott joined in he got it working perfectly; I can’t think of any improvements I’d want to make.

Using a physics engine did mean we had to solve a few extra problems. At first each tile had its own collision shape; and the character would catch on the cracks where they join. Scott’s auto-geometry code solved this one for us.

Retro style

We drew everything to a 340×280 framebuffer and scaled it up to the user’s window size using nearest neighbour sampling. This is a quick and easy way to keep everything sharp, and it suits the style perfectly. I used a 256 colour palette to make all the artwork, and textures were loaded as RGBA5551.

I think this worked out well. These constraints make things easier rather than harder. For everything on screen I had fewer decisions to make, and fewer options to choose from. It forces you to put the same amount of attention into all the artwork, because any shortcuts you might use in other styles look out of place. Layer styles and filters aren’t any help here.

This style does make errors more visible. We had to take care to make sure the player and enemies sat pixel-perfect on top of the ground. To stop them from occasionally overlapping we had to run the physics at 120FPS.

What Went Right

Fun extras added last-minute

Just before the submission deadline I scattered eight collectible coins that were tricky to get to. It took maybe an hour to make a sprite for them and put them in good places, and another hour to keep track of the number collected and display them in the UI. Collecting all the coins gets you to a slightly more satisfying ending.

Towards the end of the voting period I added a timer, and a completion screen that reported your time. This is great for speed runs. It doesn’t store local or online high scores, but it seemed to be a popular addition and I really enjoyed hearing how quickly other people had managed to beat the game.

These features were quick to add and I suspect they contributed to our gameplay score. Considering how close the results were, that probably made a big difference.

No sentimentality about features

We had an ambitious feature list, and many things on this list didn’t make it into the game. I think we were both realistic about this, and we were quick to determine what should be cut and what could be quickly made into something that adds value to the game.

The lighting is a good example of this. We had planned to have lights casting shadows from geometry, similar to the effect in Twilight Golf. We ended up with a much simpler system, but one with a lot of value – it adds tension and challenge to the dark level, and it looks great in the last level.

No premature optimisation

I finally got this right. There are many areas in the game that aren’t as efficient as they could be, and I’m glad that there are. I did spend some time rewriting areas that were too slow, but I’m sure that I saved more time than I lost.

No placeholder art or sounds

I’m not sure if this is generally considered to be a good thing, but it worked for us. Enemies were never drawn with placeholder art; I created art for them at the same time that Scott did the AI. Even small details such as eye movement was important right at the start, because I knew if I left it until the end it wouldn’t get done.

This meant that there was no big rush at the end to go over everything redoing all the artwork. I think that might have required more discipline than I had.

What Went Wrong

Difficulty

Most people found the game difficult. Most platformers have easier levels towards the beginning, but I’d unintentionally done it differently – a hard jumping puzzle, a hard timed exploration section and finally a hard fighting section.

I find the game very easy, probably because I’ve played it so much. But I’d recently been playing Cave Story’s secret final level, which perhaps clouded my judgement. I shouldn’t have expected people to invest time in a game before making it clear that it would be worth it. I made it easier before the end of the voting period by adding checkpoints, but people were still having trouble before they even reached them.

Part of the problem was that I didn’t make the objective clear. People are used to killing everything they see, but in this game it’s easier to avoid as many enemies as you can. If you try to kill everything you can become frustrated with the limited power of the weapons.

Effort

I spent too much time on the game. I love the end result, but I was programming all day at work and then doing another few hours on the game when I got home. While I’m glad to know that I can get something like this done in my free time, it’s not something I’d want to do often.

I’d happily enter shorter contests, or perhaps do something other than programming next time.

Playtesting

I’ve never watched anyone play this game all the way through. We got some helpful feedback through the forums, but most of our decisions were done to suit ourselves rather than anyone else. This let us develop more quickly, but I’m sure it cost us in other ways.

Conclusions

I’m really pleased with how this game ended up. I’m not going to make any promises about future development; I’ve had enough programming for a bit and I think the game is nicely complete in its current form. But I think there’s a lot of valuable code in there which I might be tempted to use again in another project.

I’m grateful to Scott for his participation; working in a team is great motivation and without his help the game would have been very different. Thanks very much to everyone who gave feedback during development, and to everyone who voted so generously.

uDevGames was great motivation and a lot of fun. I’d recommend contests like this as a great way to push yourself to get something finished. Thanks to everyone involved.