2009
11.18

Icefall uses literally dozens of textures… (and it will probably be ‘hundreds’ by the time the game is completed).

Textures are used for everything, from the mouse cursor, menus, fonts, buttons, to the game world itself, spells/action icons, monsters, equipment… everything.

Although my own main PC has 512MB of video (texture) RAM, not everyone does! And
following on from my minimum requirements post, I don’t really want someone’s video card memory size to be a limiting factor if everything else meets the requirements, so Icefall needs a way to manage things when there are more textures than there is video memory.

I don’t want each bit of code that uses textures to worry about whether they’re loaded or not, so the logical choice is to encapsulate all of the texture handling into one place: I call the class that handles this the TContentManager (“content” because it also handles sounds, fonts, music, etc.).

When the game code asks the TContentManager for a texture: the first thing it does is look to see if that texture is already available in video memory: if so, it just hands out a reference. Easy! If not, it retrieves the filename for that texture from Icefall’s ResourceDatabase, and attempts to load the texture from disk. If that fails, it looks at why it failed: if it’s D3DERR_OUTOFVIDEOMEMORY, the next step is to unload some other texture and try again, repeating until the load succeeds or we have no loaded textures left. (If it still doesn’t load, or if the texture load fails for some other reason, it’s goodbye Icefall).

Programmatically:

function TContentManager.GetTexture(ID: TTextureID): TLXTexture;
var
   HRes: HRESULT;
   NewTexture: TLXTexture;
   FileName: String;
begin
   if TextureLoaded(ID) then
      exit(Texture[ID]);

   FileName := ResourceManager.Textures[ID].FileName;
   repeat
      HRes := LXLoadTexture(FileName,NewTexture);
      case HRes of
         D3D_OK:
            Texture[ID] := NewTexture;
         D3DERR_OUTOFVIDEOMEMORY:
            UnloadTexture(0);
      else
         // Fatal error!
      end;
   until TextureLoaded(ID);
   result := Texture[ID];
end function;

UnloadTexture is a method that unloads a texture. It takes a TTextureID as a parameter, but passing 0 in this case tells the method we want it to choose a texture to unload itself. This is where it gets interesting.

Before I got to this, I originally had set up a few states so that they explicitly called TContentManager.UnloadTexture to release textures when the game left that state (e.g. the game would unload the ‘Option-selection’ texture when the player closed the Options dialog). However, this turned out to be sub-optimal for several reasons:

  • Players might well leave and re-enter states (like Options) several times to accomplish whatever it is they’re trying to do.
  • It doesn’t make use of extra video memory: it keeps loading from disk (or the disk-cache anyway) while the extra video memory stays idle.
  • I had to explicitly declare what textures I was done with. Not a problem really but ‘just another thing’ that I had to do when changing states.

So now I no longer explicitly release anything. UnloadTexture always chooses the texture to unload that was least-recently used (a linked list makes this a very fast and efficient check – no timers or array scanning involved). In practise “least recently used” turns out to be about 97% optimal (when simulated against a 100% optimal algorithm which is permitted to see the future when deciding what to unload) so it’s virtually perfect – substantially better than my explicit declarations were.

If for some crazy reason the user doesn’t want Icefall consuming all of their video RAM*, I can chuck in a call to IDirect3DDevice9.GetAvailableTextureMem and trigger UnloadTexture if it’s below some specific amount. Alternatively, I could keep a sum of the amount of texture memory I’m using, and trigger UnloadTexture if that amount threatens to exceed 32MB or whatever (I haven’t decided yet).

The point is, if you find yourself manually balancing resources, it’s probably an excellent idea to profile your resource usage and see if you can find a pattern that will let you just automate the whole thing**. You’ll save yourself much time and your code will be cleaner and more flexible.

*Note: this only actually matters on Vista or Windows 7. Under the Windows XP model, multiple applications can’t share texture memory anyway. As soon as an application takes focus, DirectX invalidates all texture resources belonging to everything else (forcing them to reload from system-memory or disk when they get restored). The WDDM (Windows Display Driver Model) in Vista “understands” video memory, and can share it amongst applications. This is one of the reasons DirectX 10+ can’t be backported to XP: XP has no concept of video card resources.

**If you’re creating a game frame-rate locked or just frame-rate dependent, you might still need to explicitly acquire and release resources (e.g. between levels), because a 10ms pause at an unexpected point in your game could be noticeable or detrimental. Either that, or move the resource acquistion to another thread and have low-quality ’emergency’ textures to display while the real ones load… this is a very common technique for FPS games.

2009
11.16

I’m currently reading a book about the evolution of Windows. One of the most interesting things I keep finding is how stupid some 3rd party application developers must have been…. for example, it seems to have been common practice that if you wanted your app to grab a particular Windows setting (let’s say the Fonts directory), instead of a quick MSDN search, which turns up both the SHGetFolderPath and SHGetKnownFolderPath functions (either of which is exactly what you want), these programmers fired up RegEdit and searched for the path of their own Fonts folder… the first key they found, they used as the parameter for a call to RegOpenKeyEx and they read the value that way.

To me, that is not only a frighteningly ignorant and dangerous way to develop software (you’re not going to discover caveats & usage notes by browsing RegEdit!) but of course this is not the supported way to do it (how could any sane developer think otherwise?), and of course that app would have broken immediately on any new of Windows had MS not added a compatibility shim to watch for that program checking that buggy key, and substituting in a quick call to obtain the real value…

This isn’t backyard programmers writing in VBA in Excel to accomplish some one-off business task, either.. it’s commercial software that did this, written by professional developers and sold to unsuspecting customers for big cash. Scary stuff.

The only question worth pondering here is: was this ‘grab something promising out of the Registry’ technique better or worse than just hard-coding “C:\Windows\Fonts\” into the application? (I’m not 100% sure but it seems very likely there’s a shim out there for programs that did that, too.)

2009
11.12

I thought I’d cover this rule first, because I listed it as number one and also because it’s probably one of the most controversial. Let’s begin: a simple Why/Why Not argument should suffice for this one:

Why Allow Windowed-mode:

It’s more convenient for your users. Some users multitask (gasp!), even while playing games. This is much harder to do when your game is Fullscreen. I suspect this is a part of why games like Minesweeper and Solitaire get so much play-time. They’re built into the OS, sure, but you can also fire them up and play while you’re waiting for something to download/compile/whatever. Very handy!

It’s more convenient for you. Debugging is hard, and debugging fullscreen is harder! My own game engine (in debug builds) has a feature to throw a debugging/log window up so I can watch internal game messages etc: you can’t do this if your game is always fullscreen. Not only that, but if your game crashes at some Direct3D stuff (which can happen in early builds, before you lock down your video interface code), it’s very tricky to find a cause when you’re staring at a blank screen. A blank window on the desktop gives you more context and options.

It makes paying certain Windows taxes more obvious. If you’re running in Windowed mode while developing, you’re going to be hitting the titlebar close button, you’ll be minimising/maximising your game Window, or maybe just clicking other apps, stealing your game’s focus. Because you’re doing these things, you’re much more likely to take the time to ensure your game handles them correctly. Fullscreen games are required to handle these situations too, you know: but some of them never get around to it! (Civilization 3, which is always “fullscreen”, can experience a rather ugly crash if I dare to click something on my second monitor while I’m playing).

It’s future proof. You might think your fullscreen game is pretty cool, what with it supporting resolutions right up to 1920×1080, but who knows what the future holds? How well will your fullscreen game look on some giant desktop running 12,000×12,000 pixels? Or do you just expect no one will be playing it then? (if you don’t, then code this way: you’re sure to be correct). Windowed mode doesn’t solve this completely, but it gives your users more options.

Ok, hopefully you can that there are always scenarios where that option would be valuable, but you might not be convinced to allow it in your game. Let’s take a look at some reasons why not:

Why NOT allow Windowed-mode:

It’s hard to code. Oh no, now all of your video code has two scenarios to account for! Well, actually, no it doesn’t. Once you’ve initialised Direct3D correctly, none of your other code even needs to *know* it’s drawing to a windowed area of the desktop. And initialising Direct3D to support either Windowed or Fullscreen mode is easy! I’ll bet you $5 that the sum total of video code required to support this option is LESS than the amount of code required to present the option to the user and store the result.

Fullscreen is more atmospheric. Atmosphere is important in my game! By all means then, make fullscreen the default. Plenty of games do. I’m just asking for the option!

But I want to retain control. Fuck off! The user is in control: it’s their computer. Besides, if the user really wants to window you, they can do it: they can fire up a virtual machine and lock you inside it: good luck getting into fullscreen mode then. Of course, if it’s that important to them, they’re more likely to just uninstall you and go play something with a windowed option.

And there you have it. Why I believe every game should support Windowed-mode!

2009
11.11

In Windows (like every operating system), when you’re writing an application or game there are certain things that your application is responsible for handling: some of them are easy, some of them take a little bit more effort. On his excellent blog, Microsoft’s Raymond Chen calls these responsibilities “Taxes”, and there are good reasons why you should pay them. Windows taxes include things like:

  • Respond to Windows messages correctly
  • Respect user action (don’t silently cancel a Sleep request)
  • Non-standard installs (don’t assume C:\Windows!)
  • Run fine as a Standard User
  • Respect the user’s settings

Raymond talks about more complex taxes too (internationalisation, heirarchical file systems), but I’m sticking to what I’m comfortable with!

Unfortunately, amongst all applications, games appear to be the worst at being good Windows citizens, there are far too many games out there (not just freeware ones either) that don’t pay any of the above taxes, and (to sustain the metaphor) some start trying ‘tax-fraud’ schemes like:

  • Trying to disable Alt-Tab
  • Refusing to be minimised (automatically restoring themselves after 1 sec)
  • Preventing the system from shutting down

I might make this another series because there’s plenty to talk about, and most of it’s not even that difficult these days: you just have to be aware of the situation, and what the correct behaviour is. (I must admit I never gave thought to multi-monitor situations before I got my second monitor).

For now though, I will limit myself to a list of ten ‘golden rules’ which I believe all games should obey, at a minimum (not all of them are Windows taxes – some of them are just treating your users properly). In fact I will expand on some of these in later posts too, because they’re worth talking about.

Top ten Golden rules for Games: being a good Windows application

  1. 1. Fullscreen games: always allow an option to run in a Window.
  2. 2. Provide gamma and volume controls, and separate music from sound.
  3. 3. Always allow your game to be paused, saved and quit. At any time.
  4. 4. Provide a way to skip anything non-interactive: from cutscenes to credits.
  5. 5. Respect multi-monitor: If you were dragged to monitor 2, next time open on monitor 2.
  6. 6. Respect the filesystem: don’t open files in Read/Write mode if you only want to read from them.
  7. 7. Respect security: A game does not need an Administrator account to play!
  8. 8. Respect UI settings: if the user has selected ‘Use Large Fonts’ in Windows, use larger fonts in your game!
  9. 9. Respect sessions: if the user logs off/hibernates/shuts down, handle it gracefully. Don’t try to block the action, and don’t lose their progress.
  10. 10. Adapt to a changing system: if you last opened on 1680×1050, but the system now says the monitor can’t support that, open in a res it can support.

I’ll talk about how to implement some of these (and why they’re so important) in future posts.

2009
11.09

Class Balance

Class balance. In the RPG sense, class balance means that the various different character types (wizard, warrior, druid etc) are “balanced” in the sense that the difficulty of the game, and your character’s ability, remain approximately the same regardless of your choice of class. (and Race: Humans, Elf, Dwarf etc)

Obviously, in an online-, or otherwise multiplayer game, class balance is critically important. If your wizards can always beat your warriors, the game will NOT be fun for people who choose to play warriors. And they won’t switch and play wizards, either: they’ll just stop playing and find another game.

But is class balance critical in a single-player game, like Icefall? In many roguelikes, the classes aren’t balanced: some classes and races are substantially more powerful than others (e.g. High Elves might come complete with bonuses to all their stats, Resist Poison, etc etc – with no downsides), and players are actively encouraged to start with the easier classes.

A third alternative is to balance classes not for ‘difficulty’, but for ‘effort’: you might be free to roll a powerful Immortal instead of a lowly Human, but the Immortal will require twice as much experience to gain every level.

I’m not at the stage of class balancing yet – but I’m thinking about it.

2009
11.05

What’s a reasonable minimum spec to aim for these days?

With Icefall, I’ve already taken the decision to target Direct3D9 – I get a lot of extra capabilities compared to DirectX8, and it still works with Windows XP unlike 10 or 11… a pretty simple decision.

But what about in terms of video memory? And system RAM? What’s a realistic minimum these days? Icefall is a freeware, turn-based RPG, so by rights it shouldn’t require a leading edge PC, but I need a specific target to prevent limiting myself unnescessarily.

Howzabout 32mb video, and 512mb RAM? I think that fits most every PC you could buy in the last few years… and should be enough for some reasonable effects. Anyone got any thoughts on this?

2009
11.02

Should Icefall come with an Installer/Setup program?

My previous games (like the Five Hundred card game) didn’t require any installation at all: it assumed you had DirectX7 (the game just failed if you didn’t), and all of the files it needed were in the same directory as the EXE itself. You just unzipped it to wherever you liked, and double clicked the EXE to play. To uninstall, you just delete the folder.

Icefall is a little bit more complicated. All of the game’s data is still a relative path from the EXE itself, but this time it needs a specific Direct3D9 library installed (one that doesn’t ship by default with the rest of DirectX, but that other games may have already installed). So I need to include the DX Installer.

The Microsoft DX installer is smart enough to not overwrite a newer version of the same library (and you can only include the needed library – I don’t have to include the full DX9 100mb installer!), so I don’t need to worry about that stuff, but the question is, should I include this as an ‘optional’ installer that the user can run if Icefall doesn’t run immediately, or would it be less confusing to just make a full install program that all users run, and call this as a part of it (I could throw out options for the Start Menu etc. at the same time).

I’m leaning towards making a full installer, mainly because the DirectX library is designed to never be uninstalled (it’s a shared library, and other D3D9 apps might use it), and it would be very confusing for users to have an installer with no corresponding uninstaller… also, I may as well get with the program and use the Start Menu, registry etc. the way Windows programs are supposed to. Does anyone have any opinions on this?

Bonus trivia: I get quite regular emails about my Five Hundred game, since it made it onto lots of the large ‘freeware games’ websites and was quite well received at the time. One of the common questions people ask these days is “how do I uninstall it? It’s not in Add/Remove programs”. They must have forgotten that they never installed it in the first place, just unzipped. A few of them are still confused when I tell them to just delete it, so it’s clearly not what today’s users are expecting.

2009
10.31

Virtually all programs have this, a central ‘game’ loop that grabs user input, updates game logic, redraws the screen. At it’s simplest possible level, it usually looks something like this:

repeat
   Input;
   Update;
   Redraw;
until Quit;

The problem mainly comes in that middle section, Update. For any game, there are a variety of different states you can be in (main menu, options screen, credits, playing game) and for most games, “playing game” breaks down into a whole lot more states by itself. For my simple 500 Card Game, I had states “bidding”, “dealing”, “choosing kitty”, as well as playing. If you’re not careful, your Update procedure can end up looking like this:

Procedure Update;
begin
   case State of
      STATE_MENU:
         // wait for a menu click
      STATE_OPTIONS:
         // handle user input
      STATE_CREDITS:
         // roll some credits
      STATE_GAME:
         case GameState of
            GS_PLAYING:
               // handle user input
               // update some monsters
            // etc
         end;
      // STATE_ even more stuff:
   end;
end;

So far, so big and clunky. It gets worse when you have to handle nested state transitions: in my card game, someone could be playing, then go to the Menu and come back. So I had to have a variable ‘LastState’ that remembered where they were, so they could go back to it. But it’s worse than that, because they might go to the Menu, then go to the Options screen: and when they came back, they’d still want their current game to not be lost! My card game was simple, so I managed this as simply as I could: when entering the ‘menu’ state, the menu grabbed it’s own copy of LastState, and it restored this value when the other screens (Options, Credits etc) returned to it, so there was always a way back to the game. This was the simplest case, because every state had exactly one other state that it could be transitioned from (you couldn’t get to Options from Game without going through Menu).

For Icefall though, the stakes were raised. I wanted the Options screen accessible from in-game, as well as in the initial menu. And there are many more states that the game can be in, and some of them should not be returned to (e.g the “create character” screen), so rather than a gigantic and ugly Update loop, I went back to good old OOP and implemented a class-based state stack.

Icefall has a central “State Engine” that looks after the current state stack, handles transitions between them, and calls whichever state is ‘on top’ during the main loop. The State class looks something like this:

TIceState = class (TIceClass)
   constructor Create
      (StateEngine: TIceStateEngine; 
       Transition: TStateTransition);
   procedure OnEnter; virtual;
   procedure OnLeave; virtual;
   procedure Update; virtual;
   procedure Redraw;
   // other useful state methods
   destructor Destroy; override;
end;

Essentially, for every state the game can be in, I have a corresponding class that defines it’s specific behaviour in Update. I can also do other ‘maintenence’ (e.g. ensure the right music is playing) by overriding the OnEnter and OnLeave procedures. The game can change states by constructing a new TIceState instance, passing it a reference to the state engine and describing the type of transition to use (e.g. whether to nest the state [for a trip to a Menu] or just progress to the new state with no way back [like a character create screen]). You can also leave a state just by destructing the class instance: the state engine will pop back to the next highest state on the state stack, or quit the game if there are no states left (e.g., you just hit ‘Exit’ from the Main Menu). 

The state engine takes care of nested states and transitions, and someone’s exact state in the game can be saved (if needed) by storing the entire state stack: while I’m unlikely to want the game to be saved while on the Character Create screen, it’s good to know I can safely save the game while in shops, or at any other point, without even worrying about special handling code to cover all the situations.

Another interesting thing I have done is move the game’s “loader” (the part that loads textures, sounds, music, fonts, databases) into it’s own state, and just made it the very first state that’s pushed onto the stack, and it takes a parameter to the state to transition to when it’s done. It takes the whole ‘loading’ step out of the main game code, which makes that much simpler, and I can make the loader just load the resources I’m going to need right now: some other state (like the credits) can always call it again later to load specific credit-y images.

I can also use the the same game engine to build other tools like the Map Editor: the only difference between the map editor and the game itself is that it compiles in a different set of states: when the map editor has loaded, it launches itself into a TMapEditorState instead of a TMainMenuState.

Overall, having a state stack is very flexible, quite simple to use and maintain, and overall a vast improvement from the ‘giant case statement’ I was using previously.

2009
10.30

Last time, we looked at the inheritance style of object-oriented programming in detail. Now let’s look at the alternative: composition.

We’ll use another example from Icefall to illustrate the differences. Icefall has a central ‘world view’ that shows the player and their immediate surroundings (items, monsters, terrain, etc). The world view also shows animations (e.g. fireballs, weapons swinging, speech bubbles, etc) and it’s the animation code that we’ll be looking at in detail today.

I designed this feature around each animation being a class instance, with the class methods and properties making it easy for the game engine to control the details (lifetime, location, save/load etc etc). I knew I’d have several different types of animation, so my initial implementation chucked all that ‘management’ functionality into a TAnimation class, and left virtual methods for  things like Process and Draw for descendents to implement. After creating a few basic animations, my class hierarchy looked like this:

TAnimation
   TAnimText
      TAnimSpeech
      TAnimTexturedText
   TAnimTexture
      TAnimMissile
      TAnimExplosion
      TAnimMelee

Animations with text (i.e. picking up an item) were a subclass, and speech bubbles (or text with a textured background) were subclasses of that. Missiles (like fireballs) were a subclass where the animation moved from one place to another (and was rotated to face the right direction), and Explosions were in one place but had a series of animation frames over time. Melee animations showed a weapon and some motion-blur, sweeping out to attack a monster/player.

The problem with this system, which I discovered after adding TAnimTexturedText (specificially to show damage-dealt as a number on a bloodsplat-graphic background) was that most of the subtypes only varied in very small ways, and the overhead of naming, constructing and using each subtype took more effort than defining the subtype itself. Also, the ‘event’ system I was setting up for Icefall was supposed to allow for animations to be defined dynamically in response to any spell or event (and new events added in data files without recompiling the game) – but the code that supported this was going to be very complex and ugly if it had to choose between all of the different constructors each time and pass a specific set of parameters to make it happen.

So, I rewrote the animation subsystem to bring any functionality that I could possibly re-use into the parent class: now, all animations had a Texture property, a Rotate property, Frames, Movement, Sound… which could all be left at Nil or 0 if not needed. My new, composited animation hierarchy looked like this:

TAnimation
   TAnimText
      TAnimSpeech

As soon as I did this, I found that it was not only easier to manage the sources, but that features of the parent class ended up getting used more often than I anticipated: e.g. giving an explosion a random value for Rotate made each explosion look slightly different, and I could apply a small Movement value to Text to let it ‘float’ upwards from where it first appeared: new and useful functionality essentially for ‘free’.

Note that I kept AnimText separate from the parent, because there is some substantially different functionality: it has text (which directly contributes to the size and position of the anim), which is also dynamic, and there is some special logic to ensure two text animations don’t overlap each other. It made sense to move this code out into a specific class where it could be closely tweaked. Speech is different again, because there is a “speaker” creature that it it linked to: the speech bubble needs to move around with it’s speaker, disappear if they die, etc.

In summary, now that the TAnimation class is composited, it’s significantly ‘better’ code than before:

  • Fewer types to worry about
  • Much easier to follow the logic of the code in a single class
  • Can trivially re-use functionality developed for one subtype in others
  • Much easier for other code to utilise this class effectively

So, my conclusion in this small series is:

Use composition in your classes, unless there is substantially different behaviour, or external code needs to interact with a specific subtype in a special way (e.g. TAnimation itself is inherited from TWorldObject, because the world view needs to interact with animations in a specific way).

Next time, I’ll find something different to ramble on about.

2009
10.29

This is all too common. You’ve developed some minor tool to meet a specific purpose, whether it’s a batch file, JavaScript, Visual Basic macro, whatever.

You know other people around the office will use your tool, but it’s not worth the investment in handling real error cases or writing proper documentation. Instead, you just throw in a message saying “If you see this message, talk to Jim!” , safe in the knowledge that all of the users are less than 20 metres from where you work.

Please, resist the temptation. These tools will often, completely by accident, end up with a lifespan that exceeds your term of employment! Two years later, this message pops up and confuses the hell out of the user.

A similar thing happened to a colleague of mine. A spreadsheet that ran a simple virtual-rugby sweep for his workplace, allowing users to enter their predictions and email them away. If a user tried to trigger the code to calculate the winner, they got a helpful dialog box: “Sorry, you’re not Jade Baxter! Nice Try”. Needless to say, after he left, virtual-rugby remained popular, and because he transferred to a different part of a large organisation, it caught up with him.

Now, we all use it around the office whenever any function or data is withheld from any person, for any reason, at any time. Sorry: you’re not Jade Baxter!