Work goes on, and the code gets closer and closer to an actual, playable game, with goals and score and loss conditions and everything. Crazy!
It’s been a pretty grueling month or so of work getting here, but I’m finally hitting the point where enough of the back-end stuff is working that the part players will actually care about—the game part—is coming together quickly. There’s still a lot left to go, but it’s amazing how a project can turn from “nothing much to see” to “oh, hey that’s kinda cool” as soon as one little chunk of code gets done.
Anyway, lots to talk about today, because I’ve been busy and not saying much. I thought about breaking it up, but if I do this across multiple posts, I’ll probably take the rest of the week to catch up.
So, in the words of that rotund Italian plumber, Here we goooooo…
(Game) State of the Union
For a project that already existed in prototype as a Torque2D game, it’s taken a long time to get things to the point where it’s started to look like a game. This is partially because there’s very little code I could copy over, due to the differences between working in Torque and Torquescript and working in XNA and C#, and largely due to realizing how hacked-together the original project was since I had to learn Torque and finish the project in just under five weeks last fall. So a fair bit of the time coding this version has been taking time to do things reusable and right that were hacked-together the first time.
Mostly. Honestly, there’s still some hacked-together-ness all over, but part of the issue has been actually learning where things can be done better. Often a couple days after I’ve written the first pass, which necessitates either living with it and making a note(and sometimes writing stuff into my game library so I do it right next time), or re-working the code to use the better way of doing things.
Anyway. The thrust of this musing is that one of the major updates since my last post is that I’ve moved all the game logic out of XNA’s main update loop and into a set of game state components. This makes it easier to manage by a long shot. Essentially, the Game State code in my library has a Manager, which holds and keeps track of the game states, and a parent class for the game states themselves. The idea is you derive game states for the specific game from the GameState class, overriding the Update() and Draw() functions (and some others) to provide the needed logic. The GameStateManager class is then registered as a Component (and as a Service), and you register your state objects with it. Then, as your game requires it, you call a ChangeState() function to move from state to state.
The idea here is that whenever part of the game has a markedly different execution model than the rest of it, you have a new state which is in effect it’s own little sub-game, and you swap back and forth between different states being active. This is a pretty manageable way to handle title screens, options menus, and so forth. Nucleus has states for Gameplay, Title Screen, Help, Options, and Game Over. It helps keep the code cleaner and more manageable, and I suspect that it performs better with this modular arrangement.
Show Me the Eyecandy
As awesome as all this behind the scenes stuff is, players don’t really care about it, so long as it’s working correctly. What players care about is the game. When they can play it. And that’s fair.
I’m happy to say that Nucleus has moved towards “playable” in a huge leap over the weekend. The code is sort of hitting this critical mass where enough of the backend is done that a couple of little bits of code that link that back to the front has massive impact on the game.
The image on the left is the first test run where the orb spawner was fully hooked-up to the rest of the game. This small act suddenly meant that several large chunks of code were finally actually doing something—the code that makes an orb “fall” into a stable inner space, the code that manages the visual effect of orbs moving from one spot to another, the code that makes sure that when you spin the whole structure, the orbs stay locked in place, and so on. I was pleased to find that it mostly worked the first time. There was a bit of a bug in the stabilizing code that left it failing to fill in the spaces quite right, leaving the extra orbs flitting around the outer rim looking for open spaces that weren’t there.
Fixing the bug gave this much better version. All the spaces filled in properly, which was a huge relief. You can see there are still orbs moving around the outer ring (that’s what all those colored circles are) because the code that detects the game over state(all spaces are occupied) isn’t in yet. This means that a bunch of extra orbs end up circling around the outer ring of spaces trying to find an open one.
While that last point is an unwanted behavior in the final game, it is also a useful one right now—the game is designed to have a maximum of 50 orbs in a live state at any given point in time. Letting the system run in this technically-broken state lets me test the code that makes sure a new orb isn’t spawned if for some reason we’re at the limit. It is unlikely this condition would be met in the final game, so it’s best to test it now while I can. It also gives me a chance to see what kind of impact having a whole lot of stuff going on at once has on performance, since this is more sprites than we’re ever likely to see in a real game. As it happens, it’s working fine and fast, so I can move on.
So What’s Next?
There isn’t a lot left to do to have a functional, if unfinished game. The aforementioned game over condition needs to be detected and handled. The code that checks for matches to eliminate needs to be written, as well as the code that actually destroys those orbs and tells the remaining orbs to check their stability. Scoring will also be needed. Finally, the game over screen and code to reset the game will need to be added. After that, there’s simply a lot of polish and platform code that’ll need to go in.
That’s quite a bit left to do, but there’s also a lot that’s been done at this point. And that much is very heartening.