components used: TImage TPaintBox TTimer

this tutorial will work with borland kylix

download source code

We've recently learnt about achieving flickerless animation, but as well as moving our sprite around, we may also want to be able to scroll our background. In this tutorial you'll learn how to scroll around an image as we've done in the DelphiX tutorials, and in the next tutorial you'll learn about scrolling a tiled map (like the one made in tutorials nine and ten).

Scrolling our image isn't as difficult as you might think, and if you've just got one large image that you just want to be able to scroll around in, it's particularly easy. If you recall, when we introduced flickerless animation we made extensive use of TRects to take a particular portion of our sprite image so that we could display the correct frame of animation. We can take that principal and use it here by changing the coordinates of a TRect to reflect the portion of the large image we want to display. The diagram below illustrates this, where the purple rectangle represents the TRect. Only the area of our background image which is covered by the TRect will be visible to the user. By decreasing the X coordinate of the top left corner and the X coordinate of the bottom right corner, we move the TRect along the image, creating a scrolling effect.

So, if we open the source code from tutorial 11, let's make the necessary alterations to do just that. The first change we'll make is in the FormCreate procedure. We need to change the line that gives the size of AreaRect so that it now reads as follows.

X1 := 0; Y1 := 0;
X2 := BackgroundImage.Width;
Y2 := BackgroundImage.Height;
AreaRect := Rect( X1, Y1, X2, Y2);

We need to also declare these four new variables X1, X2, Y1, and Y2 in the private section which you should be used to doing by now. So, what have we done? Well nothing really. The program will still run as identically as it did before. What we have done though is gained our self access to the starting coordinates of our AreaRect, which we want to modify to scroll our image.

To make efficient use of these coordinates, we need to write a function which will return a TRect of coordinates, (X1,Y1,X2,Y2). The function is similar in design to that of SpriteRect except that we don't send it any values when we call it.

function TForm1.ScrollRect:TRect;
begin
  Result := Rect(X1,Y1,X2,Y2);
end;

The place where we want to use this new function is in our OnTimer procedure. The first section of this procedure draws our background onto the buffer first and its here where we need to use ScrollRect. The second line should be altered to read:

BufferBox.Canvas.CopyRect(ScrollRect, BackgroundImage.Canvas, AreaRect);

All we've done is exchange the word AreaRect for ScrollRect in the first parameter of our CopyRect line. At this stage if you were to run the program again, everything would still run exactly as before with no scrolling. But, we've now done all the ground work to allow us to start scrolling. To do that, all we need do is decrease both the X1 and X2 coordinates.

For this example, we're going to do all our scrolling in our OnTimer event, so at the end of this procedure, add the following two lines:

X1 := X1 - 1;
X2 := X2 - 1;

If you now run the program, and you've changed the background image so that it is now wider than the BufferBox and ViewingBox, you'll see the image scrolling by. Depending on how big your image is though, after awhile, your image will scroll off the left edge of the screen leaving behind it a trail of rubbish (just run it and you'll see what I mean). To get by this, we can do one of two things.

1) We can tell our program just to stop scrolling when it reaches the end of the image.

2) If both sides of our image will look okay beside each other, we can cheat and reset the coordinates back to their original values, therefore creating the illusion that we've tiled our image infinitely.

I'll demonstrate both now. The first way is the easiest (but probably not the preferred) option. All we need do is get our program to check when our image will no longer scroll nicely. In the example code, my image is exactly 1280 pixels wide and my ViewingBox and BufferBox 640 pixels wide. As I am decreasing this by one pixel each time to make our program scroll, once my X2 coordinate reaches a value less than 640, the scrolling will no longer work correctly. So, change the code to look like this instead.

if X1 > -640 then
begin

  X1 := X1 - 1;
  X2 := X2 - 1;
end;

If you try running this code now, you'll find that when the edge of the image is reached it will stop scrolling. We can now easily modify this code to achieve option two.

if X1 > -640 then
begin

  X1 := X1 - 1;
  X2 := X2 - 1;
end
else
begin

  X1 := 0;
  X2 := BackgroundImage.Width;
end;

All this does is, instead of stopping scrolling, it resets the TRect's coordinates to that which they were originally and continues scrolling, unknown to the user.

So, that's it really. I'm sure you'll agree that it wasn't too difficult. In the next tutorial we'll be dealing with situations in which the background that we might want to tile is smaller than the viewing area. In this situation you can't cheat like we did above, so things will be slightly more complicated. Until then, happy scrolling. Any questions can be asked (and probably answered) on the forums as usual.

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 ]