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
« Make a Font from your Handwriting | Main | Useful 3D Printing Text »
Saturday
Apr202013

Sprites and Distances

Space Killlers Backdrop

At the moment quite a few of the first year are working on a “Space Killers” game. Above you can see my sample screenshot from the specification. You can see that my graphical design abilities are around the same as usual.

The idea is that the player (the green object) must survive in brightly coloured space while all around are trying to kill. Collision with any game object is instant death. Survive until the clock counts down to zero and you are rewarded with another level with more, and nastier, things in it.

One of the game objects is the “Master”. This is the one that looks a bit like a fried egg in the above screenshot. (Note to graphics department, fix that please).

Anyhoo, a Master sprite will sit and do nothing unless you get too close. Then it wakes up and chases you. To make this work the game needs to be able to work out how far the master is from the player. In my solution I have a sprite class:

public class Sprite
{
    public Texture2D SpriteTexture;
    public Rectangle SpriteRectangle;
    public Vector2 SpritePosition;
    public Color SpriteColor;
}

This contains stuff that we need to position and draw the sprite. The Update method for the parent sprite just uses the position vector (which I use to decide where the sprite is on the screen) to set the SpriteRectangle value (which I use to decide where to draw the sprite).

public virtual void Update(SpaceKillersGame game)
{
    SpriteRectangle.X = (int)(SpritePosition.X + 0.5f);
    SpriteRectangle.Y = (int)(SpritePosition.Y + 0.5f);
}

My sprite also contains another method, DistanceFrom, which is used by code in the Master sprite to decide how close it is to the player.

public float DistanceFrom(Sprite otherSprite)
{
    float dx = SpriteRectangle.Center.X -
               otherSprite.SpriteRectangle.Center.X;
    float dy = SpriteRectangle.Center.Y - 
               otherSprite.SpriteRectangle.Center.Y;
    return (float) Math.Sqrt((dx * dx) + (dy * dy));
}

This is how it works. It turns out that the Rectangle class contains a Point value which gives the coordinates of the centre of the rectangle. I can use the X and Y components from this to work out the difference in x and y between the two rectangles. I can then use Pythagoras Theorem to work out the distance between the sprites. Pythagoras said “The sum of the squares of the sides of a right angled triangle is equal to the square of the hypotenuse”.  My code works out the sum of the squares and then takes the square root of this to work out the distance value.

image

Hopefully the above diagram will make it all clear. If not, just enjoy the pretty colours.

My Master sprite then contains the following statement in its Update method (Update is called on the sprite to make it update itself. It is given a reference to the game that is currently active).

if (DistanceFrom(game.Player) < MasterRadarRange)
{
    ChaseActive = true;
}
MasterRadarRange is a value which controls how far the Master can “see”. If a player gets closer than the radar range the flag ChaseActive is set to true, which triggers the chase behaviour in the Master sprite.

Reader Comments (6)

Square Root is fairly expensive. Doing this often (in a game loop) can add up. You might want to investigate approximations that work 'good enough'. (lessons learned from the old Terrarium game :-)

http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
April 22, 2013 | Unregistered CommenterMarc Jacobi
What is wrong with fried eggs? They do go with cheese.

Do you actually need the square root? If you are a mathematics purest probably, but in a game you only need to know it is less than a certain value. your choice is to keep running sq roots or just square the target distance once.
April 22, 2013 | Unregistered CommenterJohn Marshall
Why bother with the square root at all? Define SquaredMasterRadarRange and use that for the compare instead?
April 22, 2013 | Unregistered CommenterCarl Pickering
Good point. In fact I was waiting for someone to point it out. (honest)

I've used this myself. If all you need is a value to detect when something happens you might as well use the square and then save the effort of the Sqrt. On the other hand, from a play testing point of view you might like to be able to change the value in a linear way, and having the actual distance is useful in that respect. So perhaps the best way is to store both the value and the square, and then work out one from the other. But that has to happen in each of the objects because they might have different proximities, so ideally the method should be called GetDistanceFromSquared in that situation.

All good stuff.
April 22, 2013 | Registered CommenterRob
Will the full code for this be on sharepoint?
April 22, 2013 | Unregistered CommenterHello
Sorry, I can't really post my entire game code, but what you see above should be all you need to make it work. If you have any specific problems, find me and I'll go through it with you.
April 23, 2013 | Registered CommenterRob

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.