Ludum Dare 22 Post Mortem
December 2011 – Game: Fernands War.
Last year I found out about the Ludum dare competition and was really interested in doing something, unfortunately I didn’t have the weekend totally free to commit to making any real attempt, but I managed to crank out a tiny little endless runner in a couple of hours and catch some of the live recordings (Notch’s one mainly). It was interesting to see the fruits of every-one’s labours, and the community spirit here is really inspiring.
So as I hadn’t managed to make a decent attempt last time, I had planned to jump in properly for LD22. In preparation I had made all the necessary requests for that 48 hour period to be free and started thinking about the tools I would use to make the game.
Physmo is a 2 man team, I do the art and design and @physmotone is the chap with the coding skillz. We had talked a bit about entering the jam as a team but were struggling to both get the time off we needed so I planned to enter solo. This meant coding the game myself; I am a programmer but I’m certainly no game programmer so I realised this would be tough. I’m sure Tony would be shocked by all the fundamental coding mistakes I made while making my entry, stuff he has the experience now to avoid, but I learned a lot doing this, especially about the architecture of making a game, the game states, resource management etc – all that tricky stuff we can take for granted sometimes.
In the week before the theme was announced, I decided I would choose Java as the language, and Slick2D as the graphics library for drawing the sprites (It also does a great job of loading graphics, sound and level data.) I’m not a java programmer but it seemed close enough to C++ to be easy to pick up, but mainly I wanted something that would be multi platform with the vague possibility of embedding in a web page (this didn’t happen). I didn’t know what kind of game I’d be making but assumed it might need level data, and I had heard of a map editor that was supported by Slick2D called Tiled, so I downloaded that and made sure I knew the basics of how it worked. In the prep week I didn’t find as much time as I would have liked to do actual prep but I did get a few hours to find some java tutorials and create a small test application that demonstrated loading and displaying sprites, loading and playing sounds and reading a Tiled level. I didn’t want to waste much of the 48 hours being stuck on some trivial problem like not being able to draw a font to the screen so I investigated the font libraries too (Angel code fonts I think it was). I had the small test app running, the final thing on my list of prep was to actually package the program to be runnable on other computers.
This was a couple of days before the announcement and I could not for the life of me package this thing properly. Eclipse is the IDE I was using and it’s pretty complicated if you don’t know it, and I had no idea about how to create Jar packages (which is what I needed to make the thing runnable). I tried every combination of including the platform specific .dll files, the library .jars for Slick2D and LWJGL, and did a lot of googling for the problem. Fortunately (?) many novices seem to have a problem with this step, and in the end I reluctantly tried using another app to package all of the files up into a fat jar, which worked. i say reluctantly because even though it worked in the end, I still don’t have a good understanding why it didn’t work and why it does now, but hey, it works! This was a real problem just before the compo started though. If I couldn’t find out how to package the game, there would be no point in working on a game. I would heartily recommend anyone taking part in a time limiting game creation competition to build a full app end-to-end before they take part.
The graphic and audio tools were to be Photoshop, SFXR (of course) for sound effects and Audacity in case I needed any sound effect editing. In the end I did install audacity in the final hour to tweak the ship thruster sound effect but that’s all.
I’m in the UK, so the announcement came at 2am our time. The plan was to stay up for the announcement, have a think about it and then get some sleep.
The theme is announced. “Alone”. I stare at the screen for a few minutes. My first thought is, “Well at least I won’t have to code any enemy AI”.
At Physmo we have a folder full of crazy game Ideas and prototypes, but we have never really considered a thrust style game. I used to like thrust style games though, and I though it would be within my skill range to make a good attempt at one. Quite soon after the announcement I had come up with some ideas for a decent plot – I wanted to have some narrative in the game that would be explained as you play and I really wanted to have a good twist in there too. I had my general story Idea and style of game I wanted, I could now sleep (and secretly hope to come up with good ideas in my dreams).
Oh, this post mortem is going to be a total spoiler for the game, so please play it first if you intend to… I’ll give you a couple of minutes, just watch out for the spinning sawblades, the collision on them is a bit saucy.
For the plot of the game, I wanted the player to have unwittingly done something really terrible. This idea made it into the final game but was very scaled back. The initial idea was that you would be flying a ship around a room with some kind of reactor in the middle, there would be a cage full of energy capsules milling around that you would have to pick up and drop into the reactor. At some point you would realise that this is not the true reality of the situation, the reactor is actually a horrible mind controlling alien, the energy capsules are really other human members of your crew and the alien has tricked you into feeding your crew to it.
This was the plan until the end of day one, I didn’t think I would have time to code the mechanics for all this, the switching level graphics, picking up and dropping the crew etc, so at the start of day 2 I decided to change it slightly so that you were a security guard of a mining colony, who was going mad. It seems like at first you are being attacked by aliens, but as you progress through the game you can read log files that gradually explain that the aliens are really just the colonists, and by the end of the game you will be alone, having killed them all. It’s nice to end on a cheery, up-beat note.
It was time to start programming. But first I went to my trusty Photoshop and drew some sprites: A yellow ship, some bullets, some white splodges to use as particles and a simple tiling foreground and background tile sprite. The spaceship made it into the final cut of the game with no modifications as I quite liked it. NOW it was time to start programming! First I needed some classes to represent the ship, bullets and enemies. That’s what the game needed, they are an integral part of the game. You can’t have a game without them. That’s why, like an idiot, I spent the first couple of hours making some pretty particle effects.
Ok, Basic particle engine created, I now really HAD to start creating the game objects. I found a nice tutorial about creating game entities, and then creating generic behaviours that could be inserted into them, this seemed like a cool Idea and one I had never tried before so I gave it a shot (I’ll try to link to these tutorials and things at the end of the post). After stealing the code to create the framework of the entities, behaviours and renderers, I derived my own object classes for them, starting with the players ship movement code. This was easy as I had used some basic maths like this a lot in some processing toys I made a while ago. It’s useful to know so I’ll write it out here:
Horizontal Thrust = sin(ship angle of rotation) * force;
Vertical Thrust = cos(ship angle of rotation) * force;
So everytime the thrust button is pressed, I add these values onto the ships velocity on the x and y axis. Every time through the game loop, I add the velocity vector to the ships position, and that moves the ship. And at the same time I dampen the ship’s velocity by multiplying it by a number slightly less than 1.0 (0.98 or something). That reduces the ships motion over time and eventually makes it stop in a pleasing way.
Ok, next big problem. In my processing (processing is a simple java-like programming language) experience, the main loop is locked to a certain frame rate, but in the Slick2D framework it isn’t. This means the loop runs as fast as it possible can – maybe hundreds of times a second – but it will vary from computer to computer and will vary depending on how much is being drawn on the screen too. To handle this, the update loops are passed in a variable that represents the number of clock ticks that occurred since the last update, and using this I could feed it into all the motion equations. Essentially, every calculation that results in something moving on screen needs to be scaled down by the number of clock ticks, so that the movement is nice and constant. I forgot to do this to the scrolling routine though so sometimes the scrolling can be a bit slow if your machine is struggling. That’s a bug but would be easy to fix.
I now had a ship swishing around the screen nicely, with lovely particles firing out of it’s bum (and me making “woosh” sounds) so I flew it around the screen for half an hour thinking how awesome I was to have achieved such a thing. Next I needed some background to be drawn. The Slick2D libraries can load and display level data from Tiled map files, although they couldn’t handle (as far as I could tell) drawing level sprites scaled up, but it was quite easy to parse through the loaded level file, find what tile is at what location and draw it scaled up myself. I got this running surprisingly quickly (well it wasn’t very complicated) and then added some scrolling offset code, and voila! I had a ship flying around a scrolling level. Flying right through the walls though. Next step was to detect collision on the walls, so I wrote a routine that given a point in the game world, would find the foreground level sprite, and check if the pixel was filled or not. It worked and that is the basis of all the collision in the game. To collide the ship off walls, I check around 10 points in a circle around the ship to see if they are touching a solid part of the background. If they are, i calculate the vector from that point back to the centre of the ship and add that to the ships velocity, I was amazed that this works but it resulted in some pretty solid feeling collision (I was worried that the collision would be awful in this game) so maybe this is what real collision is based on.
I created some simple behaviours for the player bullets that I reused for enemy bullets (The entity system worked well here) then I added some basic enemy types. I regret not having the time to make the enemies do more, but in the end I just had static enemies that varied in the speed that they fired bullets at you and the number of shots it would take to kill them.
I added a lot to the game in the last half day, as the main mechanics were there. Different sprites for the enemies, more particle effects and the log file objects that can be picked up. Some trivial looking things took more time than expected, for instance displaying the log file text on screen and making the rest of the game pause while it was displayed. At this point I realised I would have to start thinking about game states, so I changed the main class to be a state based game state using the Slick2D libraries and created another state for the main menu screen, then worked on getting this to transition back and forward and make sure that the player could die and the game would switch back to the main menu. This is something I wish I’d thought about a lot more at the start as game states are a tricky thing to to if you aren’t used to it.
Panic was setting in in the last few hours of the 48, there was a lot to be tidied up. The collision between bullets, player ship and enemies was quite off so I modified the renderers to display the collision box and that helped me track down and fix the issues there. One big problem that I regret not fixing is that the hit-boxes for the circular saw blades is a square, not a circle and this makes for some really unfair deaths in the game. I realised I had no time left to fix this so I modified the level to move the saws and give the player more room to move around them, still it’s disappointing to get unfairly killed by them.
The game was looking quite finished, all the log files were placed and the end could be reached, but it was quite hard, so at the last minute I made the players health slowly regenerate over time. In the last half hour I feverishly added a lot of minor details: The player health bar, more particle effects for killing enemies, more sound effects and a dodgy system for playing the ships thrust sound. Panicking further, I played through the game one more time and hit the build button to build the final Jar file, and opened slick jar (i think) to package it up into a runnable jar file. With minutes to spare I clicked the Jar file and it seemed to work, phew! Opened my web browser, and went to www.ludumdare.com …… wait a … WTF .. oh MAN! Why is the site not working! Through lack of sleep and burnout I thought all was lost, I refreshed the site and still nothing. Thinking that all was lost, I gingerly climbed onto the window ledge, and, oh wait, the site loaded! Wheee! Well, at least, I saw a message from the site saying they would accept entries for an hour or two after the closing time. I eventually uploaded the game and could relax, but those last few minutes leading up to the deadline were some tense minutes let me tell you.
In closing this rather rambling post, I did enjoy the experience. I think I made a decent, complete game that I hope you enjoy playing – it’s quite short. I’ve learned a lot about what should be prioritised next time, and I feel like I was part of something big and crazy 😀
Please try it, it’s called “Fernands War” http://www.ludumdare.com/compo/ludum-dare-22/?action=preview&uid=5349
We have a full game called Mos Speedrun too, for iPhone and Mac/Pc, you might like it.