components used: TDXDraw TDXImageList TDXSprite

delphix does NOT work with borland kylix

Part 1Part 2Part 3 download source code

In this final part, we'll introduce a second sprite, so that you're sure of how we use and add sprites. We'll also deal with collision and changing our sprite's animation mid-way through our program.

We'll start by adding the following code after our previous sprite declaration:

TGhost = class(TImageSprite)
public
procedure
DoMove(MoveCount: Integer); override;
end;

This sets up our TGhost sprite, in the same way we set up TPacman before. We then just need to add the following line in the var section to assign this class to a variable:

Ghost: TGhost;

Simple. Now before we continue, let's add our ghost sprite to the DXImageList component, calling it Ghost. The ghost images I used are shown here, again provided by Dicon Peeke.

Ghost Sprites

We need to set the PatternWidth property of this image to 35 this time, as our sprites are slightly 'chubbier'. While you're here, you might want to also add the following image (called Explode), setting its PatternWidth property to 28, as we'll be using that as well in this example.

Explode Sprites

Now we have that set up we can initialise our Ghost sprite with the following code in our form's OnCreate event.

Ghost := TGhost.Create(DXSpriteEngine1.Engine);

Ghost.Image := Form1.DXImageList1.Items.Find('Ghost');
Ghost.X := 400;
Ghost.Y := 10;
Ghost.Width := 35;
Ghost.Height := Ghost.Image.Height;
Ghost.AnimCount := 2;
Ghost.AnimLooped := True;
Ghost.AnimSpeed := 50/1000;
Ghost.AnimStart := 0;

I won't go over the details of this again, suffice to say that the only difference here is the individual values of the X and Y coordinates and the replacing of the word 'Pacman' with the word 'Ghost'. I should point out that this time we have specified the width of our sprite. This is because we are dealing with a collision and our program needs to know the width of this sprite and indeed, the width of our Pacman sprite. With that in mind, add the following line before the Pacman.Height line:

Pacman.Width := 28;

We haven't done anything different really so far, but now we'll change all that by adding a DoCollision procedure to our TPacman. We do this by placing the following code in our code for the TPacman class, just after the DoMove procedure has been declared:

procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;

This allows us to add a procedure to place code in for dealing with any collision the pacman has with another sprite. The code for this is shown below and should be placed in your program after the TPacman.DoMove procedure to keep things organised.

procedure TPacman.DoCollision(Sprite: TSprite; var Done: Boolean);
begin
 if Sprite is TGhost then
 begin
  Pacman.Image := Form1.DXImageList1.Items.Find('Explode');
  Pacman.Width := 28;
  Pacman.Height := Pacman.Image.Height;
  Pacman.AnimCount := 5;
  Pacman.AnimLooped := False;
  Pacman.AnimSpeed := 50/1000;
  Pacman.AnimStart := 0;
  PacmanDead := True;
 end;
end;

This procedure starts by checking to see if the sprite that has been hit is of the type TGhost. If it is then the lines that follow are carried out. Of course, in our program a collision can only occur with TGhost as it is the only sprite available to bump into. If you were to later add other sprites which you wanted to cause a different reaction when hit though, this would be useful. It's worth keeping here for now anyway to give you a useful lesson! So, when our Pacman collides with the ghost, we want it to change its image to that of our Explode image, remembering to change the width, height, number of animation cells, speed and starting cell. We need to also set the looped property to false so as not to keep repeating the explosion animation over and over again. We then finally set a new boolean variable, PacmanDead to true, which we will use in our Pacman.DoMove procedure next. You can set up this variable in the usual way, in the main var part of our program. It should be noted that what we have done here is simply run a different animation in replacement of the last, telling it to do no further animations after this. The sprite is still there, it's just that we can't see it because the last animation cell in our Explode image is blank. To actually delete the sprite you need to call the Dead; line and put the line DXSpriteEngine1.Dead; as the first line of our OnTimer procedure to check for any 'dead sprites'. Obviously, in a large game we would want to call this so as not to take up valuable memory with lots of sprites sitting about, but for the purposes of this example, we don't really need to.

So, to make use of our new collision procedure we need to modify our TPacman.DoMove procedure so that it looks something like this:

procedure TPacman.DoMove(MoveCount: Integer);
begin
 inherited;
 if
PacmanDead = False then begin
  PixelCheck := True;
  Pacman.X := Pacman.X + 1;
  Collision;
 end else
end;

So what does this do then? Well, firstly we check to see if our PacmanDead variable is true or false, and if it is False (ie. our Pacman is still alive) we carry out the lines that follow. The following line sets the PixelCheck property to true. This property allows us to carry out collisions only when the actual edges of our Pacman and Ghost images touch each other, rather than when the transparent surrounding areas touch. This is illustrated below in case you're unsure. It is a great feature as it allows us to carry out collisions realistically which don't look as though we haven't actually collided with anything. Try setting this property to false as well to see what I mean if you don't understand my dodgy example pictures below. After we've set PixelCheck to true, we need to move our pacman along to the right by one pixel as before, but before we finish we need to call the doCollision procedure. As we are within a TPacman procedure we only need to write Collision; but if we were in any other procedure we'd need to write TPacman.Collision; so that our program knew which collision procedure to run.

PixelCheck Bounding Boxes

With PixelCheck set to false, the outside area of our sprite only need to touch to cause a collision, seen here with a slightly brighter red.

PixelCheck - pixels

With PixelCheck set at True, the actual pixels of the pacman and ghost need to touch in order to cause a collision.

That's it then. Running this program will give you a pacman sprite moving across the screen until it bumps into the ghost and explodes. Perhaps not the most inspirational program ever, but in the next tutorial we'll cover scrolling backgrounds and the different ways of moving our pacman around with the DXInput component already covered. Give yourself a pat on the back if you've made it through all three parts of this tutorial, you've learnt a lot and you should hopefully now be able to think about how you could make some basic games with it. If you have any questions, or if you notice any mistakes or things I've missed out, then just e-mail me at ben@delphigamedev.com. Until next time, happy programming.

Part 1Part 2Part 3 download source code

Subscribe to the feed delphigamedev.com NEWS Feed
archived news | mailing list

[ all tutorials found at delphigamedev.com are Copyright © 2008 Ben Watt ]