Pause for thought (or not, as it turns out)

Paws for thought

The wrong type of paws, yesterday

For more than ten years, I’ve been generally working on massively multi-player technology. One of the things with that sort of stuff is that “Pause” is not a feature that you need. In fact, the software is usually asynchronous, heavily multi-threaded and real-time. From the server’s perspective it never ends: you keep on going and you never stop. From the client’s perspective, pause is a feature implemented with the disconnect button if at all. So perhaps, with this in mind, you might find it forgivable that I should completely forget to implement such a feature in my iPhone game. And by “completely forget” I mean at all levels. I failed to put it architecturally into the engine. I didn’t even think to put a button on the screen. I have not remotely considered making some programmer art for it… until I was playing my one level the other day to show a friend.

Ping! Yes, that was the bleeding obvious machine registering a hit at my expense. “Why yes, the pause function, it’s here somewhere. Well, it’s not, but it won’t be hard to add… should be a five minute job…”

Oh, cocks.

It turns out that adding pause functionality into my engine is akin to changing the tyre on a car roaring down the motorway at 130kph when you’re driving at the same time. I’m rolling in timers that are all over the place. They’re in the entities. They’re in the entity manager. They’re sprawled sexily across the game components showing off their awesome accuracy, they’re everywhere. On top of that, there’s the classic “Christ on a bike. I can’t believe I’ve done that again” mistake: with the fact that I’m running a fixed frame rate which I know in advance, I figured I’d “save myself some time” and merge the entity update with the entity render. Update handles collision detection, simple physics, the constraint engine, life and death of entities and all sorts of gubbins. When I pause, that needs to pause. But the rendering, well, that needs to continue…

And then there are those pesky timers. A global pause is almost fine because ultimately, there’s a static component to all timers that manages the details: I could simply add a static PauseAllTimers() and ResumeAllTimers() and I’d be cooking on gas — with the exception of the timers and entities I’d love to use on the pause menu for the buttons, animations, backdrops and other stuff.

Solving this kerfuffle involves a number of steps:

  • Separate Update() and Render() code paths
  • Remove timers from the entities: each tick has a fixed delta-T, they can count ticks: at 20ms, count 50 updates and a second has gone by even if the game was paused for an hour in between
  • Add master super-classes to the entities so that they can be paused by super-class: this allows UI prettiness to continue
  • Remember that whilst a detailed design might be overkill, some design may have avoided this…

Basically, the above is a 400 word excuse. Une bonne excuse, peut-être, but an excuse nonetheless. It’s a real bugger to fix and I feel like a right tool for not factoring all this in. Still, on the bright side, I decided on four levels of parallax in the end and they look great even if you can’t pause the game to appreciate their beauty.

This entry was posted in My iPhone game and tagged , , . Bookmark the permalink.

4 Responses to Pause for thought (or not, as it turns out)

  1. Pingback: That’s right, Paisley, the specification | Cobras Cobras