Thought for the Dazed

I've had to give up that Distance Learning course as I was having trouble seeing the teacher.

Flickr
www.flickr.com
RobMiles' items Go to RobMiles' photostream
Twitter
C# Yellow Book

Search entire site
Monday
Apr182011

Dalby and Ducks

Went to Dalby Forest today. (having a tiny holiday) Great place. Once we arrived we had a coffee at the Purple Mountain Cafe. If you like riding bikes at great speed down steep hills you should go there. They arrange all kinds of races and stuff (including truly scary sounding 12 hour ones). Find out more here:

http://www.purplemountain.co.uk/

Dalby Bikes
“Excuse me, can you hire these bikes?”
"Certainly sir, they have a small adjustment at the back”

Note – this joke completely breaks if you write it down….

Then we went for a walk around, and I took the big camera.

Dalby walk
Look! Blue Sky!

We rounded off the trip with a visit to Thornton-Le-Dale, which has a lake and ducks.

Ducks

Nobody mention oranges.

Sunday
Apr172011

Positioning Sprites with Rectangles and Vectors in XNA

Prada

Staying with the XNA techie theme, now a word about performing sprite positioning in a game. A sprite is something that has a texture (the image to be displayed when the sprite is drawn) and a position (the place to draw it). Generally sprites map onto objects in a game. If I am creating a game and I need to draw a bat, ball, spaceship, alien or asteroid I will use a sprite to do this.

There are two different ways to position sprites in XNA and each has its advantages and disadvantages. However, it is worth knowing about both.

Rectangle Positioning

With this form you create a rectangle which tells XNA where to draw the item, and how big it is:

Rectangle r = new Rectangle(0, 0, 200, 100);
spriteBatch.Draw(texture, r, Color.White);

This draws our texture in the top left hand corner (0,0) , in a rectangle 200 pixels wide and 100 pixels high.

Using a rectangle like this works well, it also gives you a ready made “bounding box” which you can use to test for collisions:

if (rect1.Intersects(rect2)) {
    // We have a collision between rect1 and rect2
}

However, there are some bad things about using rectangles that make me less keen on them

  • Rectangles are positioned using integers. The x and y properties you use describe where they are do not have a fractional part. This means that if you want to move a rectangle slowly around the screen (i.e. less than a pixel per update) you can’t just use the x and y properties to do this.
  • You can use rectangles to scale drawing, but this gets a bit tedious as you have to work out the size of rectangle you need, and you also need to be mindful of the aspect ratio of the item you are drawing so that it doesn’t end up squashed or stretched.
  • It is impossible to rotate a sprite which is positioned using a rectangle

So, rectangles are good for very simple sprites, but once you have become more familiar with XNA I think it is worth moving on to Vector positioning.

Vector Positioning

A vector is something that has direction and magnitude. That sounds posh. Actually it just contains an X and Y value, just like a coordinate. The “direction and magnitude” bit kicks in if you draw a line from the origin (0,0) to the X, Y position given. This line is the vector. The direction is the way the line points, and the magnitude is how long the line is.  In XNA terms the Vector2 type is the one you can use to position 2D sprites:

Vector2 v = new Vector2(10, 10);
spriteBatch.Draw(texture, v, Color.White);

This code draws the texture at position (10,10) . The texture is drawn in whatever size it happens to be, i.e. if the texture image was 200 pixels by 100 it would be drawn that size.  This means that you might need to scale your textures to fit a particular screen size – but as we shall see later this is not  a huge problem.

There are quite a few good things about vectors though.

  • The X and Y values of a vector are floating point, so you have very good control of sprite speed
  • The XNA framework supports vector mathematics directly. So you can write code like this:

    position = position + speed;

    - where position and speed are both vectors

When it comes to scaling and rotating a sprite positioned using a vector you can use a more complex version of the draw command (find a detailed description here) to do all this. Also, bear in mind that if you targeting Windows Phone you can fix your resolution in the game to a particular value and then make all your to assets fit.

graphics.PreferredBackBufferWidth = 480;
graphics.PreferredBackBufferHeight = 800;

The phone hardware will scale the display automatically to match whatever size you specify, now and in the future.

If you want to detect bounding box collisions you can write code like this:

public bool Contains(Vector2 pos)
{
    if (pos.X < position.X) return false;
    if (pos.X > (position.X + texture.Width)) return false;
    if (pos.Y < position.Y) return false;
    if (pos.Y > (position.Y + texture.Height)) return false;
    return true;
}

This returns true if the area covered by the sprite contains the given position.

For bounding box collisions you can use this:

public bool Intersects(Sprite c)
{
    if (pos.X + texture.Width < c.pos.X) return false;
    if (c.pos.X + c.texture.Width < pos.X) return false;
    if (pos.Y + texture.Height < c.pos.Y) return false;
    if (c.pos.Y + c.texture.Height < pos.Y) return false;
    return true;
}

This test will tell you if the bounding box around the two sprites intersects. However, if the sprites are textures that don’t fill the entire sprite rectangle this test is not a very accurate one. I’ll be covering pixel level collision detection next.

Saturday
Apr162011

Game Object State Management in XNA

Vegas Building

Hmm. This sounds a bit deep for a Saturday blog post. I suppose it is, but I got asked a question at Mix 11 and I’ve been pondering it ever since then. The question was about some code like this:

class Cloud : CloudGame.ISprite
{
    public Texture2D CloudTexture;
    public Vector2 CloudPosition;
    public Vector2 CloudSpeed;
    public bool Burst = false;

    public void Draw(CloudGame game)
    {
        if (!Burst)
            game.spriteBatch.Draw(CloudTexture, 
                                                                       CloudPosition, 
                                                                       Color.White);
    }
   // rest of cloud code here
}

This is a tiny part of my “Cloud Bursting” game demo, where players touch clouds to burst them. The above code is the definition of the cloud itself. This has a texture, position, speed of movement and a Burst flag as properties.

Burst is how the cloud “knows” if the cloud has been burst. If the cloud is burst it is not drawn. At the start of the game all the clouds have the Burst flag set to false to indicate that they are still part of the game. As the player touches them the Burst flag is set true.

You see this in a lot of game play situations. Anywhere that things are “killed” they have to be able to remember whether they are still alive or not. The code above is simple and works well, at any instant a cloud is either burst or not. If it is burst (i.e. the Burst flag is true) plays no further part in the game and is not drawn.

However, this design gave rise to the question: “Why do we need to have a flag? Surely it would be more efficient to remove a ‘burst’ cloud from the list of things to be drawn?”

This is a very good question. To understand it you need to remember that in a game we will have many objects on the screen at any given time. To manage this the game contains a collection of some kind (usually a List). During Update and Draw the game works through the list acting on each item in it. If an item is removed from the list it will no longer be part of the game.  When the player bursts a cloud, rather than setting a flag you could just remove that cloud from the list of active game objects.

This approach has the advantage that it is more efficient. Instead of a cloud having to decide not to draw itself the game never tries to draw burst clouds at all.  However, it also adds complication. The game must now have a “master” list of clouds and an “active” list of clouds. At the start of a game the master cloud references are copied into the active list. This is to avoid the overheads of creating and destroying objects, something you really don’t want to be doing on a regular basis.

Furthermore, the time that is saved is probably not going to be that much use to us. If the game works fine with all the clouds visible (which it should do) then saving small amounts of processor time when some clouds are removed is not going to make that much difference to performance. In this situation it is the drawing of the objects that takes the time, not deciding whether or not to draw them.

The fundamental principle here is that you should go for simplicity first, then optimise when you discover you have a performance issue.  I like having the flags present, it makes for greater cohesion and easier debugging. I can look at any cloud and decide whether or not it should be drawn simply by inspecting the flag.  If the flag wasn’t there I’d have to check which lists held the cloud, and so on.

So, I go with internal flags, not lists, which is pretty much what I said at the time as I remember.

Friday
Apr152011

Back to Hull

Excalibur

This is not Hull

Got back to day, sat down and woke up an hour later. Gotta love jetlag.

Thursday
Apr142011

Heading Home from Mix

New York

I’m missing the last day of Mix because I have to head back. The good news is that I can watch all the videos of the sessions later on. I walked up from the hotel to The Venetian last night, taking pictures all the way there and back, which was nice.