DoomDrive Postmortem

Posted by
April 21st, 2009 1:06 am

Since I want to learn to write good blog posts, I would appreciate any feedback about which parts of the following post you found interesting. I tried to make it not dull. Hopefully you’ll learn a couple of new game design tricks or something. And if you’re not a programmer, just ignore any code, you won’t miss much.

The wiki mentioned that I should keep a log of some sort as I develop my game. I decided to write short entries in a txt file, then thought I would post it all when I was done. Now that my game is finished, I thought it would be a good idea to expand this short log into a full commentary-type thing of my Ludum Dare 14 experience. I will describe the development of DoomDrive in detail in the hopes that someone will find this interesting. Maybe this will make up for not doing a timelapse. Note: In this post, all times are EST and entries from the original log.txt file are italicized.

SF’s devlog

The first real language I learned was C++, I started learning it at age 11 when my older brother gave me a book about it. I didn’t know anything about compilers then so I couldn’t even write a program until much later, but I absorbed the information with great interest anyway. I love C++ for its speed and the amount of control it gives me over my code. When choosing graphics and sound libraries to start learning I did a few comparisons and settled on OpenGL with GLFW helper tools, and OpenAL. I haven’t had too much trouble with these (though my OpenAL knowledge is limited) and they’re what I know best so they’re what I used to make DoomDrive.

Car sketch

Saturday morning (18apr09)

2:40 – Forgot about LD for the past couple days, remembered it just now.
The contest began at 23:00 on Friday, so it was 3:40 in. I had decided to start developing a game (unrelated to any contests) a week before. It was to be my very first serious game (a space shooter, heavily inspired by the rather obscure Hell Fighter). I’d done enough half-projects experimenting with the aspects of game design – code structure, physics, graphics, art, sound, game theory, etc – that I knew I had a good grip on making games… I just hadn’t done it yet (other than a GameMaker game I made at 14, and of course Tetris). My problem was I never felt like doing anything. But over the past month I’ve been working on my mindset and setting clear goals and all of that personal development nonsense, so I finally felt ready to begin coding my first game ever. I did. Then I found out about Ludum Dare from browsing java4k-related stuff, realized it was gonna be the next weekend, and wondered if I should try it. I voted on the first three rounds, still unsure if I would participate, then kinda forgot about LD as I concentrated on coding my space game. I remembered it at a convenient point in time, thought “now or never”, checked out the theme, and immediately started thinking up ideas. Well, it didn’t take long to come up with one…

3:05 – Idea: Drive a 3rd person 3D car around a forest and ramp off rocks to get away from the wall. I haven’t done much 3D in OpenGL. I will most certainly get stuck on bugs until it’s too late. Whatever.
My conceptual vision also involved pools or rivers of water that you had to jump over by driving off cliffs. It just seemed fun in my head so I went with it. I was a bit pessimistic about it. It might have been because the idea of making a game in 48 hours sounded so absurd; I always thought a decent game would take at least a month to complete. More probably it was just a safeguard against being disappointed when I failed to live up to high expectations for myself.

5:05 – Should I sleep? I hand-coded a car model and not much else is working yet.
My idea meant mostly procedural, randomly-generated content. I love procedural, but the car model would have to be designed by hand. I began drawing it out as soon as I picked out the idea, because that seemed like the most natural thing to do at the time. Since it was so simple, I just punched in the numbers in a const array, remembering to keep vertices of quads in clockwise order (I later found out counterclockwise is preferred). The model (and the game idea in general) was probably influenced by Twisted Metal 4, a PSX game I played a LOT as a kid. My favorite car was Orbital.

Ambient lighting effects

Check out those ambient lighting effects. I chose these colors in GIMP. I thought the car should be a different color but the light gray sorta stuck.

5:30 – I’m making elementary math errors because I’m sleepy, so I will rest before continuing the game. Night.
I think this was when I was trying to figure out OpenGL lighting. I dunno why I did the most graphical parts of the game first, probably because it was what I would have to look at for 48 hours, and it’s more fun to code a pleasant-looking game. I never programmed lighting before but I figured I only needed simple stuff so I could learn it in time. I seem to understand complex ideas pretty quickly, at the expense of poor memory of concrete information, like names of functions, or the fact that Ludum Dare starts today. I think it helped that I slept twice during the compo, so that I worked for what felt like three days instead of just two. The best ideas happen in bed, and I like to think my brain is subconsciously thinking about things while I sleep.

Saturday

13:20 – I AM UP! I’ve been coding in my dreams all night long, let’s see if that helps me any.
That night I had the odd experience of watching a half-dream where a programming problem appeared as code before my eyes, and I solved it without consciously thinking about it. I think it was a premonition.

Incorrect lighting

This seems incorrect somehow.

16:20 – Stuck on a dumb lighting problem like I expected to. Losing motivation. I’ll just ignore the problem for now.
17:05 – I couldn’t ignore it. The problem is lighting needs normals that I haven’t worked with much and mine are kinda wonky.
I made the mistake of trusting some lighting tutorial example code that seemed wrong at first. Wasted too much time on this and felt dumb afterward. I never did get directional lighting to work, which would have made sense since I wanted sunlight. I just did a point light that’s a fixed position from the camera. It looks about right. I didn’t even bother with specular or smooth shading, I knew I wanted the simple flat look when I first thought up the idea.

XYZ arrows are colorful

MERRY XMAS! Note: This screenshot does not demonstrate proper debugging procedure, don’t try to understand it.

Foggy hills

Yeah fog! The car just hovers so far. I made a hazy sun by rendering the inside of a huge cone a fixed position from the camera (like a skybox) with the center almost white and the edges sky blue.

17:50 – FIXED IT! Now on to making game mechanics.
I believe I was messing with the car speed and turning and friction around this time. I obsessively tweaked these throughout development, up until the very end. I’m glad I did because the controls contribute a lot of the feel of an action game, though I still think it could be made more fun. You’ll find that I left in the code to tweak game constants if you press a number key or insert/del/home/end/pageup/pagedown and look at the stdout. I did something like “float SPEED=tweakvars[1];” in the game loop, ran the game and adjusted the value with those keys, and when I settled on a value I changed tweakvars[] to initialize accordingly. It’s a primitive system but it did the job.

Impaled car

The entirety of my collision detection code:
car.z<groundHeight(car.x,car.y)

19:10 – Well, at least it looks fancy. I’m gonna eat dinner.
21:20 – Time to figure out perlin noise terrain, then I will have awesome screenshots. My morale is back up and I’m doing way better than I expected, although I don’t think my forest is gonna have any rocks or trees. It’ll still be fun to drive around hills.
By this time I had a fairly clear vision of where my game was going.

21:40 – I’m humming tunes. I hope I don’t go insane from non-stop coding. I will listen to noise music for a while. I don’t know if doing that has any mental effects that are beneficial to programming games, but noise usually helps me clear my head.
Also tried trance. It seems to help at first, but becomes a distraction once I’m in the zone. I took a reasonable amount of breaks, but other than that I had been coding nonstop that day AND the day before (my space game), so I was already getting worn out.

Scratch work

Here you can see me trying to figure out vertex orders and terrain slope calculations. This is just scratch work so it’s probably wrong. I only write in cursive so people can’t read it at a glance (it’s actually less efficient than print).

22:35 – OH SEGFAULTS! My goal is to finish the terrain and the car “physics” before I go to bed so I can add the actual wall and maybe a little sound tomorrow.
Spoiler: The car is actually a single point. It does physics by controlling z height based on things like slope of the ground at x,y – the game is essentially 2D. The terrain is an array of z values. The car is either on the ground or flying. When not flying, the point follows the slope of the ground. When it crosses an edge between triangles, it checks the angle at which it hit, so that if the ground is curving up the car slows down, and if the ground is curving down the car ramps off into the air. However, there’s a problem in that this angle checking doesn’t happen when you land (only when you drive across an edge), which means if you’re flying and you land on the very tip of a hill, your forward velocity will not be updated to account for it, and you will get pushed up the slope way too fast, causing you to fly really far. This is a gamebreaker that I intend to fix in a postcompo version. (Note: The physics are actually an inaccurate fudge I came up with by just guessing at how the car should behave, and adjusting it to be playable. The postcompo version will be much better.)

A beautiful view

The game doesn’t change much visually from this point on. Though I wanted to tweak the colors at the end, I didn’t have time and decided that was just polish for the postcompo version. Blue ambient with orange diffuse light worked pretty good. I noticed from using Hammer (the HalfLife 2 map editor) that shadows should be rendered blue (not gray) when sunlight is yellow – complementary colors.

00:05 – EPIC SCREENSHOTS! Just the car physics left now.
You can see that the procedural terrain gets generated as you drive. It’s stored in a 2D circular buffer, which was a little confusing to figure out how to do, but is very efficient (a single array on the stack). Random hills were accomplished with perlin noise. I made some with varying roughness factor (using perlin noise to vary it) roughly in the range 0.0 to 1.0, raised it to the fourth power to flatten out low areas (fourth power is called “quatric”), and of course scaled it to a proper height. The noise function returns a random value seeded by x and y position, so the infinite terrain stays the same every time you play. I figured if it changed all the time people wouldn’t be able to make maps of the best routes. No, no one would be that dedicated. I hope.

01:20 – But I mess with the camera instead. Getting sleepy.
The camera was another thing I tweaked all throughout development. My photographer side definitely had a hand in this. But again, I’m glad I worked so hard on it, camera problems are frustrating and awkward for the player. What bothers me is that you never get to see the awesome epic wall of fire in all its glory until you die, unless you turn around like I did for my official screenshot, and there’s no reason to do that. I considered adding a rearview, but what’s the point if it’s only there for looks? Maybe I’ll add an attract mode that shows the wall from a better angle.

02:10 – Decided on “Doom Drive” for the name. Physics will have to wait til tomorrow. I am falling asleep. Night.
04:10 – Ate, washed, went to bed, couldn’t sleep, but got some ideas. I always get ideas in bed. Ideas: I will reward airtime with a proportional amount of boost. The terrain will get more and more intense over distance, as a difficulty curve.
I knew I was going to bed way too early, but I was so tired of coding that I thought I’d fall asleep right away. I’m glad I got the boost idea because until this point the game was about finding the flattest (most efficient) route, and I wanted it to be about RAD AIR!

Why am I floating

Why am I floating

05:05 – My car is floating aughhhhh oh no
05:25 – YEAH GRAVITY!
In my exhaustion my log entries have degenerated into basic feelings about what was happening at the time.

06:30 – God, there are so many bugs with driving backwards and stuff. Hmm, 16 hours left. Going to bed for real now. Night.
If you’re gonna use something like negative velocity values for driving backward, make sure to REMEMBER that when you do calculations. It can get frustrating to get stuck on a bug where your car falls through the ground when you drive backward. Humorously, before I added flying, gravity, and fixed the backward movement, the game played a lot like Big Rigs.

Sunday

14:40 – Slept nicely. Final stretch, here we go.

Concept art

Worst concept art I’ve ever drawn. The music was actually gonna be just a repetitive trance beat, but making that sound good procedurally would take way too long for me, as simple as it is. I’m really sad I didn’t get to adding scoring, at least a timer, but I thought it would require displaying fonts, which I didn’t have time to figure out when I realized I had to.

Burninated! This is the first firewall (looked less refresh linesy in-game). Here the fire looks like crap because it’s a lit material instead of a plain color. Fire isn’t supposed to have shadows on it.

16:55 – Finished the firewall and boost mechanic. If I add a HUD and tweak the wall speed I will have a working entry.
19:35 – Woo, it’s playable! I will add boost effect and cam shake for fun, then submit.
DoomDrive has three kinds of fire: the enormous wall of destruction, the boost flames coming out the back of the car, and the car burning as it tumbles into space when you lose. They’re all just triangles with vertices that are randomized each frame. The boost flames are each a single triangle, but if you ask me they make a pretty effective flame. I like my burning car flames way better than a lot of the graphical fire I see in commercial first person shooters like HalfLife 2. Then again, I was never much into realism. Cam shake is the best thing ever. I knew the wall of fire wasn’t giving off quite the feeling of horrible doom and despair I wanted it to when it caught up with you, so I came up with cam shake to fix that. I think it worked.

Second firewall

These fire colors were a little too cartoony. I like everything to be desaturated and sad.

21:45 – 1 hour 15 minutes left and I am as finished as I will be. The game now features driving a car in 3D around rough procedural terrain with a wall of fire chasing you, a boost meter that increases with air time, with fog and a procedural noise algorithm I developed a while ago for sound effects. It’s almost over…just gotta see if it compiles on Windows. I’m sick of coding, but I’m really happy with what turned out.
Oh yes, the audio. I’m kinda into noise music, and I’m totally into procedural generation, so one time I made a procedural noise synthesizer that could be controlled by moving the mouse around a square window, the x and y values mapped to the two controls. It seemed obvious to reuse some of that code for sound effects for intense fire. Ogg audio demonstrating the noise synth.

22:45 – 15 minutes left. Submitted linux version. Gonna go try to compile on Windows. Wish me luck.
I ended up working on final touches for an hour. At this point I was in a bit of a code trance, completely exhausted from the past two days and starting to get apathetic.

00:15 – Last entry: One hour fifteen minutes past the deadline, Windows version compiled. Though it probably has crappy sound. Whatever. I’m done.
It only had crappy sound on my crappy windows box and apparently worked fine elsewhere, besides being lagged due to the way I tried to fix a problem with audio skipping in between buffers. Thanks to DrPetter for helping me get the right OpenAL libs since I couldn’t download the SDK on dial up.

END OF LOG

Wireframe

Holes in my car

Some of my vertices turned out to be in the wrong order after all. Shoutouts to my good friend in Devon, without whom I probably wouldn’t have figured this out in time.

All in all

DoomDrive flew in the face of my own expectations for it. I’m happy. However, I’m friggin sick of coding, so I don’t know how long it’ll take before I recover enough to do a postcompo version. I want to make the game feel complete, though. I got this far, why not finish it off?

Ludum Dare has been a good lesson in getting the most bang for the buck. Things like fog effect, random triangle fire, cam shaking, are all very simple to implement, but add a lot to the game. Also, I learned you don’t need a full blown physics engine to have physics, as my single-comparison collision detection demonstrates. I never thought it was possible to make such great games in such a short time. This is definitely a motivating realization.

DoomDrive is the first serious game I’ve ever made, and I think it’s safe to say I’m gonna be doing more action games in the future, hopefully for a living.

It’s been beautiful, guys. On to voting.

Tags:


2 Responses to “DoomDrive Postmortem”

  1. mrfun says:

    I don’t know why but I love seeing paper designs, makes me want to get off my butt and do those too.

    Yeah you should finish up the game and put it up for download, good practice at doing the “last 5% that feels like 200%”…

  2. Simon says:

    Far more interesting than a timelapse. Thanks!

Leave a Reply

You must be logged in to post a comment.

[cache: storing page]