XNA: a first look
(level : easy)


When I first heard about XNA last year, I was immediately interested in learning more about it. I guess the ability to write and run my own programs on the Xbox 360 I use to play games at home sounded too tempting :-). XNA has been available for a while now, and a first update called "1.0 Refresh" was even released in April, so let's have a look at what's inside the box.


What is XNA?

Actually, I will start with what it is not: XNA is not a game engine, or a full featured 2D and 3D engine. If you want to develop a game, without having to program anything but the game logic, then you'll need something else on top of XNA (like TorqueX for example, but there are other options).

XNA is more like a managed and easier to use version of DirectX, that can run both on PC and Xbox 360. It also implements a new content pipeline, which gets totally integrated into Visual Studio Express. Maybe this doesn't look too exciting yet, but let me explain my definition a bit more:

Getting started

Here is what you need to develop applications using XNA:
Also, you only need a graphics card compatible with Shader Model 1.1 in your PC, although having one supporting Shader Model 2.0 is recommended. That may seem like a lot of things, but actually if you already have a decent PC and an Xbox 360 connected to Xbox Live, and since all the software is free, it is just a matter of downloading and installing a few programs (this can still take some time, and you need to be careful about the order), and buying the Creators Club membership if you want to run your creations on the console. More information can be found here.

Once everything is set up, you can create a template application for your Windows Game or your Xbox 360 Game in a few clicks, like you would do for a Windows or Console Application for example (using the 'New Project' dialog box).


Unfortunately, you have to choose: you can not create a project with configurations corresponding to each platform, if you want to run your program on both targets then you need 2 separate projects, which is counterintuitive and annoying. Sure, the projects can share the same files instead of having their own copies; but each time you add a new class or asset on one side you have to do the same thing on the other (and set the same properties for the asset), and when you want to test on both PC and console new functionality you just implemented, you end up working with 2 instances of Visual C# opened at all times. To me it doesn't make sense, I hope this issue will be addressed in a future version.

As I mentioned earlier, some boring things like the creation of a graphics device are already taken care of, by the Microsoft.Xna.Framework.Game class. What that means is after the wizard is done creating a template application, you have a working program that you can start modifying (it displays a blue background and doesn't print "hello world", but it could, since text and font support has been added to XNA 1.0 Refresh). And this program looks pretty simple: initially there are only 6 functions in the class where you are supposed to add your code (of course at some point you will have to create more classes and functions, if you want to avoid "spaghetti code".

To learn about the classes and functions of the XNA framework, and how to use them, you can either read the documentation and do the tutorials, or have a look at some code samples and starter kits (see http://creators.xna.com). Building the Spacewar starter kit (included in XNA Game Studio Express) is probably a good idea anyway, in order to see how content is handled, or to try deploying a project to your console (which should not be difficult, if you follow the steps described in the documentation or on the aforementioned website). Also, modifying existing code is usually easier than writing something from scratch, especially if you don't have much experience as a programmer.

On the .NET side, you need to know that only some namespaces and classes are supported on the Xbox 360; the missing ones are usually irrelevant to console games (Windows Forms are not included, for example - the full list can be found in the documentation, under Programming Guide / .NET Compact Framework for Xbox 360). The size of your game (executable and content) is also limited to 2GB on the console (that should be enough! I don't know how much time it would actually take to deploy that amount of data...), and to finish with the limitations on Xbox 360, only 4 of the 6 hardware threads are available for your program (which is already pretty good - the other two are reserved by the system).


The content pipeline

Integrating art assets (meshes, animations, textures, effects, sounds, etc) into a game usually requires quite a lot of code: the engine needs to recognize several different file formats, exporters sometimes have to be written for some content creation tools, and each platform can require the data to be modified (for example, the endianness is not the same on PC and Xbox 360). That's why XNA Game Studio Express introduces a new content pipeline, which basically becomes part of the process of building (as in: compiling) your game. Here is how it works: first you add the art files to your C# project, and use the Properties window to give each asset a name, and specify what Importer and Processor will deal with it. Then when you build your source code, Visual Studio also figures out what assets have changed, and imports and processes them again to update the corresponding output files. These files are where your executable finds the data it needs, when you load your assets by name with the ContentManager class of XNA.

Here is an example: let's say you created a texture in Photoshop or any other program you want, and saved it in the TGA format. Using the "Add / Existing Item..." command in the Solution Explorer of Visual C# Express, you added it to your project. Since XNA recognizes the .tga extension, it automatically selects the appropriate Importer and Processor for you, and after you choose an Asset Name, the properties of your texture should look like this:

When you build the solution for the first time after adding the texture, or after modifying it, the content pipeline uses the importer to load it in memory, and the processor to run some operations (like generating mipmap levels, or compressing the texture). Finally, a writer saves the results to disk (somewhere under the \bin folder), in a file that would be named buffyTex.xnb in the example (the Asset Name, followed by the .xnb extension). On the game side, only one line is needed to load this texture:

Texture2D buffyTex = content.Load<Texture2D>("data/buffyTex");

'content' is the ContentManager object of the Game class generated by the wizard; it uses the requested reader (here a Texture2D reader) to load the asset specified. The "data/" folder in the asset's name shows you can organize your art as you want, you don't have to put everything in the same directory (in the above Properties, see the full path of my example texture).

Which file formats are supported by XNA 1.0? Fbx (an Autodesk format) and X files for meshes, bmp / jpg / png / tga / dds for textures, fx for effects, spritefont for fonts, xml for whatever you want, and xap for sounds. Xap is the output format of Xact, the Microsoft's audio creation tool that comes with the DirectX SDK; the sounds imported in this tool and organized in banks are actually wave files. But you can also add support for other formats in the content pipeline, by writing you own importer, processor, writer and reader. The related documentation is not very thick right now, but I tried it and it's doable. The real question is: is it really necessary?

Initially I thought it was, because even if I didn't have any additional processing to do on some files I exported from 3DS Max in my own binary format, I still wanted to be able to load these files both on PC and Xbox 360 with the same code. The truth is: you can already do that without the content pipeline, it works out of the box! :) Let me explain: to load a binary file in C#, you use the BinaryReader class (the ContentReader class of the content pipeline actually derives from BinaryReader), which has several methods to read a byte, a float, an Int32, etc. I mentioned endianness is not the same on the 2 target platforms, which means the code to load would work on PC (since the files were created by a PC program), but not on Xbox 360. Except that the .NET compact framework for the console swaps bytes on the fly for types that require it, et voila! Thanks to that, the code to load my binary files is auto-magically cross platform, which is extremely cool.

Another concern could be deployment on the Xbox 360: if the content pipeline doesn't know about some data files, will they still be copied to the console? The answer is yes: everything you put under the output folder of your project (the one where the executable is generated) is deployed, this is convenient. So, to answer the initial question, it is not necessary to add support for your own file formats in the content pipeline if you don't have a need to process them here, and you basically only have to write the code for a reader. But you may still want to extend the content pipeline, if it is important to you that your files are loaded using the ContentManager, like it's done for other resources.


Main differences with DirectX

The main difference with DirectX 9 is that the XNA Framework doesn't support any Fixed Function Pipeline for rendering, everything has to be drawn using shaders (like with DirectX 10). There is a good reason for that: the Xbox 360 only supports shaders. Swap chains, which were the recommended way to render to several views, are gone too: render targets and depth/stencil buffers can be used instead.

Some objects, for example index buffers, that used to be created through the graphics device (with a call to CreateIndexBuffer in this case), are now instantiated directly, with the constructors of their class taking the device as a parameter. Writing data to a buffer is also different, and doesn't require the "lock - copy - unlock" sequence anymore, everything is taken care of by the SetData function of the buffer's class:

// 'data' is of type VertexPositionNormalTexture[]
SetDataOptions dataOptions = SetDataOptions.None;
vb.SetData<VertexPositionNormalTexture>(data, (int)pos, (int)nbVtx, dataOptions);

I also already mentioned the new input classes that allow you to access the keyboard, mouse, and Xbox 360 pad very easily; however, if you want to support joysticks or other pads on the PC, you may still have to use DirectInput as well. On the math side, the XNA Framework uses a right-handed coordinate system, unlike DirectX. Finally, people who were using D3DX will notice other big differences, since some of the functionality it contains is not available (yet?) in the XNA Framework (animation support, for example).


Missing features

XNA is a promising API, but it's a very young one, and some important features are missing in the 1.0 Refresh version. In my opinion, the biggest one is network communication between the console and the PC while the game is running, because this prevents tools from sending commands to the game, and getting some information back from the console. This means that if you want to enable / disable some debug information or cheats for example, or tweak any value in a level while playing, you have to implement some kind of console window or HUD and display it on top of the game, instead of using a Windows Forms application with a nice user interface. Even taking a screenshot on the Xbox 360 becomes tricky, as demonstrated here. This kind of communication is already possible though, since the Remote Performance Monitor for the Xbox 360 (a tool distributed with XNA Game Studio Express) is able to display in real time some statistics coming from the console, and the full feature is actually expected to be available to programmers with the 'Pro' edition of XNA (if such a thing is released one day).

Another request that shows up a lot on the forums is the ability to play videos and mp3 files. Currently, only wave files are supported by Xact, which is ok for short sounds, but takes a lot of space (on disk and in memory) for music. Regarding video, there is no equivalent to DirectShow in XNA, as far as I know there is nothing at all. Same thing for animations: you can import meshes with several underlying bones (for example, characters), but unlike in D3DX there is no class to animate them, which is very restrictive to say the least. Some people are working on an animation library for XNA, but I haven't tried it and can't tell you what it's worth.

Having access to some Xbox Live functionality at some point would also be good, since even Arcade games usually feature at least an online leaderboard, and multiplayer games are more and more popular. One thing that is probably much more critical for the success of XNA though, is the ability to distribute games on Xbox 360, without requiring each player to have a creators' club membership. You can bet Microsoft is working on this one, but how and when it's going to happen remains a mystery.

Finally, my wish list also includes occlusion queries, text input using the dashboard GUI, and having both platform configurations in the same Visual C# solution.


Conclusion

I already said it, but I say it again: being able to write programs for your own Xbox 360 is totally awesome, and doing it in a managed language with a revisited version of DirectX is extra bonus. But XNA works great and speeds up development of graphics applications on the PC as well, so if this is the kind of software you like to code, you just can't ignore it. There are still some important features missing, but the XNA team has been very good so far at listening to the feedback it has received, and I'm pretty confident most of these issues will be addressed in the near future. In summary, I can't wait for the next version!



back to top