I agree wholeheartedly with the comments on the previous blog post: game code seems to pick up most of its crap at the end of development (or what you suppose is the end). You start cutting corners because you think you’re done, or there isn’t much time, and soon enough your objects are pulling triple duty.
More than that, though, I think game code is just generally less reusable than code in other arenas. The problem you’re trying to solve with game code is “being fun,” and it seems rare that fun-ness comes together in the same way twice.
When your code is very unlikely to be reused, making it beautiful just isn’t worth it. Of course, if your code is buggy, then you lose sales. And if you can’t leverage your code to make sequels, you lose again. But aside from that, whatever. Game mechanics are so finicky and yet so simple that reusing your game objects isn’t a big win… you’re better off just hacking what you need now. Your next game will probably want all different details anyway.
There are some things that you’ll obviously want to use again: GUI widgets, configuration objects, maybe even your entire Top Ten List. But most of the actual game varies too much to be reused. So I don’t try.
So I propose a system that acknowledges that most of your game’s code is dead-end code, never to be reused in future projects. Its goal is just to be comprehensible and bug-free, not pretty.
I like to think of my code as having hit points. A beautiful code body with really elegant object structure has maybe 50 hit points, and as you start hacking things into the code, it starts to lose health. If it reaches 0, it’s unmaintainable and you lose. So you’ve got to periodically heal the program by refactoring code and documenting. However, if it’s still at 50 at the end, you lose, too, because you’ve probably overengineered things and wasted time.
The difference between this and traditional engineering is that I don’t recommend trying to make all your code perfect the first time through — I recommend quick hacking and then refactoring. When coding game features, you just can’t tell where something’s going to lead. The exploration factor is so high that you’re wasting time if you try to create perfect code the first time.
I think that at least half the cool ideas I had for Starcrossed got discarded. They sounded fun on paper, but they weren’t actually fun. And the other cool ideas changed dramatically from their original incarnation. If I’d spent a lot of time designing each feature instead of hacking it in real quick, I’d have wasted TONS of time. The only way to know how a feature is going to work is to see it in action, and tweak it for a while. Only then do I know how to code it the right way.
At that point, I step back and figure out if my quick-hack version is going to be reliable, or if I should rearchitect it to be cleaner. It depends on how much damage my quick hack caused. Sometimes I leave ‘em in there, if they’re fairly isolated and reasonably obvious.
I think a major time-waster among new programmers is ego: they know how to do things the right way, and they can’t give themselves permission to do it the fast way instead. Even for a prototype.
Because I give myself permission to hack code, I can test ideas very quickly, even though I code in C++. I give myself two days’ coding time on an idea: by that point I can usually tell if it’s going to be exciting or not.
This is coding for fast results, not coding for reuse. It’s optimizing my time now, instead of gambling at optimizing my time later. My game code sucks, but it’s good enough: maintainable and bug-free.