Sunday, January 14, 2007

XNA game structure thoughts

I've seen a few posts and articles around the net with recommendations on how to structure an XNA game, for example this great post at Cornflower Blue.

Most of these revolve around the same idea of building an own rolled Game Component collection class as the backbone for your game's partitioning, e.g. Startup:GCCollection, LevelSelect:GCCollection, InGame:GCCollection, HUD:GCCollection and so on. The collection usually implements at least Update and Draw, propagating the calls through the internal collection, and in most cases is actually derived from Game Component its self.

I'd like to propose a slightly different approach.

Back to the original reasoning for the problem:
  • XNA games want to stick to the Game class's methodology, i.e. Initialise, get LoadGraphicsContent and UnloadGraphicsContent called at the right times including any adapter malarkey, make sure Load is called before Draw, and conversely that Draw is never called when unloaded.
  • The most obvious and arguably the easiest way to do this is to implement Game Components. Bonus: sticking to Game Components should make code more recyclable!
  • Games tend to be easy to partition, usually with pretty huge chunks belonging naturally with each other, e.g. the level select screen's background and OK button belong together, while neither appears when a game is in progress.
  • Micro managing each Game Component would suck. Adding and removing each at every transition is error prone, and there may be any number of other operations that need to be done to them as a group that would similarly suffer.

These definitely seem to point at having a collection class around to hold the groupings, but here's where I diverge: why do more than the problem requires? Why reimplement Update and Draw iteration over the collection, and in the process actually lose the Order and DrawOrder functionality? Who's to say you won't want these interleaved between the partitions, e.g. Portions of the HUD group rendering and updating in between portions of the game world group?

What I reckon we really need is just a collection through which to issue orders to all its members. We're looking for more of a set really. So I propose something like the following:

    class GameComponentSet : List<GameComponent>

    {

        GameComponentSet( Game game )

        {

            this.game = game;

        }

        private Game game;

 

        public void Activate()

        {

            foreach ( GameComponent g in this )

                game.Components.Add( g );

        }

 

        public void Deactivate()

        {

            foreach ( GameComponent g in this )

                game.Components.Remove( g );

        }

    }



With a few of these we can manage our logical partitions as groups, but we don't chuck the functionality that is hidden away inside the Game class.

While Activate and Deactivate are pretty plain here, they serve as entry points for all manner of verification. For instance in Activate, you could check to see if the component is already in the game's Component Collection, and deal with the situation as you see fit, effectively adding in a bit of late checking to see if a Game Component is mistakenly in two sets at once.

Specific to each game, we could add other registration functions and properties here as well, e.g. RegisterPhysics to add all the Game Components to your physics manager, or RegisterUI to pass them onto your UI manager. Obvious additions would be the Game Component Enabled and Visible properties. Sure they may end up as just simple function/property wrappers around foreach loops, but as with the above Activate sample, it's always handy to bottleneck this sort of thing just in case you need to address it later.

Clearly we can also derive from GameComponentSet and make specific versions, e.g. UIGameComponentSet, PhysicalGameComponentSet, AIDrivenGameComponentSet, and so on.

Confession: The above simple sample deriving from List<>, while serving as an easy illustration, isn't entirely robust. The problem lies in the being able to change the collection after you've called Activate. Further evolution of this class would probably want to hide the collection implementation internally, and validate for this.

The only problem we face now is how to control the unloading of graphics content for our sets. Frankly, I have no clue how this is supposed to work. The function its self is not public, and it seems that the only way to invoke it is to lose the graphics adapter. I've taken to adding my own public interface addition to classes derived from DrawableGameComponent to chain the call over to the protected version. If anyone knows how this is meant to function, could you please shed some light here?

Finally, while admittedly it is more runtime work to add and remove all the members of the list individually rather than enabling or disabling a single entry point to them, bear in mind that the cost should still be really small, and rarely paid: how often do you reckon you'll want to turn entire modes on and off! For smaller sets, the difference should be so small, that its perfectly viable to use the same scheme more often, e.g. for HUD mode changes like overhead map on/off.

Saturday, January 06, 2007

Mooncasting: First mechanics!


Joy!

Just before I pop out of town for a week's holiday, I get to spend a day on my own toys. Life is good.

So I'm motoring along on this Mooncast project. Since the last post on the subject, I've written most of the main mechanics. The video illustrates the following:

* Buildings UI.
* Castle spawning plebs (here cheated to take no time for speed of demonstration).
* Plebs being reassigned to different buildings.
* Effect of staffing on the firing speed of cannons.
* Effect on fog of sending out scouts from the aviary.
* Blowing enemy buildings up!

Next task is to spend some time on the flow, i.e. start screen, begin, middle, end. Need to pay particular attention to the progress reporting while in game. I reckon that the right side of the screen will have mini icons for enemy buildings that have been spotted and nuked.

A note on the XNA so far: still loving it. Nothing has gotten in the way, and C# continues to be lovingly supportive. There are quite a few omissions in the XNA libs, but compared to all that has come before, this is a massive step forward.

Oh! And note: the music in the background of the video is the most excellent "One Thousand Tears of A Tarantula" by Dengue Fever. Absolutely music to code by.

Thursday, January 04, 2007

The Moral Combat trailer and Jumbled Jack


It's a trailer, and I'm absolutely not going to comment on someone's work without having seen the entirety of it. Suffice to say that I'm looking forward to watching it and seeing how he's pieced together this hot button topic.

No, this post is to address a specific quote from the trailer: Godverdomme, but I’m tired of hearing Thompson’s pearls of wisdom. We don’t recognise violence as a virtue? Really? Quick someone tell the military where the “will to kill” is a prime learned virtue, or sports fans who egg on boxers.

It is precisely because society is filled with violence-is-a-virtue memes that we find so much entertainment in fulfilling that self image. We want to be badass action heroes because we grew up being told that badass action heroes were bad as. And we’ve done that ever since David badassed Goliath.

I’m all for changing that culture, but it’s not going to happen overnight, and it’s certainly not going to happen through censorship, soft, self imposed, morally outraged, outright stamped, enforced or otherwise. Censorship doesn't challenge anything, it's just plain head-in-sandery.

If you really want to change our culture of violence, you need to create media that presents a different world view. You have to tell a different story, and a more compelling one at that. But no, Jack. Being against something is a whole lot easier than being for something, isn’t it? Being a destructive force rather than a creative one comes naturally doesn't it? Can’t charge if there are no windmills, eh?

Meanwhile, the least damage I can think of anyone causing while trying to live up these pervasive violent memes is acting them out in a video game.

Tuesday, January 02, 2007

Novelty: when did this become a dirty word?


I've persistently heard the oddest disparaging comment made about the Wii recently: "It's all just novelty. The Wiimote is just a gimmick"

WTF?

When did being new become a sin? For some reason I thought it was the goal: show people what they haven't seen before. Is "Racer X Part 4 Autumn '07 Tournament Edition 1.74 Extreme" really the path we want to go down? Is it really OK that the main attractions are the minor refinements instead of the mad gambles?

I say viva novelty. I, and others I've queried on the matter, have conversely found that the Wii's novelty is making everything old... new. Zelda is for all intents and purposes still Zelda, but everything feels so fresh with the new controls. Every little movement is a joyous discovery. It's almost like getting to start all over again, and Lord only knows how many times everyone's wished for that.

Whilst perusing the gaming shelves, I find myself furtively glancing at games in genres I would normally not give the time of day to. Like some sort of gaming pervert I'm now bloody flirting with anything I can shake a Wiimote at.

Luckily though, I don't really need to defend novelty much: the DS happened. It received the same disparaging comments about its dual screens, microphone and pen input. Despite that, this past Christmas it was the tearaway lead in sales.

Stop fighting it: Novelty is where it's at.

Elebits


So I got me some Elebits last week. General impression: Good fun!

The principle is very straight forward: the world runs on Elebits, these little adorable puffball creatures. Something's gone a bit off and the Elebits are behaving bizzarely, leaving everything without power. Your dad, currently away from the house, is an Elebits researcher. You decide to take matters into your own hands, grab his capture gun and start to hunt down the critters in your home.

The game works like an FPS of sorts. You shoot your capture ray at the Elebits, they get sucked in and you get power. The capture ray can also manipulate objects much in the same way that the grav gun did in Half Life 2. Elebits are shy retiring things and can be found hiding under or in objects, requiring you to basically make a mess of your environment to flush them out.

The electrical power you collect by capturing the Elebits goes towards various bits of electronics that come to life once you pass their power requirement thresholds. Proceeding to then turn these electronics on causes them to spew a different breed of Elebits that when captured upgrade your gun. An upgraded gun lets you manipulate heavier objects.

The core fun here is a balance of making a mess to flush the little buggers out, and sharpshooting them: so basically two things the Wii is bloody brilliant at.

Shame then that the package isn't left at that. In an effort to introduce more "game" to the proceedings, Konami have slapped in some unwelcome features. Well, at least unwelcome in my book. Some of the later levels come with additional rules applied to them. Two of the least fun are "don't make sounds louder than X decibels" and "don't break more than X shatterable objects".

Both of these run counter to the core fun of the game, preventing you from shredding the environments for fear of breaking the rules. Both are also very fuzzy: you're never certain what volume of noise any given action will generate, and in the chaos of objects flying about you could accidentally domino something over out of view. Both are just plain fun dampeners and very poor design decision to my way of thinking.

Luckily they're not pervasive, and once you've passed them it's back to the good stuff!

Visually the game is charming enough. Aurally everything is copacetic as well.

Honestly, if Katamari Damacy hadn't come along and pretty much defined true, unbridled mechanical and aesthetic zaniness, this would be golden. As it is, knowledge of better out there leaves you feeling that there's a sort of restraint while playing the game that can only be the result of not enough time spent polishing it. Somehow the whole thing just fails to make the jump from fun to sublime in the same way that Katamari Damacy or Rez did.

You feel this restraint in the objects that don't fit the collision system (looks like it only does convex hulls, but there are objects with large cavities in their silhouettes), in the music that fails to crescendo (sounds like they were composed without having played the game, so they loop indefinitely rather than aim for the time limits), in the story presentation that seems to lack soul (the same sort of non committal feeling that you get from bad Disney movies that are written by committee), and in the graphics that vary in detail from object to object (looks like there may have been a shift in target midway through). This is all a shame, because I like the concept so much, and when it works it works so well that I'm convinced it could have been an all time great if it were given the loving attention it needed to grow up.

Ah well. I was still thoroughly entertained by the whole thing, so I'm happy enough with it. Perhaps Konami will have the will to finish what they started in a sequel. Until then, most certainly rent this, and if you're a fan of the weird and wacky, you absolutely must consider treating yourself to a purchase.