Sunday, February 15, 2009

Three-Day Weekend SVN Logblog

I passed another milestone today: fifty thousand lines of code written. I've hit a renewed stride over the past week or so and have been continuing to optimize while also implementing several features that bring the project closer to being a game.

------------------------------------------------------------------------
r1059 | Administrator | 2009-02-07 18:59:41 -0800 (Sat, 07 Feb 2009) | 2 lines

Finally implemented my old idea to allocate all the mostly-static stuff that is loaded in Game::Initialize() and while loading worlds in a separate place from the main allocator, which improves block seek time substantially.
Also implemented a very easy #define switch to turn off my memory manager for Brass City, so I can compare performance against the default allocator and try to justify having my own at all.


This was a huge optimization that I had considered making months ago and then left alone because it seemed difficult to implement. My custom allocator uses a single linked list of blocks, and as the number of allocations grows, it takes longer and longer each time to iterate over that list and find the first free block of the right size. I realized that I very easily use a temporary, scoped override to allocate all my static content somewhere else entirely, so that allocations made while the game is running have practically nothing to iterate past. This was the last and biggest of several optimizations I made last week; after making this change, memory is no longer a bottleneck and the game is much, much faster.

------------------------------------------------------------------------
r1070 | Administrator | 2009-02-09 01:21:06 -0800 (Mon, 09 Feb 2009) | 1 line

Added the persistent weapons stuff I'd been thinking about doing for a while. Weapon and ammo equipped can persist across level transitions by use of some scripts.


This is just one of a large number of gameplay changes I've made recently. It is a solution to carrying weapons between levels. Because my levels are completely discrete units, anything that is supposed to persist across level transitions has to be stored before the transition and restored afterward. In the case of the player's health, score, etc., I can simply store a number and set it on the newly-constructed player in the new level. Weapons are more complicated, because I have to reconstruct the set of weapon objects, all the ammo objects used by the weapons, reassign the amount of ammo remaining in each weapon's magazine, and make sure that whichever weapon the player was actively holding is the one that is selected in the new level. There was no especially clever trick to this or apparent generalization to the problem that could save me time now or in the future; I simply had to write a bunch of code to store the large amount of relevant data and set everything back up again on the other side. In fact, it's really only worth mentioning because there was no clever solution; sometimes the blunt force approach is the only way to go (and I'm getting into the realm of special case gameplay code where this sort of thing may become more common).

------------------------------------------------------------------------
r1092 | Administrator | 2009-02-15 16:37:46 -0800 (Sun, 15 Feb 2009) | 1 line

Implemented AI weapons and a very simple AI attack task.


This is the change that broke the 50K LOC mark. It's also especially significant to me because AI is one of the last remaining generic systems I need to write before I can start prototyping gameplay. There's a lot left to do here to make even a simple combative bot, but AIs can now aim and fire weapons at the player, which is one big step toward that goal. At this rate, I believe I might have a functional AI opponent within a week, perhaps, and from there, I can build out some test levels and start getting a feel for how the game will play.

Tuesday, February 3, 2009

Code as Art

Reposted from a TIGForums discussion, in response to the assertion that programming is more frustrating than other creative endeavors

I actually find similar challenges in writing code and composing music. I start with a basic idea in my mind of something I want to create. How a system should work, or how a piece of music should sound. Then I start building it, writing code or arranging chords and melodies. On a good day, it all just works, but sometimes things don't fit together so nicely: my interfaces aren't well-architected, or a harmony sounds dull and trite, or a matrix transformation isn't working the way I thought it should, or I can't find the right chord change to segue into the prechorus the way it sounds in my head. If the problem gets really hairy, I step through one line at a time in a debugger, or try every combination of notes until I find the right ones. And in both cases, I find that the more I practice, the more it comes naturally and I learn to anticipate and avoid the tricky problems in advance.

Monday, February 2, 2009

I was going to write a Weekend SVN Logblog, but it's useless to pretend those are actually weekly at this point, and I've made too many small, incremental changes over the past week to easily summarize with a couple of select entries. I will, however, post this because it was a huge milestone for me:

------------------------------------------------------------------------
r1024 | Administrator | 2009-01-26 20:55:22 -0800 (Mon, 26 Jan 2009) | 1 line

Fixed bug trying to spawn ammo classes while serializing in a world. Protecting against similar cases in the future with a spawning "semaphore".


1024th checkin. I sort of wish it had been a more momentous change than a simple bug fix.

Last weekend saw a huge system finally get added to the game: weapons! It actually took me by surprise the first time I ran the game with a proxy weapon mesh on-screen just how important the first-person view of a weapon (or any instrument in the player character's virtual hand) is for immersing the player in the game. Even before the weapon did anything, before there were animations or ammo classes or any of the myriad of details I've added in the last week, I was running around in this world with a simple, untextured revolver on-screen, feeling at last like I was a part of the game world.

I'm sure there's something meaningful to be said regarding the destructive nature of games that a weapon is critical to grounding a player in the world, but analyzing games in that fashion isn't my style.

Most of the rest of my week was spent either improving the game in small but significant ways (the camera topples over when the player dies, there's a Return to Title button on the pause menu, you can't save your game after being killed, etc.) or starting the arduous process of optimizing this whole thing. I made a couple of simple optimizations (not emptying and reallocating some large arrays every frame) that actually helped bring me back up to 60 Hz in my best case scenes. There's still a long way to go if I want this to perform well on older computers, but then again, I'm developing on a laptop that's over three years old, so my own machine keeps slipping further toward the low end of the spectrum. I guess that's not a terrible place to be--it keeps me honest in my expectations of the engine.

Finally, I added a race timer. It was a very simple class that took me maybe ten minutes to fully implement and test, but it was significant because it is one of a few gameplay systems to be designed specifically for my next game (as opposed to the engine in general) and brings me much closer to having a working prototype. In fact, as soon as I can hash out some more details on the broader AI architecture--sensors, behavior design, AI weapons--I'll be ready to put the code aside momentarily and build out my first real level for this game. I'm excited about this again.