Cuboc – Ludum Dare Post Mortem
My last Ludum Dare post. I promise.
Design Phase #1 and Prototype
I read about the theme of the LD20 about 6 hours after it was announced. My first thought “woah, companion cube”. For me it signifies the one thing in game history that really fits the theme “it’s dangerous to go alone! Take this”. The word “alone” signifies to me that what you receive is actually something that is a companion, not just a mere tool like a gun or a shovel. The companion cube is both a tool and a “friend”. A silent friend, but a friend never the less.
The overall idea would be to have a companion cube (yes, how original) but deviate from the formula in Portal. While the cube serves pretty much the same purpose as in Portal, you are also able to control it directly. That makes for some interesting game mechanics atop of what we saw in portal. It’s also a way to ease the burden on the programming side as the cube would automatically follow the player which would mean a good path finder. Something i didn’t have time for.
Given this idea i settled for a puzzle platformer, where the protagonist was accompanied by a cube which he can control and anchor in the world for a given time. From there on i tried to come up with game mechanics. I spent 6 hours implementing the basics (protagonist movement & collision detection, cube following) to get a feel for everything. For this i had to settle on a unit system so i can give my game objects proper sizes and positions. I settled for the following:
- One unit in the world equals one meter. The protagonist called Bob is 0.8×0.8 meters in size (comic like proportions). The cube is the same size.
- The viewport into the world (the porition that is visible on screen at any one time) is 24×16 meters wide. Why? Because it is easily mappable to pixels as you’ll see in a bit.
- I settled for a mapping of 1 meter == 20 pixels. From this and given the viewport of 24×16 meters i derrived my target screen resolution, 480×320 pixels.
- With these measures i started pixeling the tile graphics, Bob’s animation cycles and the cube, all arranged in a 20×20 grid so i can adhere to the sizes chosen in world coordinates easily (e.g. 0.6×0.6m ~ 12×12 pixels etc).
I implemented Bob’s movement (acceleration + damping makes for some nice movement) as well as collision detection. The later turned out to be a problem and took me 4 hours. Once Kivan told me an easy way to handle it in my setting i was able to completel scratch and rewrite it in 20 minutes. The more you know.All in all i spent around 6 hours for this first phase.
In terms of language, tools and so on i settled for the following:
- Java plus libgdx. I wanted to eat my own dog food
- Deployment would happen as a single self-contained runnable JAR file. Easy to distribute, no installation required, the closest you can come to an executeable in Java
- Eclipse, cause it’s what i know best.
- For graphical asset creation i used Paint.NET. While i really like Gimp, it’s interface still turns me off and i find it a lot easier to work with Paint.NET’s more streamlined (but less capable) interface. Sadly it’s only available for Windows (not a problem for me).
- For the tile maps and object placement i also turned to Paint.NET. Objects and tiles are color encoded in a bitmap. Objects that span more than a tile are represented by a pixel indicating their starting position only. The rest is constructed during run-time.
Downtime, trying to give up
With this prototype i ended the first LD phase. I had a feeling that there was not enough time left for me to fully finish a playable game. I started on sunday, 1:30am GMT-2, so there were only ~27 hours for me to work. My woman and I planned to go to an HR Giger exhibition the same day. Let’s say she was surprised to see me awake at 8am in the morning in front of the netbook. I went to bed at around 8:30am and got up at 1pm. At that point i gave up on LD as i figured i’d only have 8 hours when i come back from Vienna (trip was estimated to take ~6 hours). Some impressions from the exhibition (couldn’t photograph the actual artwork).
The toilets in the Hundertwasserhaus are especially artsy fartsy.
Aliens with Penises and Tits, Phase #2
On our way to the exhibition we talked about the game in the car. For 2 straight hours. Steffi wrote up all the ideas we talked about. When we arrived in Vienna i had a full fledged game design in my pocket. I was psyched. I knew with this in my hand i could easily finish of a basic version of the game in the remaining 8 hours i had when we came home at 8pm. Here are the notes in German:
- Entry/Exit, use cube to open the exit.
- One or more cube dispensers/respawn points
- If there’s not cube in the scene, the last touched dispenser generates one
- Cube follows automatically
- Keypress activates cube control via usual means (w,a,s,d)
- Pressing the same key while the cube will return control to Bob, the cube freezes for n seconds and is collideable (useable as a platform). Once the time is up the cube follows Bob again.
- Bob can die in which case he respawns at the last touched dispenser. Same is true for the cube
- Spikes – kill Bob
- Lasers, vertical and horizontal – kill Bob, can be blocked by cube
- Moving Spikes, vertical and horizontal – kill Bob & Cube
- Homing Missles – kill Bob, blocked by cube
- Robot – kills Bob on collision, no effect on cube
- Shooting Robot – kills Bob on collision, shots blocked by cube
A sequence of levels was also losely defined:
- Introduce dispenser, cube & exit
- Introduce jumping and cube following
- Introduce spikes (no help from the cube needed)
- Introduce moving spikes
- Introduce non-shooting enemies
- Introduce spike pit only traverasble via the use of the cube mechanic
- Introduce shooting enemies and corresponding cube mechanic
- Introduce Lasers and corresponding cube mechanic
- Introduce homing missles and corresponding cube mechanic
- Be creative with the elements from here on
Back home i looked at this and was excited. I had 8 hours left, a very simple prototype and a full-featured plan. I started by prioritizing game elements. The doors went the way of the Dodo, they didn’t add anything to the game play. While they would be a motivator to keep the cube alive they were ultimately point-less: you can always get a new cube from the last dispenser, the only effect would be that you have to replay the level from start without any real benefit. Frustrating!
The enemies were cancled as well. I thought the other game play elements (spikes, moving spikes, homing missles and lasers) where interesting enough. I was also confident i could implement them all in the remaining time.
After some reordering of the level sequence i decided to have a single big level with multiple dispensers. Sort of like in VVVVVV. Continuous level for the win.
The level itself would be tile-based as said earlier. Objects would be encoded as pixels with specific colors, e.g. a dispenser would be red (0xff0000), a laser cyan (0xffff00) and so on. An object’s pixel would only signify it’s position in the world, not it’s extend. Lasers and moving spikes span multiple tiles in-game for example. I could easily derrive all properties during runtime given only their position, e.g. their direction and so on based on their surrounding.
With all this ready i started hacking again. And hacking i did.
Hackaton, Phase #3
Everything went a lot better then excepted. I added one game element after another. I set a time-frame for each feature and a sequence of implementing them. 7 hours to go!
- Cube control & following with Collision detection: 30 minutes, code is basically the same as the one for Bob in the prototype
- Spikes and collision detection & response: 60 minutes, this included respawn points, animating Bob’s death
- Homing missles: 45 minutes, this included spriting the rocket and an explosion plus the usual physics/logic implementation
- Moving spikes: 60 minutes, a simple afair of figuring out the direction based on the position & surrounding of the spike in the map as well as collision detection with the map and changing direction in that event
- Lasers: 80 minutes, basic setup as with moving sprites (figure out direction and end position of laser) plus some more involved collision detection with the cube (blocks the laser mid-way) and Bob. I knew this could get hairy but it turned out better than expected
- Screens: main menu, intro screen, game over screen: 30 minutes. I decided to go with a rather “make-your-eyes-bleed” single image per screen style which could be implemented quickly.
- Exit & Gameover state: 30 minutes. Another simple afair, just place the exit somewhere in the level and trigger a screen transition to the game over screen
- Level Design: 80 minutes. I wanted to have one continuous level. For this i made a special respawn object that let’s me test different chambers immediately on the go. This system let me test a specific chamber immediately. I just moved the object around the map when i created a new room. This way i could generate a level that takes an average player (Steffi) around 6-7 minutes to complete. Not a lot but enough for my needs.
As you can see in the timelapse i could stick to that schedule pretty much 100%. The final packaging took about 5 seconds. Export -> Runnable Jar.
I delivered the submission at pretty much excatly 4am local time, a spot on submission so to speak.
What went Well
- The decision to use a bitmap to encode the level information was a good one. I did not have to battle any editor i wasn’t familiar with and could make up new encoding rules on the go. Previewing was also painless and always only two keystrokes away.
- Since i decided to eat my own dog food in form of using libgdx for this i was curious if our design decisions would hold up in an extreme situation like Ludum Dare. Thankfully the framework never got into my way at all. Everything i needed was in place, from input handling to rendering and some math & collision helpers. Of course, the game is pretty simple so i did not have to make use of any of the more advanced facilities in the framework. Never the less it turned out to be extremely simple to work with.
- Having a full design is something i can’t state the importance of enough. Seriously, if you enter something like Ludum Dare, spent enough time to make everything watertight. It’s so much easier to work from a design then to make up shit on the go. Of course i first prototyped before i went full-design-metal. Once you know your prototype works start designing, not coding!
- Paint.NET is a joy if you know all the keyboard shortcuts. I was able to pull of all the asset and level creation in no time.
- Having ~20 people in our IRC chat was valuable as well. I had some test slaves and some of the folks could even give me tips on how to approach the fsm damn initial collision detection problem (never did a platformer before…). Thanks Kivan!
- The schedule was also very helpful and allowed me to make the deadline. It would have been very easy to get sidetracked with a small detail otherwise. Keeping my eye on the clock was a “good thing” and mostly responsible for me making the deadline.
What went Wrong
- Having done some rather elaborate math and computational geometry in the past i thought that the collision detection for a simple platfomer would be a piece of cake. Not so. I spent full 4 hours out of the 13 hours total to get Bob to correctly react to his surrounding. That was rather embarassing as i thought i was knowledgeable about most game development stuff. The more you know! A humbling experience.
- Due to me starting on the second day and spending a good 7 hours on none Ludum Dare related things i was really short on time. I think i could have created something a lot bigger if i’d used the full 48 hours.
- Sleeping for 4 hours is useless. Sadly there was no other option. I really wanted to see the Giger exhibition and spent quality time with my woman. Note to self: sleep at least ~8 hours before and dacuring Ludum Dare!
- I did not have time to include sound effects. Which is funny cause i really think sound makes up 30% of a game easily in terms of immersion. I’ll do better next time (sfxr & my own sequencer to the rescue!).
- The level design is very basic. I underestimated the time needed to come up with something fun and engaging. I think the basic game mechanics and elements would allow for a pretty decent game. 80 minutes are simply not enough to explore the full potential of the game. Spent more time on this item the next time!
- The game is controlled by w,a,s,d and e. It was my goal to keep the controls as simple and intuitive as possible. To bad i forgot to add an option to “unfix” the cube. At the moment it will stay fixed for 5 seconds which can disturb the overall flow quite heavily. I didn’t think of letting the user press e when the cube is fixed so it starts following again. Oh well
I haven’t written a single “real” game in over a year. The three games i wrote for the book felt a lot like work due to the time pressure, so i don’t count them. Hacking away on libgdx, while game development focues, is not the same either. I nearly forgot how enjoyable game development can be. So, thanks Ludum Dare you reminded me why i do this