Wednesday, January 31, 2007

Shooter Zero: A data driven sample

So, in the last programming post I tried to dump what I know about data driven architecture onto a rather dense page. Here I'd like to share with you a sample application that might shed some light on what I was trying to say.

The ShooterZero.zip file over on my google pages page contains an XNA project that is a 2D shooter game framework.

The code describes a series of classes that together provide services that a shooter will need:
  • Resource management and a game loop with debugging functions (even a simple console!)
  • An object model, where all elements of the game are Object Instances that are created from Object Definitions
  • A scripting language to define the behaviour of Objects
  • A set of services that the Object Instances can employ, e.g. intersection, rendering, input, etc.
  • A parser that can create Object Definitions and Object Instances
The project comes with 3 XML file definitions for 3 different kinds of shooters.

The implementation here is admittedly very slapdash for lack of time invested, but I believe the principal features of the kind of data driven system I'm trying to demonstrate are evident:
  • Game is setup with parameters read from a data file - one engine supports a variety of expressions by implementing common primitives.
  • Objects in the game are defined using data driven templates, both properties and behaviors - data is parsed into logical collections of primitives.
  • Object instances are created from data - separate structure from content.
  • All the Data is reloadable at runtime - faster iteration time when it comes to implementing content.
So, if you wish, download and have a play with it. Questions are welcome, and if there's enough interest I could write a few more posts that break out the details.

A Dark Day For Gamedevs

An article over at gamesindustry.biz is painting a horrible picture of what's just gone down at Sports Interactive. In summary: a leaked pirate copy of Eastside Hockey Manager has killed legit sales so badly that they've had to can the game. Not any pokey little game either, we're talking a critically acclaimed game. They didn't make their money back and they can't afford to pay the hockey team licences in the game.

Real devs just lost real work. This isn't a theoretical discussion about piracy, it's real actual people who work to make games who have had their livelihood directly affected. No sales means no recoupment, means their investment down the drain. Thank goodness the company can survive the blow and the guys haven't been laid off.

To the pirate to hacked this one: hope you're proud.

Sunday, January 28, 2007

Data Driven Game Architecture

You hear the term "data driven" bandied about reasonably often in gaming tech circles. Why is this? Here I'll present a summary of my experiences in the matter.









Goals:

  • Laziness. We want to write the least amount of code to deal with each instance of a feature of our game. Why on earth write a whole class for a new bad guy if we can get away with a bit of data instead?
  • Laziness part 2, or maintainability. As a consequence of laziness, we want to end up with the most compact form and the least possibility for errors in our instances.
  • Quick iteration. Reloading a bit of data in a running game is much quicker than compiling and restarting. We want to spend time on the game, not the structure.
  • Encapsulation. Games change during development, usually quite a lot. Data is easy to add and remove from projects whereas code can all to easily get entrenched.
  • Devolution of responsibility. The power to actually carry out game implementation begins in the hands of the programmer, but not all aspects of implementations belong there. Data, and tools to edit said data, let you shunt that power to whomever requires it.

Bonuses:

  • Better modularity. We end up partitioning functionality in our code more naturally when we're thinking data driven. As a result, you're also more likely to get recyclable code for next time.
  • Easier serialisation. Writing your save game module can be made easier by a nicely data driven framework: the data to save is usually easily found and easy to mark out.

How to go about it?

  • For a given feature in your game, collect a definition that encompasses all instances of the feature. For example, if you're making an RPG you'll need NPCs. Each NPC might want to be able to engage in a conversation, query information from the world state, be able to retain and be queried on its state, etc.
  • Figure out what portions of your definition will be the variables between your instances, e.g. each NPC will have a different name, a different description, a different storyline, etc.
  • Figure out what sort of data will best facilitate describing those variables.
  • Start out right! If you already know you'll need this, invest in the time to get it right. Sure you can hack in something hard coded to start with, but you'll later pay the price in lost momentum when you least want to.

There are two broad divisions on methods of data driving a game.

  • On the one hand, we have the simple property bag. This is passive data that simply sets up a few variables for game objects. Simple RPG weapons, for instance, where each definition is a name, a description, damage information and some art resource references. My preference for this sort of data is a nice XML file. XML is robust and easy to parse, there are plenty of decent raw XML tools to leverage (especially if you write a schema to go with it), and there are plenty of mature XML code libraries to work with. That last part is particularly important as it makes a painless transition to a binary format, should it prove necessary, trivial. XML isn't perfect, but it's easy and it's there.
  • On the other hand we have the more complex behavior bag. This is an extension of the property bag where we also add some scripted behavior specialisations to each of our instances. Enemies in a shooter for instance: where each enemy is defined with some art resource references, and callbacks that contain code fragments to describe their AI. There are a lot of ways to implement this, a virtual cornucopia of choices. You have all manner of embeddable scripting languages like Python or Lua that are quite mature now, and plenty of experimental smaller ones if that's your bag. Depending on your exact requirements, rolling your own might even be an option. There's a lot to say for domain specific languages.

Things to watch out for.

  • Don't get carried away. Do your homework first, and make sure that you really do need to data drive a feature. There is some overhead to pay in terms of implementation time, and it's not a cost worth paying if all you'll do with it is define the one instance that never changes!
  • Remember performance. You should absolutely be willing to pay some performance decrease in exchange for data driving, as obviously you're trading that for a quality upgrade from the faster design iteration. Be careful not to be disastrously generous with this trade though; as with all things be pragmatic about the end result. Above all do not fall into the "we'll fix it later" performance trap. The industry is littered with horror stories where teams have leaned on a scripting language only to spend half a year backpedaling out of it to get the frame rate back to 30, or get the memory footprint back down to the release configuration.
  • Beware the lure of generic! When building your data driven system, it is intuitively tempting to continue to generalise the implementation. In fact, as you continue to work, you'll keep getting struck with "Hey, this is just a slight specialisation on that other thing!" Be careful here! All problems in your game are implementable in an ultimately generic structure: the programming language you're writing the game in. Hold fast to the idea that what you're doing is in fact specifying groups of solutions to remove the redundancy of implementing their variations generically! In other words: if you end up embedding a scripting language into your C++ game and then writing nothing else but script for every feature of the game... all you've done is swapped programming languages. This is not necessarily bad (and possibly a topic for another time), but it's not an action towards the ideal we're discussing here.
  • Continuously evaluate where you are. The whole point here is that you're optimising how you write the game. If you end up haemorrhaging more time than you otherwise would have, you've made the wrong choice. Often it's too late to back out, but learn all you can from the experience.

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.