My Daemon
May 10th, 2007
For anyone who loves “His Dark Materials”
So busy...
March 30th, 2007
I’ve written the source code for the next article. Now I need to write the article. Does anyone have any spare time they can let me have? I need more time.
Anyway, the dreambuildplay competition is up and running. I have a great idea for a game, and some great collaborators too. I can’t see me hitting the deadline unless I take 3 months off work.
If you’re interested in Go, get yourself over to here and take the test. I scored 9Kyu, which I doubt is my real skill level, but it would be nice if it were.
Anyhow, I’ll have another article out on soon!
DreamBuildPlay, First Challenge
February 13th, 2007
The first challenge at DreamBuildPlay has been announced. We have till February 28th to submit a derivative of “SpaceWar”, for the chance to win one of five $500 prizes. I’m not sure what happened to the July date originally stated. I know a lot of people have games under development that are far more complex that Spacewar (I know I have) and will be wondering whether to enter this challenge or not.
What are Microsoft up to?
Simple Meshes
February 3rd, 2007
The XNA game system is specially designed to make it easier to import models from 3d editing applications. That’s fine if you actually know how to use these applications, or have the time to learn. I’m betting that most XNA coders want to dive in and get their hands dirty with code that throws models around the screen, without actually having to spend the time designing these models. Models can be created later, once you know XNA works for you. If this seems to describe you, then read on.
Even if you already have a designer beavering away with blender, you’ll still need to understand how meshes can be created dynamically. Without this kind of knowledge height maps will stay as height maps, never to be rendered as a beautiful rolling landscape; the craft you’re flying won’t be able to decompose into fragments when it gets hit by a rocket. You get the idea.
XNA is only capable of rendering four things. Points, lines, sprites [2d images] and triangles. As the game you’re writing basically comes down to line after line of C#, the images your program will be creating comes down to triangles. Thousands upon thousands of texture-mapped triangles.
Some may even be bump-mapped. But they will still be triangles.
To start with, we’re going to display a simple cube. A cube appears to be made of 8 vertices:
To render this we need to use 4 separate vertices per side. This makes 24 vertices:

You can imagine from this diagram how the faces are decomposed into triangles. No faces shares a vertex with any other face, even though every vertex shares the same (x,y,z) position as two other vertices. The reason for doing this is that the vertex structure does not just contain its location. It also contains a texture coordinate and a vertex normal. This allows us to give each face a unique texture, and also to ensure all its vertices point in the same direction (useful for lighting). For a smooth object, such as a sphere, we would share vertices between faces, as they would need to share normals and texture coordinates to make the object appear uniform.
This program uses the same camera movement technique as detailed in the Camera Movement tutorial . Also, if your mouse has a scroll wheel it will be the view up and down.
Creating the cube
The cube is created in the call to InitialiseCube(). This takes a Vector3 object as a parameter, which specifies the size (in three dimensions) of the “cube”. It should perhaps be more accurately named “cuboid”.
This code first creates a few objects necessary for the rendering process.
vertexShaderDeclaration = new VertexDeclaration(graphics.GraphicsDevice,
VertexPositionNormalTexture.VertexElements);
vertexBuffer = new VertexBuffer(graphics.GraphicsDevice,
typeof(VertexPositionNormalTexture),
24,
ResourceUsage.WriteOnly,
ResourceManagementMode.Automatic);
vertexArray = new VertexPositionNormalTexture[24];
The VertexDeclaration object instructs the shader how to interpret any vertex data it is passed. This is passed an array of elements which describe where the shader can find the position, normal and texture within the vertex data stream it is to process. It also indicates that each vertex will have a position, a normal (used for lighting) and a texture coordinate. This is an example of a flexible vertex format – referred to as an FVF. Other examples are@VertexPositionColor@ and VertexPositionColorTexture.
The VertexBuffer object will contain the array of vertices, and is initialised with the type of vertex being used, the number of vertices it should expect, and a few resource-management enumerations. The array to contain the vertices is then created.
Eight locally scoped Vector3 objects are initialised to the eight cube corners, and then four vertices per face are initialised. Each face has its vertices in clock-wise order. Any faces where, once all transformations have taken place,the vertex order is anti-clockwise, are marked as facing away from the viewer point and culled. Think about the cube: if the face nearest the camera has its corners in a clockwise order, once the cube is rotated by 180 (through its Y-axis), and that face is no longer visible, its corners would appear to be anti-clockwise 1.
Each call to SetVertex() sets an individual vertex for one of the six faces. As well as the position of the vertex it also sets the face normal (the direction the face is facing – shared by all vertices on a face) and the texture coordinate (a two-dimension texture, with a two-dimension vector coordinate).
vertexBuffer.SetData<VertexPositionNormalTexture>(vertexArray);
This code then passes the vertex array into the vertex buffer. The vertex buffer is what is eventually passed to the renderer.
Next a vertex index array is created, to contain the vertex number of the series of triangles that will be passed to the renderer. This is simply an array of shorts. This array has one element per triangle vertex – and refers to the vertex buffer that was just created. So, the first face is composed of two triangles – it needs six vertices. These are the vertices numbered 0,1,2 and 0,2,3.

[apologies for my handwriting here. Still getting used to the tablet, and my handwriting sucks even on paper. Perhaps this tablet is for right-handed people only?]
The code loops through the array, calculating the vertex numbers, The reason this can be done is that when the vertices were created above (in the vertex buffer) the order was very specific. When any face is rotated to be at the front, facing the camera, the corners would be in the same position in the same order.
indexBuffer = new IndexBuffer(graphics.GraphicsDevice,
sizeof(short) * vertexIndices.Length,
ResourceUsage.None,
ResourceManagementMode.Automatic,
IndexElementSize.SixteenBits);
indexBuffer.SetData<short>(vertexIndices);
This first creates the index buffer, then passes the index array is to it. This index buffer is passed to the renderer when Draw() is called.
The texture
All polygons, apart from very boring ones, need to be texture-mapped. To do this an image is needed. To prevent you having to download a texture-map of my creating, or creating your own, the program will create its own. For the moment this will be very simple, just two diagonal lines. However the code to create the texture will show you how to generate your own, programmatically. Later we will be creating more interesting textures.
protected void CreateTexture()
{
faceTexture = new Texture2D(graphics.GraphicsDevice,
64,
64,
1,
ResourceUsage.Dynamic,
SurfaceFormat.Bgr565,
ResourceManagementMode.Manual);
ushort [] data=new ushort[4096];
for (int i = 0; i < 64; i++)
{
SetTexturePixel(ref data, 64, 64, i, i, Color.SlateBlue);
SetTexturePixel(ref data, 64, 64, 63 - i, i, Color.SlateGray);
}
faceTexture.SetData<ushort>(data, 0, 4096, SetDataOptions.Discard);
}
When creating the texture, because we are going to dynamically alter it, we have to use pass ResourceUsage.Dynamic and ResourceManagementMode.Manual. Also we are using 16 bit colours – with a surface format of 5 blue bits, 6 green bits, and 5 red bits. The texture created here is 64 pixels by 64 pixels, so we initialise an 4096 (64*64) element array of unsigned shorts (16 bit numbers).
The call to SetTexturePixel() is implemented in the code too. It sets the points passed – here (i,i) and (63-i,i), to the colour passed.
The faceTexture object is then passed this array. This texture object is then passed to the BasicEffect object when it is initialised.
The shader
To make this easier, we are going to use an XNA-provided shader, the BasicEffect class. This allows us to specify lighting and texture-mapping without having to write shader code. The method InitialiseShader(), called during initialisation (just before calling InitialiseCube()) creates a BasicEffect object, specifying a light that is above, to the left, and behind the viewer when the program starts. The direction of the light remains fixed, the viewer is free to move.
A texture is also passed to the shader here, that was created by a previous call to CreateTexture()
Rendering
As always, all rendering is done inside the Draw() method. In there you will find the following code:
GraphicsDevice device = graphics.GraphicsDevice;
device.VertexDeclaration = vertexShaderDeclaration;
shaderEffect.Begin(SaveStateMode.None);
shaderEffect.World = sceneWorldTransformation;
shaderEffect.View = viewMatrix;
shaderEffect.Projection = projectionMatrix;
foreach (EffectPass pass in shaderEffect.CurrentTechnique.Passes)
{
pass.Begin();
device.Indices = indexBuffer;
device.Vertices[0].SetSource(vertexBuffer,
0,
VertexPositionNormalTexture.SizeInBytes);
device.DrawIndexedPrimitives(PrimitiveType.TriangleList,
0,
0,
24,
0,
12);
pass.End();
}
shaderEffect.End();
First, the vertex shader is passed to the graphics device – this lets it know what format the vertices will be in. The shader is started without saving the render state and the world transformation (the cubes position and the way it is rotating), as well as the view and the projection are set.
The loop uses the BasicEffect object, shaderEffect, created in the InitialiseShader() method. Although this code will allow multi-pass rendering, in actual fact only one pass is performed here. It then passes the device the index buffer and the vertex buffer. DrawIndexedPrimitives is told it has to draw a list of indexed triangles, 12 to be exact, using 24 vertices.
1 This clockwise/anti-clockwise magic is done using the vector cross-product operation.
Dream Build Play, Contest Registration
February 1st, 2007
The XNA contest is now open to registration. Well, nearly. Its open for registration to people who live in America, and who don’t receive an error when they go to here
Hopefully they’ll add international registration soon!
New tablet!
January 31st, 2007
Ok, my next two tutorials on simple objects are nearly finished. However I’m now the proud owner of a Wacom tablet, and it’s really hard to use. I guess I could go back to my tablet PC, but I should try and use this. So once I get the pictures done, they’ll be some more articles. Promise!
However, apart from that I have a huge deadline at work, I’m technically reviewing my friends Ruby on Rails book., and I’m learning Go, and tonnes of other stuff.
There is still no word on DreamBuildPlay and its now the end of January. Perhaps MS have some internal processes slowing it down, or maybe they just forgot?
Or perhaps they meant January 2008?
Upcoming contest
December 13th, 2006
Microsoft are going to be running a competition from January:
Fantastic prizes sound great, but personally I’m in it for the global envy. If anyone is wondering what the morse means – “yourworldyourgame”. Thanks to Alan for the translation.
I am busy working on the next few articles. The next one will look at simple meshes; I’m also working on a simple game for an upcoming article. So check back soon!
Game Studio Released!
December 11th, 2006
XNA Game Studio Express has been released. Get yourself over to there to download it. All future development will be done using this, their first non-beta release.
You can now deploy code to your XBox-360, as long as you’ve paid at least $49 for the privilege.
Movement
December 11th, 2006
The problem with 3d games is they are complex beasts, even very simple ones. The (so far unpublished) sample code I have written just to display simple objects isn’t a very good starting point as it relies on the programmer (that’s you) to understand an awful lot about what’s going on already. So I’ve taken a step back from simple objects to writing code that I feel is missing from most of the samples I have seen. Today I’m going to be writing about a simple camera control mechanism that will allow you to move around any objects you create or models you display, using controls familiar to anyone who has played Doom or Quake. This will then allow you to easily explore any 3d environments you create yourself.
The implementation of Draw() here simply draws a bunch of points, in a star-shape1. The code could draw anything, we’re not really interested in that. What we’re interested in is how these are projected into the world, and how we then move around them.
Transformations
Each object in a 3d world has a world transformation. This transformation is held in a matrix. If you don’t understand matrix math’s, do not worry as XNA takes care of the complexities. A world transformation lets the renderer know how to rotate the object, and where to move the object to in the world. When we talk about moving an object, we use the word “translate”. Translation is the act of moving all the vertices (corners) of an object by the same amount in either of the three axis.
!
To create a transformation matrix, the XNA Matrix struct (a bit like a C# class, only with more limitations) has various methods to help. For instance to create a transformation matrix that translated an object 5 units across the screen (along the x-axis) you would use:
Matrix translate=Matrix.CreateTranslation(5.0F,0.0F,0.0F);
Here the ‘F’s after the number indicate to use a floating point number. If you miss an ‘F’ off, the number “0.0” would default to a double-length floating point number, and your program would refuse to compile.
The world transformation places and orientates an object in the 3d world we are creating. However we still need to choose a vantage point to view this world. This vantage point can be likened to placing a video camera to record the scene, so we refer to our observation point as a camera. Placing a camera is done using a view transformation. The view transformation is another Matrix struct, but it is created using the Matrix.CreateLookAt() method. This method takes a Vector3 (a simple struct which places the x,y and z coordinates together into one place) as a position for the camera, another Vector3 structure as a point for the camera to look at, and another Vector3 indicating which direction is up.

To move our viewpoint around the scene we simply alter the position passed as the first parameter to Matrix.CreateLookAt() How do we alter the direction we are looking in though? There are various ways of doing this, but because we are going to emulate a first-person-shooter here we only need to look up and down, and left and right. There is no need to tilt the cameras viewpoint. To take the phrases from airoplanes, looking left and right is “yawing”, and up and down it “pitching”. Thus we record the current yaw and pitch the user has selected using the mouse.
To do this, we first create a vector which points in the default camera angle. This is directly into the screen, and is given by the vector (0.0, 0.0, -1.0). The reason the z-element is negative is because XNA (by default) uses a right-handed coordinate system. This means (as can be seen on the diagrams) that whilst the x-axis goes across, and the y-axis goes up, the z-axis actually comes out of the screen towards the person viewing the display.
This default view vector is then rotated around the x-axis (pitch) and then rotated around the y-axis (yaw). The order is important. If we reversed this, rotating around the y-axis first then the x-axis, we would get into situations where we would not be able to look up and down. Imagine rotating to the left by 90 degrees. If we then tried to look up and down by rotating around the x-axis we would fail, the orientation of the vector would not change.
There are ways around this problem, using quaternion math’s – we’ll save that for a (much) later article.
From the programs UpdateCamera() method
// Copy the camera's reference vector.
Vector3 cameraLookAtVector = cameraReferenceVector;
// Create a vector pointing the direction the camera is facing.
cameraLookAtVector = Vector3.Transform(cameraLookAtVector, Matrix.CreateRotationX(cameraPitch));
cameraLookAtVector = Vector3.Transform(cameraLookAtVector, Matrix.CreateRotationY(cameraYaw));
// Calculate the position the camera is looking at.
cameraLookAtVector += cameraPosition;
// Create a view matrix for the camera, using the camera position (the coordinates
// controlled by the keyboard) and a vector pointing in the direction the user has
// chosen (controlled by the mouse)
// The third parameter is a vector which points up - this indicates the direction that "up" is in
viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookAtVector, new Vector3(0.0f, 1.0f, 0.0f));
The variable cameraReferenceVector is defined already to be (0.0, 0.0, -1.0), which is the default camera orientation. cameraPitch and cameraYaw are the pitch and yaw of the camera, in radians.
The line cameraLookAtVector += cameraPosition; uses vector translation to add the now-rotated camera direction to the camera position, giving a vector that indicates the point the camera is looking at. If you think about this, it will only ever be 1.0 unit away from the camera position (as we have only rotated as a vector 1.0 unit long). This does not matter as there is no focusing involved here. Looking at a point 1cm or 1m away (whatever units you wish the units to mean) is the same as looking 100cm or 100m away, as long as its in exactly the same direction.
There is another transformation used, the projection matrix. This is initialised in the method InitialiseCamera, and basically instructs the render how to project the three-dimensional world onto the two-dimensional screen – basically how to squash it against the back of your screen so it appears to have perspective.
User input
Mouse-look
Next we need to control the camera’s position, pitch and yaw. We’ll tackle pitch and yaw first. We’ll rotate the camera using something called mouse look. This means moving the mouse around will move the direction the camera looks in. This will be done in the Update() method.
To do this we need to know how much, and in which direction, the mouse has moved since the last call to Update(). We do this by remembering the position the mouse was in when update was last called. We use the instance variables xMousePosPrev and yMousePosPrev for this purpose. We then find out where the mouse currently is (using a call to Mouse.GetState()) and work out the difference.
The difference horizontally is taken to relate to the yaw angle, the difference vertically is taken to relate to the pitch angle. In the code we simply the divide the positional difference by a value to get these angles:
// Retrieve the current state of the mouse (position and buttons)
MouseState mouseState = Mouse.GetState();
// Calculate change in mouse position
int dx = xMousePosPrev - mouseState.X;
int dy = yMousePosPrev - mouseState.Y;
cameraYaw += dx / 100.0F;
// Clamp yaw angle to -180 degrees to +180 degrees (with wrap-around)
if (cameraYaw <= -Math.PI)
{
cameraYaw += (float)(2 * Math.PI);
}
if (cameraYaw > Math.PI)
{
cameraYaw -= (float)(2 * Math.PI);
}
cameraPitch -= dy / 150.0F;
// Clamp pitch angle to -90 degrees to +90 degrees (with no wrap-around)
if (cameraPitch > Math.PI / 2)
{
cameraPitch = (float)(Math.PI / 2);
}
else if (cameraPitch < -Math.PI / 2)
{
cameraPitch = (float)(-Math.PI / 2);
}
CentreMouse();
(see the MouseInput() method.)
You’re probably thinking if we’re constantly looking at the mouse position, when the mouse reaches the edge of the screen we won’t be able to continue looking up or down. To counter this we call CentreMouse(). This method (defined at the bottom of Game1.cs) centres the mouse on the game window – as the mouse is hidden over the game window this will not be intrusive. However we need to ensure this is only done when the game window has the focus. To do this we attach to two event handlers in the class constructor:
Activated += new EventHandler(GameActivated);
Deactivated += new EventHandler(GameDeactivated);
This ensures that the objects methods GameActivated() and GameDeactivated() are called when the game is brought in and out of focus. This happens when alt-tabbing. When the window is in focus, we attempt to capture the mouse. The mouse is only captured however if it is over the game window. Only when it is finally captured do we start the continuous re-centring.
Movement
Once we know the direction the camera is looking in, we can start to move the camera. This is done using the arrow keys.
Using the method Keyboard.GetState() we can detect whether the keys of interest are pressed or not. We then use some basic trigonometry to calculate the direction of movement. If your math’s skill are limited, don’t worry too much. The code works, and you shouldn’t need to change it.
Next time, we’ll be looking at displaying something a little more interesting that points.
1 Because we are using a BasicEffect object (object in the object-oriented sense) to provide the shader model, the actual colors of the points cannot be set. The BasicEffect class expects 3d-objects to be textured-map and have surface normals, but no colors. Surface normals are used to indicate the inclination of a surface to the shader, allowing objects to reflect lights correctly. Texture maps are images that are streched across a surface to give it a specific appearance. To avoid the complexities of this we are just using simple points without worrying about the color displayed.
The plan for this blog
December 5th, 2006
Over the coming months I will be exploring the XNA game development system to create a small and simple arcade game. I’m going to share code that you can re-use in any way you like, and discuss any problems and solutions I come across along the way. Apparently I need to choose a license for the code I write, and that the “Send me chocolate and wine if it makes you any money” isn’t a valid one. I’ll probably be choosing a Creative Commons license, but can’t right now as their site seems to be down. I want people to be able to use the code freely for whatever purpose they see fit, and to feel free to send me any kind of heads-up, case of wine or suitcase full of currency (none-sequential serial numbers, unmarked) that they deem fit.
Well that’s my current plan. We’ll just have to see how it goes. For the moment this is all going to be PC-only, but before long the code will be ported to the XBox-360.
Anyway, a brief introduction to getting XNA to do nothing. You probably don’t need this, but in case you do, here it is.
First of all, ensure you’ve installed C# express and XNA Express (see previous post), then run XNA Game Studio Express. Click the File menu, then “New Project…” At this point you could choose to create a “Spacewars Windows Start Kit”. However that would be a complex place to start, although it is good to play with when you’re stuck with the (practically non-existent) XNA documentation. Instead choose “Windows Game”, give your project a name (the default “WindowsGame1” is as good as any) and click okay.
Hopefully you will be at least a little familiar with C#, if not there are some great C# tutorials available on the web, and some even greater books. The project now has two C# files in it, program.cs and game1.cs. The first file just creates a copy of your game and runs it. Your game is defined in the second file. As things get more complex we will be adding more C# files, but for the moment all the work we do will be in game1.cs.
Have a look at game1.cs. There a few important methods central to writing games. The first is a method called LoadGraphicsContent() :
protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content
}
// TODO: Load any ResourceManagementMode.Manual content
}
This is used to load any models, lighting effects, sounds, or any other game resources.
The second method is called Update():
protected override void Update(GameTime gameTime)
{
// Allows the default game to exit on Xbox 360 and Windows
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
The update method forms part of the core game loop. It is called to update things like the camera position, in-game characters. It could be used to run any Artificial Intelligence routines (though these may be running on a separate thread) and perform physics calculations (for things like rockets and particle systems). One of the main things that it is used for is for game input. The default code interrogates the XBox-360s gamepad (which can be plugged into a PC) and exits if the back key is pressed. If you don’t currently own such a controller, worry not – the code we’ll be developing (at first) will all rely on having a keyboard and a mouse.
The third method of interest is Draw():
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
This simply clears the screen, but its where all the exciting stuff happens. Triangles are transformed, objects are culled to the view frustrum, hidden surface removal is performed, shadows created. But for the moment, just a blue screen.
Next time will be more fun.
Starting out...
December 5th, 2006
I’m really excited about the XNA game studio from Microsoft, so excited that I’ve decided to start a blog about what I’m doing with it.
Firstly, I’m not a games programmer. I write code for a living, concentrating on computer telephony and VoIP. Its fun, the pay is good, and I get to write protocol stacks. However I’ve always loved the art of writing computer games, three-dimensional ones in particular. I’ve written low-level engines (the kind coded in assembler that write pixels directly to the screen without hardware acceleration) and I’ve written demos that use Direct X. All good fun. But XNA is really exciting.
Why?
Two reasons. Firstly, its language is C#. This is a language I’ve been using recently for other projects, and it is just a nice place to program. The development tools are solid, the language is solid, and it injects a bit more fun into coding. If you’re used to using C++, learning C# is a doddle. If you’re used to other languages such as Java you’ll find it a doddle too.
The second reason is that you can target the XBox 360. Granted, you have to pay a yearly subscription each year to do this, but still, writing games for a console as powerful as the ‘360 is going to be fun.
XNA game studio express is currently in its second beta. It has to be used with C# Express edition, which is free and can be installed alongside Visual Studio if you use that. The reason MS have given is that integrating the X-Box side of things into Visual Studio is no small task, so they had to pick one edition to integrate to. C# express was the version chosen, so no VB or C++ coding.
So if you haven’t done already, get over to the following location and download C# Express. One thing to note, when installing C# everything should be green. If everything is yellow, you’re installing C++ express. While C++ is a great language, XNA will refuse to install unless C# express is already there.
Then go and grab XNA express from here:
When you run up XNA Game Studio Express, you can create a project type of “Spacewar Windows Starter Kit”. This will produce a two player two-dimensional game, similar to asteroids. You can play it from the keyboard or ‘360 gamepads (plugged into your PC). The tutorial “Going beyond: XNA Game Studio in 3d” in the help system (Under XNA Game Studio Express->Getting Started with XNA Game Studio Express) takes a model from the Space Wars game and displays it in three-dimensions. It’s much too pretty to be rendered in two-dimensions.
That’s all for now!
