One of the most important parts of any game - or any program for that matter - is the User Interface, also known as the UI. It is also called the Human Computer Interface (HCI) or the Man Machine Interface (MMI) or the Human Machine Interface (HMI). We don't usually call it a Man Computer Interface (MCI) to avoid ambiguity with the Media Control Interface and the Medical Council of India.
It's a lot easier for me to type UI, so that's what I'll call it.
The two base portions of the UI are the Input and the Output. In our game, all user input is registered through the game controller. All output is directed to the player from the monitor, speakers and force-feedback on the game controller.
There is an extremely well-done starter UI available from the
XNA Creator's Club called the
GameStateManagementSample that is a very popular jumping off point for a lot of XNA games.
We didn't use it.
Well, I shouldn't say that we didn't use it
at all. I garnered a lot of useful ideas from that project - including the concept of a ScreenManager component class and a base Screen class used by the ScreenManager component - although we decided early on that we want almost everything to be data-centric, including the UI. The GameStateManagementSample is not data centric. Everything in that project that drives the behavior of the UI is hard-coded in the source.
The upshot of writing a data-centric game like this is that if we ever need a non-programmer type to adjust pieces of the game (without disturbing the very busy - and extremely good looking - programmer) they should be able to do so without running into too much trouble, provided they possess the knowledge of reading and typing, and have even the most rudimentary deductive reasoning skills.
Every screen that you see in our game - from the title screen, to the splash screen to the screen where the game itself is played - all are configured using external data that can be modified by anyone with a text editor (and access to the game content, of course. However, I'm afraid, that is a very short list of people).
Another excellent benefit of writing the game like this, is that it saves tons of compiling time when we're making changes to the contents of the game, without having to change the source code.
When a project reaches a critical mass, compiling to software becomes a time-consuming and quite boring task. If you make a typo when making a menu item that needs to be fixed, or if you need to add a new contributor to the credits, you can make these changes in a configuration file, and rebuild the project without having to compile everything again. This makes tweaking little things in the game much less frustrating. And fast.
I said above that the GameStateManagementSample has much hard-coding to define the behavior of the UI. For instance, if you select a menu item, a handler is written in the source to determine which menu item is selected and what should be done in response. Our design, being much more variable in nature, does not define these behaviors in the source code. So the software needed a mechanism for determining what to do in response to, say, the player making a menu selection. Or the splash screen timing-out. Or the player skipping the storyboard narrative. Or anything that signals the next part of the sequence.
Enter the Sequencer.
I'm not going to go into all the details - on account'a I don't know how Carl feels about me spilling the proprietary guts of our operation on the interwebs - but I'll try to give you an overview of what it does without invoking the words "Magick" or "Miracle".
Basically the Sequencer is a class that loads a list of sequence items that defines the flow of the game. Different items within the sequencer can be called up by performing various actions in the UI. For instance, on startup, you will see our splash screen (the Small Cave Games logo + a groovy signature sound effect), which is Sequence Item Zero. Item Zero is the the default sequence item, and all future sequence items are launched after that. After the splash screen, the Title Page sequence item is invoked, either by the user clicking the "Skip" (B) button, or waiting until it runs its course, which includes admiring our logo and listening to the Small Cave Games sound effect.
The title page sequence item allows the user to invoke one of several different sequence items, by choosing different menu items. Selecing "Start New Adventure" will invoke the Start Game sequence. Selecting "Load Game" will invoke the Load Game sequence, etc.
That's about it for the sequencer. All the sequence items are stored in a sequence configuration file, and every player input action that causes a sequence item to be invoked is also stored in a configuration file. It's all about the data. Very flexible. Very scalable. Very slick.
If I do say so myself.
The last part of the UI that bears mentioning in this post is the Transition Manager. One of the things I noticed about the GameStateManagementSample is that everything transitions from one state to another. There is no "state-popping" in that application. I cannot express in words how much I agree with this approach. Objects should never pop from one state to another. They should glide smoothly from one state to another over the course of time. Even if that time is 1/10 of a second, it's better than a jarring instantaneous mode snap.
However, I don't use this apparoach only in the UI. I use it everywhere. I use it to transition our in-game camera from combat mode to navigation mode (I'll tell you all about that some day), I use it in-game when the player exits one region and enters another. I use it with narrative storyboards and subtitles. I use it in the game when the player opens or closes an auxilliary screen. I use it during HUD transitions (I'll also tell you about that some day). I use it ... pretty much everywhere.
So instead of writing all these transitions into the source, I extracted it all into a neat tidy little package called the Transition Manager. The transition manager allows for any game element to switch from one state to another smoothly. The element defines the amount of time it takes to transition in, and the amount of time it takes to transition out. It provides a property that indicates amount along the current transition (if any) the transition has elapsed. And although it pained me to do so, I allowed for instant transitions. (Just in case).
Hopefully we won't use that. Ever.
That's about the long and short of the UI. The rest of the UI is pretty basic stuff. If I stumble across a part of the UI that I forgot and bears mentioning, I'll stick it up here. I'll probably write a long-winded rambling post soon about the tile engine.