Monday, March 23, 2009

On Keeping Things Managable

Before we get started I need to do a little...

[rant]

Lets talk about project organization a little. Not code organization but where the files holding the code go. I know the standard C# starter project puts the initial code file in the root directory, and that's fine for the main code file and files for any other really important code, but when there starts to be more than 5 .cs files (or .c or .cpp or .js or whatever) in the root, it's time to get organized. 

Somebody started the Spacwar game template with good intentions, there are 4 code directories in the project with 15 base classes in them. Then someone else (I'm assuming) came along to finish the project and completely ignored this organization creating 22 more source files in the root, many of them holding classes that are children of the base classes in the folders. This is the kind of thing that makes Build Masters and maintenance programmers openly weep.

Come on, it's not that hard to create a new class file in a folder or drag and drop them into a folder afterwards. It took all of 5 minutes to move all the children classes into their parent directories and create new folders for those without. Visual Studio doesn't care where the files are as long as it can find them, and you'll probably just leave them all open and use Ctrl-Tab or the Active Files drop-down to select them anyway.

A little organization, build masters and anyone who has to jump into you're project late in the game will thank you.

[/rant]

The first code I decided to tackle was the state machine that controls the screen graph used to managed which object(s) are controlling the graphics device at any given time. On start up you're in a Splash Screen state with the SplashScreen object instance being run, then after a set amount of time the SplashScreen will change the state to MainMenu and the MainMenuScreen will take over, and so on.

The sate machine used by the Spacewar template is rudimentary, without transitional states to aid in starting up and shutting down a given state. So I created a new State base class with internal STARTING_UP, RUNNING and SHUTTING_DOWN sub-states. This should aid situations where the entering or leaving of a screen isn't a single frame task, such as when you want to fade out or have a loading screen.

The screen graph itself is interesting, the main game class contains no graphics drawing code at all, though it still sets up and initializes the GraphicsDevice. Instead it passes all Update and Draw calls to an instance of a Screen extending class stored in a currentScreen variable. Thus a Screen class is like a little XNA application all on it's own, it can handle it's own input and logic and present it's own experience. 

Screens can also hold an instances of another Screen in an instance variable called overlayScreen, which will be drawn after it's holding Screen and can itself have an overlayScreen. This lets you create something similar to layers in a drawing program. For example the Spacewar template project has a nice animated background of a nebula in it's Evolved game-play mode, if this had been implemented as a Screen (it wasn't) then it could have been used as a background Screen 'layer' for the evolved game-play, the main menu screen, the ship selection menu, the weapon selection menu and so on simply by making it the first Screen in the graph.

Initializing the main menu with the nebula background would look a little something like this

currentScreen = new NebulaScreen();

currentScreen.overlayScreen = new MainMenuScreen();

So the active Screen graph is simply:

NebulaScreen->MainMenuScreen

I really like this because it can greatly simplify some complex UI situations for a game, for example I'm expecting my game to use 4 layers in play mode:

GamePlayScreen->HUDScreen->PauseMenuScreen->CursorScreen

The PauseMenuScreen and the CursorScreen will be inactive during normal play but easy to 'switch on' when the game pauses, with the game play still visible in the background, and I plan to be able to reuse them both for other menus in the program.

I changed the game classes “Screen currentScreen;” variable into “List<Screen> currentScreens;” to simplify things in my own mind and so Screens need not be responsible for the layer above them.

Note that if you're having different Screens rendering 3D objects then which object is drawn 'in front' of another is up to the GraphicsDevices' depth buffer and not the draw order. So things drawn on a different 'layer' as I've been calling them can still show up behind things drawn earlier if they are at a deeper depth in the buffer.


Next up: In which I pick a physics engine and try to get something 3D on the screen, running headlong into Spacewars 'simple' shader while stumbling around in the dark (or to be more accurate, in the cornflower blue).

Wednesday, March 18, 2009

Greetings!

Greetings!

This blog will chronicle my adventures in writing an ambitious game in Microsoft's XNA game development platform using C#. I am not new to programming, I've been doing it for two decades now, nor am I new to game programming or 3D engines. Though I haven't used DirectX regularly I fondly remember getting my DirectX 3 Beta CD and more recently I wrote a 3D screen-saver using DirectX 9 and the Open Dynamics physics engine in C++.

So, while C# and XNA are new to me, I'm not anticipating any large challenges in learning the basic technologies involved. I'm sure there will be plenty of challenges involving everything else.

The game idea involves a top down view into a 3D world where you steer a ship over rough (height mapped) terrain avoiding getting destroyed, and maybe shooting things. I haven't decided if the player will get guns yet. “Real” physics will be used to have objects interact in the game world. There are other details, but that's enough to get started with.

So, where to start? I fairly painlessly installed C# Express and the XNA Game Studio which was nice. The C# startup tabs news window always tells me “The current news channel might not be a valid RSS feed...” with instructions on how to change it. But the Options item the instructions refer to doesn't exist. I think another daily dose of Microsoft news is something I can struggle on without.

There are a number of samples, tutorials and Game Templates designed to get you started and well on your way to a functioning game. I poked around and downloaded, installed a number of samples to see what was possible and how complex it seemed. Everything looks pretty good, an interesting blend of power and simplicity. Always a dangerous mix. We'll see how this hold up once I start digging around under the hood.

I decided cut my teeth on the simplest tutorial, the “Your First Game: Microsoft XNA Game Studio in 2D” one in the XNA documentation. Pretty simple, went pretty smoothly. I've now created a game project, added an asset (a JPEG of Dr. Orpheus from “The Venture Bros.”) loaded the asset and have it bouncing around on the screen. Pretty much everything to need to create a simple game (well, besides input... and sound).

On to something more complex. I've determined that the Spacewar game template (I guess they're calling them Starter Kits now?) has what I need in it. While it bills itself as 2D the Evolved mode actually renders in a 3D top down mode which is exactly what I'm looking for. However there are a number of things I don't like about it (the code is kind of a mess actually), so rather than starting my game on top of the Spacewar code-base I'm going to start my own projects and copy over the bits of Spacewar I like.

Next up: Into the code!