It’s been a rather busy last couple of weeks. I’ve actually had a few coding sessions at night, and that hasn’t happened in months. Been having a blast working on Outwitters and we’ve been play testing maps on a weekly basis.
In other news, Craig and Gavin, of Retro Dreamer fame, recently released their Velocispider iphone/ipad game. If you haven’t checked it out by now, then you’re missing out on some good old-school arcade fun. What’s impressive is how quickly that game came together :). I believe they had mentioned it was about a month of development? Man I wish we could crank out quality games that fast. Maybe we’ll try that after Outwitters to help ease us into something less ambitious.
Back in Outwitters land, I just recently got sprite animation implemented into the framework. Having the characters comes to life on the gameboard is pretty exciting. I still need to write a state machine to manage the different animations for the characters, and that’ll take some effort. Speaking of state machines, one of the initial problems I had to solve was how to implement Outwitters’ core game logic.
In a traditionally academic solution, I initially just wrote a state machine that has the different states of gameplay and transition functions to drive the game forward. On my first run through, the game was working but it was extremely painful adding new rules, tweaking rules, or removing rules to the game. It became a huge mess. I could see writing a ‘graph-based’ state machine would be really complex in the long run. I started to see if there was anything written on turn-based games architecture, and I came across this really helpful post on stackoverflow.com. It described a really elegant way to express game rules without having to couple them with specific ‘states’ of the game in a sequential order.
I took the advice of that post and re-wrote the game using the Command pattern described. It’s been a big win for me thus far in not only implementing the prototype, but helping to quickly iterate on game rules over play sessions. Instead of thinking of all the ways a game state can transition I became more focused on the discrete actions a player can make in a game and thinking of all the conditions that need to be valid (or invalid) in order for that action to be legal. This became much more flexible when iterating, as the logic for actions was isolated to single actions, and changes to them didn’t ripple throughout the whole game’s ruleset. Some of the more complicated conditions for actions were a bit challenging, but far more readable than if I had written it the ‘old way'.
Another nice thing that comes out of this design is the ease of serializing actions and game states. Instead of pulling in a bunch of random data from within the game to create a coherent picture of the game, I ended up creating a single class that encapsulates the status of the game. It’s fairly lightweight, and gave me the added benefit of having a central object to query for information about the game. Adding asynchronous play and saving the game to disk were very straightforward.
I have gone with a component-oriented design for the game objects in my framework. So render components are attached to lightweight gameobjects, and any other special functionality is wrapped inside another component and attached as well. In the past, game logic was usually decentralized throughout the components, as the games tended to be more open-ended with very little structure enforcing the flow of the game (for instance, platformers, and even Tilt to Live). I almost went that route again for Outwitters, but the design used to enforce the rules of the game were at odds with the decentralized component design I was accustomed to. Fortunately, the way things panned out was my components ended up being the ‘View’ and ‘Controllers’ of an MVC model, and the central game state object being the model. When the model changes, events are sent out to my components to update health huds, change character colors, etc. It can get pretty verbose at times, but I’ve loved the fact that the game logic is isolated from how things are positioned on the screen or rendered. It’s helped debugging a great deal.
In the end, the command pattern I’m using for the game rules is still in essence a state-machine, it’s just organized in a very different manner than the common “updatestate(), getNextState()” mentality.