As I stated in my previous post, over the next couple of weeks I'm going to be working my way through ALL 48 of the NeHe OpenGL tutorials (in addition to some of my own) in an effort to both show how easy it is to use XNA, as well as to highlight some of the differences between XNA 3.1 and XNA 4.0.
To get us off to the right start, it's necessary to create a "framework" for our applications. This is a basic "game" which we can add to in later demos in order to minimize the amount of work required. Fortunately for us, XNA does most of this for us with the XNA Game API. XNA already handles creation of the main game window, the creations of the graphics device, and the update and draw phases of the main game loop. The only things we need to add to the starting game to put us in line with the NeHe tutorials are:
- The ability to toggle between fullscreen and windowed mode
- The ability to see the mouse when in windowed mode
- The ability to resize the window and handle projection accordingly
So let's get started!
To begin the process of creating the sample demo we just need to launch XNA Game Studio 4.0. This is where we see the first difference. The whole thing is navy blue and .NET-looking. This is because, as you probably noticed during installation, XNA Game Studio 4.0 is built on Visual C# 2010 Express Edition. The new look you see when developing with XNA GS 4.0 is from the newer version of Visual C#. Another thing which was immediately obvious to me was the list of references. As you can see from the image below, XNA Game Studio 4.0 includes a lot more assemblies. More to the point, XNA 4.0 breaks the XNA Framework Library into mutiple, smaller assemblies. This makes it possible for you to completely remove assemblies from the project which you're not going to be using, thus reducing the loading time and the number of assemblies loaded during game execution.
This also makes it easier for the developers. XNA is a cross-platform framework, and by breaking the API into multiple assemblies it allows them to factor out the platform-specific implementations more carefully, while allowing assemblies which are compatible across multiple platforms to remain intact. I should note, I'm not sure Microsoft is actually doing this, as a number of classes in Xna.Framework probably still require multiple implementations. For example, Xna.Framework still contains all of the audio classes (not including the Xact stuff), as well as all of the input classes (not including the new Touch library). So while Xna.Framework.dll could conceptually only contain classes which are shared across all platforms, I doubt that's the case....yet. Moving on.

Another thing you'll likely notice from the screenshot is the way Content Projects are now handled. In Xna 3.1 content projects were embedded/sub-projects of the current project. Now they're isolated projects with "Content References" from the game projects. I'm not sure all of the implications of this yet, but I'll explore it more in a few weeks when I start delving into the content pipeline more aggressively. For now, it's just an observation.
Ok, with the project/file structure stuff out of the way, let's look at some code. This is the code for our starting game, which I will use as the basis for all additional NeHe style demos.
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
As with before, XNA Game Studio likes to include every XNA namespace as well as the kitchen sink when starting a new project. However, in an effort to limit the scope, I removed the namespaces I'm not going to need here. Incidentally, this means you can remove some of the referenced assemblies as well. Don't forget to do that!
namespace JWalsh.XnaSamples
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
KeyboardState prevKeyboardState = Keyboard.GetState();
The next thing you see is the usual namespace, the Game1 class definition, and a few fields. You'll notice that I've added a KeyboardState right away. I've done this because the demos/tutorials in this series will all focus (initially) on the PC. I'll be re-adding some WinPhone 7 and Xbox 360 versions at a later date as well. Anyways... we'd like to be able to toggle between fullscreen and windowed mode, as well as hit ESC in order to exit the program. At least one of them requires a previous state. We can ignore previous state when the user hits ESC.
Two things you'll notice missing from the Game class are the previously deprecated LoadGraphicsContent and UnloadGraphicsContent methods. Yup, that's right. If you were still using those out-dated methods it's time to make the switch, because your code isn't going to compile otherwise.
Next, XNA continues to put the SpriteBatch member field in Game1 for you, and they are happy to initialize it in LoadContent as well, however I've removed it for these demos. When we get to the point we need sprites, I'll re-add it. Until then, no reason to have it around.
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
// Allow users to resize the window, and handle the Projection Matrix on Resize
Window.Title = "JWalsh's XNA Demo";
Window.AllowUserResizing = true;
Window.ClientSizeChanged += OnClientSizeChanged;
}
After the fields is the constructor. Not much has changed here. I still create a GraphicsDevice in order to ensure the proper functioning of the ContentManager, and to make sure my Draw phase works correctly, and I also set the RootDirectory on the ContentManager as normal.
The following four lines are the unique elements of this demo. This ensures the mouse is visible, gives the app a friendly title, allows the window to be resized, and then captures any OnClientSizeChanged events in order to allow us to change the projection matrix used by our 3D math to accommodate the new aspect ratio. I won't be adding that in this demo, but it'll be there in the next.
After that I'm going to add a helper property and our event handler.
protected bool IsFullScreen
{
get { return graphics.IsFullScreen; }
set
{
if (value != graphics.IsFullScreen)
{
// Toggle FullScreen, and Mouse Display, then apply the changes
// on the DeviceManager
graphics.IsFullScreen = !graphics.IsFullScreen;
IsMouseVisible = !IsMouseVisible;
graphics.ApplyChanges();
}
}
}
protected void OnClientSizeChanged(object sender, EventArgs e)
{
}
This property just allows us to easily toggle between fullscreen and windowed mode. After that is the blank OnClientSizeChanged method. Nothing to see here folks.
Then we've got a few (more or less) empty methods.
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
}
protected override void UnloadContent()
{
}
As with previous versions of XNA, you must call base.Initialize() in the Initialize method if you want LoadContent to be called. In this demo it's not a huge necessity. But in all additional demos it'll be essential that LoadContent be called. After those functions we have the Update method. This method is one of the few methods that had any modifications to it for this project.
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Escape) )
Exit();
if (keyboard.IsKeyDown(Keys.F11) && prevKeyboardState.IsKeyUp(Keys.F11))
IsFullScreen = !IsFullScreen;
prevKeyboardState = keyboard;
}
In Update, we capture the Back button of the Game Pad as usual, so we can close the application with the Game Pad. In addition, we get the keyboard state so we can check to see whether ESC is down, or whether the F11 key was pressed. Note: By checking to see if F11 is down NOW, but wasn't PREVIOUSLY, it avoids the nasty situation of changing back and forth between fullscreen and windowed mode a bunch of times because you held the F11 key down too long.
Another thing to note about Update is that while it still receives a GameTime object, the GameTime object itself has changed. Noticeably absent are the ElapsedRealtime and TotalRealTime properties. Presumably, the difference between game time and real time was confusing enough to developers that they did away with wall clock time. Now, holding the window by dragging the titlebar around, or resizing the window causes the game to stop processing. When you release the window, it continues updating as though no time at all has elapsed. For those who still want access to the wall-clock time, you've still got the DateTime class, which gives millisecond precise times.
And finally we come to the Draw method. In this demo the only thing the Draw method does is clear the back buffer. Again, nothing to see here folks!
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
}
}
}
If you enter in the above, and/or download the full project file below and compile/run it, you'll see the following, unexciting screen:

Hopefully this brief look at the starting project and some of the changes to the API have been interesting. In the next project we'll starting drawing some triangles to the screen.