Delta Engine Blog

AI, Robotics, multiplatform game development and Strict programming language

Quick Tips for XNA Beta 1 (aka My Own XNA FAQ)


  • Download XNA Beta1

  • XNA Framework Forum and XNA Game Studio Express Forum

  • Getting Started: Open C# Express (which is XNA Game Studio), Help->Content->Select XNA and navigate to Getting Started with XNA and read through Your First XNA Game

  • Next you could try out the Space War Starter Kit Game. If you can't control the game read this tutorial from xnaspot.com about changing it to support keyboard input.

  • x64 Bit platform support: Read this blog entry for an easy fix. Basically just add <PlatformTarget>x86</PlatformTarget> to your csproj file.
    Or download and extract this file (Xna64BitSupport.zip 14 KB) into:
    C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE\VCSExpress\

  • Blogs:

  • Tutorials:

  • Interessting reads:


  • And now finally my own thoughts and tips:

    • How to render fonts like with Direct3D.Font?

      Well, thats not possible, there are not Font classes in XNA at all yet! You have to create your own font code by rendering bitmap fonts. If you want to see some code about that check out the SpaceWar Starter Kit and look inside the Font.cs class. The fonts in SpaceWar just contain numbers, but the game contains some text. How did they do that? Well, they just put most of the text in the game directly onto the textures, buttons, etc.
      Here is also a forum post about this issue and some source code, which might help.

    • How to play sounds?

      Thats quite easy, create sounds with XAct, load them in your game and then use the SoundBank class to play your sounds. Some tutorials can be found in the help and a simple example is in the Sound.cs file in SpaceWar Starter Kit.

    • Okay, where do I add my mp3 for some music playback?

      Could you stop asking this questions? Arg, I'm asking myself this, oh no. But I guess sooner or later this would come up anyway. Well the solution? There is none. No, I'm not kidding. There is no support for mp3, wma or CD playback of music in XNA. On the windows platform you could use some external stuff (DirectShow, MCI, external libraries, etc.), but on the XBox360 you are stuck with XAct, which does just support sound effect files.

      Ok, then just let add the .mp3 as a .wav file there. Yup, thats possible, but consider your game size. If your binaries are maybe 1MB, textures 5-10MB and sounds 2MB you don't want to add 3*50MB for 3 music files. I had quite a long discussion with some music artist about this issue and we agreed that it would be best to do try out some 22kHz mono sounds for the music for a smaller game size. Don't even try to think about any compression, the only format that XAct eats is PCM .Wav files. Sample them down or live with mega-files, your choice ...

    • How to add Controller (Mouse, Keyboard, XBox360 Controller) support?

      Again, this is not hard stuff. If you have worked with XInput before, this will be easy for you. Otherwise just read the XNA Programming Guide->Input pages, which all contain easy to work with code samples.

    • How to show a mouse cursor?

      You might notice that there is no mouse cursor in the samples, starter kit or any new project you create. The reason for this is that by default the Game.IsMouseVisible is set to false. If you set it to true (e.g. in your game constructor) you will see the mouse cursor again (write: this.IsMouseVisible = true;). Another way would be to display your own custom mouse cursor as a sprite at the current mouse position (see help to get mouse position, it is quit easy).

    • How to capture keyboard text?

      Well, thats not that easy. You can only check the state of each button (mouse, keyboard, whatever), but you can't get the text directly like with the OnKeyPress event in window forms. One way would be to write your own custom text handling, like this:

      string chatText = "";
      List
      keysLastFrame = new List();

      ...

      Keys[] keysNow = Keyboard.GetState().GetPressedKeys();
      foreach (Keys key in keysNow)
          if (keysLastFrame.Contains(key) == false)
              chatText += key.ToString();
      keysLastFrame = new List
      (keysNow);

      But this has the disadvantage if you run low on frames or the user types very fast you might miss some keys (test this by adding Thread.Sleep(50)), which really sucks. It is also a bit of work to get all the special keys, shift combinations, backspace, etc. working. For windows apps it might be wise to think about capuring the keyboard directly with some dummy form (very easy to get text then with OnKeyPress). Another approach would be to create an extra thread just for handling the keyboard at a high rate to make sure you catch all the keys. More about this solution can be found in this post.

    • What about drawing lines, boxes or other simple 2d stuff?

      Oh no, this is one of the parts that is really annoying and this does require some rethinking because all this kind of rendering was done with help of the fixed function pipeline (hello DirectX 7), which is no longer supported in XNA. It was never easy in DirectX to draw lines or filled boxes, you had to create your own vertex buffer or just draw some primitives and set all kinds of renderstages, but with XNA this gets even more complicated. Better not tell anyone how simple this is in OpenGL (glLine anyone ^^).

      So how can we draw some lines in 3d?

      Again: It is very important to know that you have to do EVERYTHING with shaders! The Sprite classes are just some helpers, but for 3d you need shaders, nothing else will work! I say this that often because many people in the XNA Forum already having problems rendering data and do not understand that if you don't have a shader around your rendering code, nothing will happen! Additionally you have to make sure you pass all the required data to your shader, there is a lot more work involved that just rendering some primitives in DirectX using the fixed function pipeline.

      I will try to keep this as short as possible, but you will see this is quite a lot of code for just rendering a single line. Here we go. We start with the variables we need (add to your Game class):

      Matrix Projection = Matrix.Identity,
      View = Matrix.Identity;
      Vector3 pos1 = new Vector3(0, 0, 0),
      pos2 = new Vector3(100, 100, 100);
      VertexPositionColor[] lineVertices =
      new VertexPositionColor[2];
      lineVertices[0] = new VertexPositionColor(pos1, Color.Red);
      lineVertices[1] = new VertexPositionColor(pos2, Color.Yellow);

      Effect effect = null;
      EffectParameter worldViewProj = null;

      We will use the Projection and View to calculate the worldViewProj matrix for our shader to convert the 3d coordinates to 2d (yep, I told you, we have to do everything ourself). If you want some camera control, always update the View matrix, which again you have to manage yourself (hello XNA team, some help with this basic stuff plz). Ok, lets continue before I explode, here is the initialization code (copy to your Game constructor):

      float aspectRatio = (float)TestGame.Width / (float)TestGame.Height;
      Projection = Matrix.CreatePerspectiveFieldOfView(
          (float)Math.PI / 2, aspectRatio, 0.1f, 1000.0f);
      View = Matrix.CreateLookAt(
          new Vector3(0, 0, -50), Vector3.Zero, Vector3.Up);

      CompiledEffect compiledEffect = Effect.CompileEffectFromFile(
          "Shaders\\LineRendering.fx", null, null, CompilerOptions.None,
          TargetPlatform.Windows);
      effect = new Effect(TestGame.Device,
          compiledEffect.GetShaderCode(), CompilerOptions.None, null);

      worldViewProj = effect.Parameters["worldViewProj"];

      Ok, what happens here? First of all we calculate our aspect ratio, nothing special. Then we have to calculate our projection and view matrices (please read the DirectX documentation if you have no idea what I'm talking about). Basically we have a field of view of 90 degrees (PI/2), we use our aspect ratio and we have a view range from 0.1 (near) to 1000.0 units (far). Then we create our camera at the position (0, 0, -50) looking at the center of our scene.

      Next we have to load our shader effect file. Yes, I told you about that earlier, we need a freaking shader to draw our simple line. We will get into that in a little bit, but ALWAYS make sure the .fx file is correct (test with FX Composer first). If the .fx file contains compiler errors you get unfunny NullReferenceExceptions, which won't help you (see below). Finally we are getting the worldViewProj parameter. This is the only line of this whole line code I really appreciate. Getting shader parameters is now a lot easier and cleaner, good work here! Also working with shaders is very easy now.

      Time to continue with our code, we need the rendering code (add to Draw()) now:

      // Start line shader
      effect.Begin(EffectStateOptions.Default);
      effect.Techniques[0].Passes[0].Begin();

      // Render line
      worldViewProj.SetValue(View * Projection);
      TestGame.device.VertexDeclaration = new VertexDeclaration(
      TestGame.device, VertexPositionColor.VertexElements);

      TestGame.device.DrawUserPrimitives
      (
      PrimitiveType.LineList, 1, lineVertices);

      // End shader
      effect.Techniques[0].Passes[0].End();
      effect.End();

      This code is pretty straight forward. We start our shader and select the first technique (the only one we got). Then we calculate our worldViewProj matrix from the View and Projection matrices we calculated in the constructor. After setting the VertexDeclaration we can draw our primitives, which are lines in our case. Just one to be more specific. Adding more lines is quite easy at this point. Finally we have to close the rendering pass (we just got 1 pass, else we would have to make a foreach loop around this code) and we also close the shader.

      So far so good, but how does the rendering now happen? 100% in the shader, the code we just wrote will do nothing more than calling the shader with the data we set, the line point positions and colors. So lets take a look at the shader, which does all the rendering. The shader itself is quite simple:

      // File: LineRendering.fx, Author: Abi
      // Code lines: 52, Size of file: 1,18 KB
      // Creation date: 31.08.2006 05:36
      // Last modified: 31.08.2006 06:44
      // Generated with Commenter by abi.exDream.com
      // Note: To test this use FX Composer from NVIDIA!


      string description = "Line rendering helper shader for XNA";

      // Default variables, supported by the engine
      float4x4 worldViewProj : WorldViewProjection;

      struct VertexInput
      {
          float3 pos : POSITION;
          float4 color : COLOR;
      };

      struct VertexOutput
      {
          float4 pos : POSITION;
          float4 color : COLOR;
      };

      VertexOutput LineRenderingVS(VertexInput In)
      {
          VertexOutput Out;

          // Transform position
          Out.pos = mul(float4(In.pos, 1), worldViewProj);
          Out.color = In.color;

          // And pass everything to the pixel shader
          return Out;
      } // LineRenderingVS(VertexInput In)

      float4 LineRenderingPS(VertexOutput In) : Color
      {
          return In.color;
      } // LineRenderingPS(VertexOutput In)

      // Techniques
      technique LineRendering
      {
          pass Pass0
          {
              VertexShader = compile vs_1_1 LineRenderingVS();
              PixelShader = compile ps_1_1 LineRenderingPS();
          } // Pass0
      } // LineRendering

      And thats it. As you can see we just take the input position, transform it and then output the color we interpolated through the vertex shader. The pixel shader has just to output the color. Working with other primitive types can be done in a similar way, so I hope this code helps.

      And what about 2d lines?

      2D lines can be done quite similary. In DirectX you would never think about rendering 2D lines with shaders, when it is so much easier with the fixed function pipeline. But this is not possible in XNA, so we have to use shaders again. Lets go quickly through the code that is required:

      Matrix Projection = Matrix.Identity,
      View = Matrix.Identity;
      Point pos1 = new Point(0, 0),
      pos2 = new Point(500, 250);
      VertexPositionColor[] lineVertices =
      new VertexPositionColor[2];
      Effect effect = null;
      EffectParameter worldViewProj = null;

      Very similar to what we had above, only our positions are now Points and not Vector3. Also note we don't calculate the lineVertices here because the data is resolution dependant and we have to grab the resolution from the graphics object first. Lets take a look at the initialization code:

      float aspectRatio = (float)TestGame.Width / (float)TestGame.Height;
      Projection = Matrix.CreatePerspectiveFieldOfView(
          (float)Math.PI / 2, aspectRatio, 0.1f, 1000.0f);
      View = Matrix.CreateLookAt(
          new Vector3(0, 0, -50), Vector3.Zero, Vector3.Up);

      lineVertices[0] = new VertexPositionColor(
          new Vector3(
          -1.0f + 2.0f * pos1.X / TestGame.Width,
          -(-1.0f + 2.0f * pos1.Y / TestGame.Height), 0), Color.Red);
      lineVertices[1] = new VertexPositionColor(
          new Vector3(
          -1.0f + 2.0f * pos2.X / TestGame.Width,
          -(-1.0f + 2.0f * pos2.Y / TestGame.Height), 0), Color.Green);

      CompiledEffect compiledEffect = Effect.CompileEffectFromFile(
          "Shaders\\LineRendering2D.fx", null, null, CompilerOptions.None,
          TargetPlatform.Windows);
      effect = new Effect(TestGame.Device,
          compiledEffect.GetShaderCode(), CompilerOptions.None, null);

      worldViewProj = effect.Parameters["worldViewProj"];

      This looks slightly more complex. The reason for that is the conversation from pixel coordinates to screen space, which goes from -1 to +1 and has y inverted. We could also do this calculation in the vertex shader, but I like C# more ^^ Please also note that we don't need the z coordinate, but it is way easier to just use the VertexPositionColor struct instead of creating our own struct. Lets continue with the rendering.

      // Start line shader
      effect.Begin(EffectStateOptions.Default);
      effect.Techniques[0].Passes[0].Begin();

      // Render line
      worldViewProj.SetValue(View * Projection);
      TestGame.device.VertexDeclaration = new VertexDeclaration(
      TestGame.device, VertexPositionColor.VertexElements);

      TestGame.device.DrawUserPrimitives
      (
      PrimitiveType.LineList, 1, lineVertices);

      // End shader
      effect.Techniques[0].Passes[0].End();
      effect.End();

      Nothing changed here, nothing we have to discuss. Everything works just the same. lets take a look at the shader!

      // File: LineRendering2D.fx, Author: Abi
      // Code lines: 52, Size of file: 1,18 KB
      // Creation date: 31.08.2006 05:36
      // Last modified: 31.08.2006 06:55
      // Generated with Commenter by abi.exDream.com
      // Note: To test this use FX Composer from NVIDIA!


      string description = "Line rendering in 2D space shader for XNA";

      // Default variables, supported by the engine

      float4x4 worldViewProj : WorldViewProjection;

      struct VertexInput
      {
          float3 pos : POSITION;
          float4 color : COLOR;
      };

      struct VertexOutput
      {
          float4 pos : POSITION;
          float4 color : COLOR;
      };

      VertexOutput LineRendering2DVS(VertexInput In)
      {
          VertexOutput Out;

          // Transform position
          Out.pos = float4(In.pos, 1);
          Out.color = In.color;

          // And pass everything to the pixel shader
          return Out;
      } // LineRendering2DVS(VertexInput In)

      float4 LineRendering2DPS(VertexOutput In) : Color
      {
          return In.color;
      } // LineRendering2DPS(VertexOutput In)

      // Techniques
      technique LineRendering2D
      {
          pass Pass0
          {
              VertexShader = compile vs_1_1 LineRendering2DVS();
              PixelShader = compile ps_1_1 LineRendering2DPS();
          } // Pass0
      } // LineRendering2D

      Not much changed here either. Only the vertex shader is changed, we don't have to use our worldViewProj matrix anymore. We are just copying the data over to the pixel shader for rendering the screen stuff directly.

      Thats it for rendering 2D data. I guess most 2D stuff will be covered by the Sprite class, but if you need some custom 2d stuff (lines, boxes, etc.) this code should help you out. Have fun writing more complex stuff.

    • Ok, if the line stuff is that hard, lets do some simple mesh rendering, right?

      Wrong again. While this was planed for the XNA Beta release, it didn't make it into the beta and you have to do your own mesh loading, handling and rendering. In the SpaceWar Starter Kit game you can find some code to load swm model files (wtf is this format?), but you can't render .x or .fbx files that easily yet. In the future no problem, but right know you are f .. erm, not able to ^^. When I got some code for mesh loading and rendering, I will show it :-)

    • Content Management, what about that?

      Well, its quite cool to just drop your content files into your project and then you can directly access them in your code. But since this feature is not supported yet, there is no point discussing it ... If you want to read stuff anyway, check this blog posts about the content pipeline out: http://blogs.msdn.com/xna/archive/2006/08/29/730168.aspx and http://blogs.msdn.com/shawnhar/archive/2006/08/26/725954.aspx.

    • Why are there so few help topics in the most important namespace Microsoft.XNA.Graphics, especially for 3d rendering?

      Well, since most of the line rendering, mesh or even the content pipeline is not supported, it is no wonder some important topics are missing. The help basically just tells you how to create a textured cube yet, nothing else. But this is also an early beta release, expect more help topics in the future. The many new XNA pages that are created these days (like 10 new ones each day ^^) will also provide a lot of resources. I bet XNA will have a really big community after a while. XNA has already interessted a lot of people about this new technology.

      Please also try to use the DirectX documentation as backup help in case you need more tutorials, samples and documentation.

    • Shaders?

      Yap, everything except Sprites has to be done with shaders. I guess this will be reason enough for most XNA games to never have any 3d content. Working with sprites is quite easy, but having to write custom shader code, declaring vertex types and having crazy random exceptions is nothing easy.

      For example if your shader fails to compile you get just a System.NullReferenceException: Object reference not set to an instance of an object. There is no explanation what did went wrong, which is pretty bad IMO. Shaders are really a pain in the ass because they are not managed in any way. Its just some script that gets compiled for the GPU and if anything went wrong you can hope your tools tell you exactly what to do. MDX did already suck in this regard, but from my quick early preview XNA is way worse. I really hope this part gets improved. What does nice and clean sprite, sound and controller programming help me if the 3d code is ugly as hell and as hard to write as c++ minus the debugging benefits from DirectX.

      Debugging DirectX? Yes, lets do that. First you need VS 2005 (see below how to get that to work with XNA). Now activate unmanaged Debugging and make sure DirectX is running in Debug mode (either go to your control panel and open up DirectX or use Start->Programs->DirectX->Utilities->Control Panel (which is the only available choice on x64 bit), now select debug mode and also set the Managed DirectX dlls to debug for better debugging support. Now when crazy NullReferenceExceptions happen and you are lucky you might see some helpful explanation.

      Scroll above to see some simple shaders for the line rendering stuff. There is also another shader example in the documentation, work with that code and change it with help of tools like FX Composer to find out about compiling errors beforehand.

    • Do I have to dispose textures, models, etc. like in MDX?

      Not really. I didn't notice any problems yet. I guess XNA has some mechanisms to collect all resources when disposing itself (game component and device). As you can see in the SpaceWar Starter Kit they didn't had to implement any disposing for their MeshCache or TextureCache lists in SpacewarGame.cs.

      This is quite cool IMO, it makes coding even easier than it was in MDX.

    • Why does my game crash with a NullReferenceException when I drag it over to another screen when using SpriteBatches?

      I guess this is some bug in the SpriteBatch class, which does not handle the device lost event correctly or something. It always crashes in the Begin() method when dragging the window out of my first screen. Since the SpriteBatch class does not have any events other than disposing, the best and simplest solution is just to add a event handler for the OnCreateDevice event and put your SpriteBatch creation code there too. This way it gets re-created when you need it. Would be nice if you didn't have to do this yourself ... XNA team reading this? Who knows ^^

    • Occlusion quering for example for lens flare effects?

      Not supported, check out this post.

    • What about Physics, AI, Collision, Particles, etc.?

      Not supported right now, check out this post. Since XNA is mainly a graphic engine with sound and controller support, it is not very likely you get advanced engine features soon.

    • How to get XNA working in VS 2005 (with all the plugins you might have, which do not work in Express)?

      Thats not supported or even possible out of the box! Read more about this here (Forum) and in the FAQ.

      But since I'm such a clever guy I modified the XNA templates quite a bit and added support opening the project in VS 2005. Read the full story here. Basically just download this: Xna64BitSupport.zip (14 KB) and extract it to:
      C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\VCSExpress\
      Now you can open your created XNA Game Studio Express projects in VS 2005 and continue working on them there.

    • Unit Testing in XNA?

      Quite simple, just add NUnit.Framework.dll, which is fully managed and should even work on the XBox360 (not that you need unit testing there). If you use VS Express, TestDriven.NET will not work (unless you have a version from last year, which still supported it). If you use VS 2005 use TestDriven.NET or TestRunner (tested it few weeks ago, very nice, but does not support static unit tests, big nono for me).

      I also suggest using a TestGame class and do many static unit tests to play around with XNA (I already wrote 5 static unit tests today). Thats much faster than to create a new project everytime. And each test looks much easier and shorter than a complete new project.

    • Performance of XNA compared to MDX or native DirectX.

      I couldn't detect any performance penalities yet, someone in the XNA forums had some problems archiving 800 fps when using bitmap fonts, dunno what that was about. But it is very hard to say how XNA performs in relation to MDX because there is not much code or games we can compare yet.

      But in my opinion it does not even matter, the XBox360 is fast enough even if you write really shitty code and the windows platform is also quite fast with all this dual core around. For most simpler or casual games this will never matter much. However I do strongly believe that XNA will perform on the same level as MDX and DirectX.

    • But I want to play my XNA game on my XBox 360?

      Me too, but we have to wait for the next drop of XNA ^^ Not supported yet.

    • What about Rocket Commander for the XBox 360?

      Well, I thought about that, but since many of the classes used in Rocket Commander are not supported yet in XNA and the actual XBox360 execution is not yet possible, why even bother? As soon as XBox360 XNA'ing is possible, I will consider a Rocket Commander port again.

    • Btw: Why is the SpaceWar Starter Kit so big (155 MB uncompressed)? There is not even music in it.

      Most textures are uncompressed as .tga files, not good ... Rocket Commander has more graphics, music and I guess more sound files too, but is less than 10 MB.

    • Need more help? Then ask in the XNA Forums and not here, I got stuff to do :D

Hope this helps. I will post more about XNA Trick & Tips soon ;-)

Yes, I'm writing a XNA game too. It will even be a Starter Kit for the next XNA Game Studio Release, more about that next week, I will post weekly screenshots like in the Rocket Commander Development time.

Comments are closed