mangobrain home


Posted on 2005/09/04 02:19

(Warning: The overly verbose, self-indulgent post-mortem continues...)

I've just been playing my game, something I never really did during the competition itself (mainly due to there not being anything significantly interactive until the early hours of Saturday), and surprisingly, I actually think it's kinda fun. Although I'm now 99.9% certain that my hackish way of using ODE has indeed disabled swept collision tests; I should have realised that it would from the start, since I'm only implicitly providing past position information, and not providing any timing or velocity information. That's all dealt with by my own code, which then just tells ODE where the object is this frame. This is potentially fixable, would lead to cleaner code (no mixing of conventions), and is generally desirable and could lead to previously infeasible, physics-based extensions to the gameplay.

Currently, lack of swept collision tests has a severe detrimental effect on your ability to shoot things, something I never noticed during implementation because I simply never played for long enough to get the tunnel runner up to a decent speed. This is a rather fundamental flaw for something that is meant to be, at least in part, a shooter. Blame it on the fact that bullets were the absolute thing added to the game before submission (bar the README), which also explains the incredibly pitiful shot graphic.

One thing I don't really know how I'd fix is the lack of transitions. By this I mean the way in which the main menu launches you straight into the game, which launches you directly into your three lives (without telling you how or why you died), then drops you straight back at the menu again. Nifty looking fades, timed GAME OVER screens, so on and so forth... these things just don't fit nicely with my handy-dandy pluggable main loop system*: as far as I can see you'd end up with either main loops full of state checking and superfluous timers, or a hideous and/or over-designed system for passing state between smaller main loops. My pause menu doesn't fade in, because that would mean an extra level of state checking and timekeeping that I really, really don't want to add to the code, because it'll make things hideous.

* What I did for ths game, that I've tried in a few other prototypes but never made a proper library of, was implement one, single main loop, which triggers methods on a "loop object". For example, when the game is first launched, the main menu loop object is instantiated and given to the system. It is the menu loop's responsibility to instantiate the next loop object, e.g. start a new game. The game loop object encapsulates all state and resources necessary for play, along with a callback that the generic loop usess to perform rendering, collision checking, etc. (there's only one such callback, the system doesn't care what you actually do during it, it just flips the buffer, ticks the timer and calls again). The great thing about this is that, in Python at least, switching to the next main loop simply involves swapping the current loop object for a different one, right under the system's nose without even telling it. Plus when this happens, the reference count on the loop which made the switch drops, which can be used to trigger automatic unloading of all no-longer-needed resources via the destructor. The downside is that since you're relying on the destructor to de-allocate your resources, and have to instantiate the next loop before the current loop can die off (unless you want to quit the game, in which case you simply set the loop object to None, which the generic system then picks up on), you might end up with an overloaded system in the interrim - this would be a job for a slightly cleverer generic loop, capable of being told which class to instantiate next rather than relying on the variable it uses always being instantiated. Sadly, without adding further levels of callbacks and abstraction, none of this makes the nifty little timed fades, and other UI flourishes that make a game seem professional, inherently easier to implement in a reusable fashion. Also, I've yet to figure out how it would be possible to shoehorn multiple threads (e.g. have a physics thread in the background for some of the loop objects) into a system like this.

Add comment
Comment by alexkidd on 2005-09-04 08:26

We have a similar loop object in our game (subclasses of Scene); I'm not sure if it's what you were thinking, but you might be interested in the fade up/down integration in our game over scenes. Some of it is a bit hacky, but we also implemented a generic "Behaviour" system which can attach to any sprite to make it blink, or fade out/in, or whatever, which could also have been applied to the scenes themselves (given a less hacky attitude on my part!).

Comment by Matt on 2005-09-04 14:05

Wow. I read all of that!

Comment by Michal Wallace on 2005-09-04 14:50

Cool. :) for trailblazer, we created a "Console" object that works sort of like your game loop. It has various states, and each state keeps running until its "done" flag gets set, at which point the console trades it in for So in Game, you can say: = Pause(self.display, self)

In other words, pass the display to Pause so you can draw over the current screen. Then pass in self (the game) so pause can set it's own .next and return.

We did manage to get physics and sprites and pygame all integrated, but it didn't turn out as nicely as I'd hoped. They're all hard coded in each state's .tick() method. I was hoping to use Nanothreads to clean this up, but we never got to it.