components used: TImage TPaintBox TTimer

this tutorial will work with borland kylix

Part 1Part 2 download source code

In this part we'll add a little to what we learnt in the first section of this tutorial by adding some animation to the pacman sprite itself as we move it along. We're going to make our pacman open and close his mouth as he moves.

We need to add some new variables in addition to the ones we've already declared. First we need to add a constant which is going to contain an integer which we'll use to let our program know for how long to keep each frame of animation displayed for. If we just got our animation to change from our pacman having his mouth open on one OnTimer, and closed on the next, and back, it would be too fast. So what we'll do is only get our program to change to the second frame half way through the number of frames we set, in this case six. We'll set up this constant with the following line in our const section of code.

NumOfFrames : Integer = 6;

We also need to set up two new TRects and an integer, as follows.

Image2Rect: TRect;

Mask2Rect: TRect;

CurrentFrame : Integer;

The TRects will represent our second frame of animation for both the sprite and its mask. The integer will be used to allow us to tell which frame of animation our program is on later.

Now we need to set up some new lines in our FormCreate procedure. These lines are as follows.

CurrentFrame := 1;

Image2Rect := Rect(SpriteWidth + 1, 0, SpriteWidth*2 + 1, SpriteImage.Height);

Mask2Rect := Rect(SpriteWidth + 1, 0, SpriteWidth*2 + 1, SpriteImage.Height);

It doesn't really matter where you place these three new lines in your FormCreate procedure but obviously your program will be clearer if you place the second line after the ImageRect line already there, and the third line after the MaskRect line already there. It's up to you though! If you remember the example I showed you in the last part, you'll know that the Image2Rect and Mask2Rect here have been set to look at the second frame along in our SpriteImage.

The next thing to do then is to alter our OnTimer event so that we can get our sprite to have done its full open and close animation after six frames. You'll need to alter the procedure to look like the following to do that then.

procedure TForm1.Timer1Timer(Sender: TObject);

 BufferBox.Canvas.CopyMode := cmSrcCopy;
 BufferBox.Canvas.CopyRect(AreaRect, BackgroundImage.Canvas, AreaRect);

 if CurrentFrame <= (NumOfFrames / 2) then begin

  // Draw the sprite's mask (Frame 1)
  BufferBox.Canvas.CopyMode := cmSrcAnd;
  BufferBox.Canvas.CopyRect(SpriteRect(StartX,StartY), MaskImage.Canvas, MaskRect);

  // Now draw the sprite's image (Frame 1)
  BufferBox.Canvas.CopyMode := cmSrcPaint;
  BufferBox.Canvas.CopyRect(SpriteRect(StartX,StartY), SpriteImage.Canvas, ImageRect);
 end else

CurrentFrame > (NumOfFrames / 2) then begin

  // *** Draw the sprite's mask (Frame 2) ***
  BufferBox.Canvas.CopyMode := cmSrcAnd;
  BufferBox.Canvas.CopyRect(SpriteRect(StartX,StartY), MaskImage.Canvas, Mask2Rect);

  // *** Now draw the sprite's image (Frame 2) ***
  BufferBox.Canvas.CopyMode := cmSrcPaint;
  BufferBox.Canvas.CopyRect(SpriteRect(StartX,StartY), SpriteImage.Canvas, Image2Rect);


 StartX := StartX + 1;

 // Set the frame back to 1 after every NumOfFrames
 CurrentFrame := CurrentFrame + 1;
 if CurrentFrame > NumOfFrames then CurrentFrame := 1;

 ViewingBox.Canvas.CopyMode := cmSrcCopy;
 ViewingBox.Canvas.CopyRect(AreaRect, BufferBox.Canvas, AreaRect);


The first differences you'll notice are when we get to drawing our sprite and mask images. We draw the background as we did before, but after that we check to see if the current frame we are on is less than three. If it is we draw our sprite and its mask exactly as before, if it is not then we draw our second frame in the SpriteImage instead. Pretty simple if you understood the last part of the tutorial ;-)

After that, we go on to increase the StartX coordinate by one as before, but before we put our final results into the ViewingBox, increase our CurrentFrame variable by one and then check to see if the CurrentFrame has been increased beyond the NumOfFrames variable. If it has then we reset CurrentFrame back to one. If you can't get your head round this whole animation business in this part, you can always add a label and get its caption to change to show the value of CurrentFrame on the form on each OnTimer event. If you download the code you'll see that I've added one for you which should help you a little.

Okay, so that's everything you need to know to at least start achieving flicker less animation. From now on our tutorials will make use of this kind of code so if you don't understand anything then either e-mail me or leave a message on the board.

Part 1Part 2 download source code

Subscribe to the feed NEWS Feed
archived news | mailing list

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