DirectDraw:
Scrolling Pictures
By: Jack Hoxley
Written: June 2000
Download:
DD_Scrolling.Zip
(302kb)
Scrolling backgrounds are fairly
easy once you know how; but there are several places where it is easy to slip
up; it also seems to be quite popular with people - I'm often getting asked
how to do this.
Making a scrolling background
isn't difficult at all; you just need to get the maths correct and the rectangle
to fit together correctly. The main reason everyone slips up is with wide surfaces.
Although I am not sure of this, most graphics cards support wide surfaces, that
is, a surface wider than the screen. But then there are those that dont - such
as the older computers, people also find that performance drops dramatically
when using large pictures
There are two choices - whether
you use one large backdrop divided into several smaller ones; or lots of repeating
small ones. When you're dealing with 16-32mb graphics cards you can safely go
for the first option; only when you are dealing with 4mb cards or lower does
it become a problem. Do not be fooled by the amount of video memory on a card
- My Savage 4 has 32Mb on board, yet reports that DirectDraw has 29,400kb (28.7mb)
of available memory, and my 1mb unbranded 2D card has only 602kb of available
space. Basically, although it may well have 32Mb of memory, it will old a little
back for itself - temporary data or other drivers etc... You may well think
that using system memory solves this problem, in a way it does - but it will
also slow things down.
In this example we will discuss
1-way scrolling, such as a background moving along behind a platformer game.
2-way scrolling has exactly the same ideas, but requires a little bit more thought.
We will have 3 640x480 pictures,
in total that will represent a 1920x480 surface. Dont be surprised if your computer
grinds to a halt whilst trying this, see above for why. The complex part of
doing the scrolling is working out which parts of which surface we are going
to require. We will require either one or two rectangles.
The logic behind it is:
If the X coordinate is >0 and <640 then RECT1 is on surface 1
If the X coordinate is >640 and <1280 then RECT1 is on surface 2
If the X coordinate is >1280 and <1920 then RECT1 is on surface 3
we can then work out the size
of this first rectangle from this formula:
Rect.Left = X coordinate
- (SurfaceNum *640 ) 'where the surfaces are 0,1,2
Rect.Top = 0: Rect.Bottom = 480
Rect.Right = 640 - Rect.Left |
|
|
|
Then, what if the
rectangle requires to go over the boundaries of a surface - we require a second
rectangle to Blit the second part. The easiest way to work things out here is
with a select case - If there were lots of sections you may well need to rethink
this:
Select case Xcoordinate
case is <640 'Rect1 will be part of surface 1
'So we need Rect2 to be part of surface 2
case is <1280 'Rect1 will be part of surface
2
'So we need Rect2 to be part of surface 3
case is <1920 'Rect1 will be part of surface
3
'we dont need another Rect
end select |
|
|
|
So we now know if we need a
second rectangle, and which surface it will be part of. We now need to work out
it's position:
Dim XPos As Integer
XPos = (Rect1.Right - Rect1.Left)
Rect2.Left = 0 'Always on the left hand part of the
surface
Rect2.Right = 640 - XPos 'we want the width of the
screen - the distance into the screen.
Rect2.Top = 0: Rect2.Bottom = 480 |
|
|
|
Now we should have either one
or two correctly sized rectangles. Now we need to work out their screen X/Y
coordinates, and use BltFast to copy them there...
'First (left hand) section
ddrval = backbuffer.BltFast(0, 0, Section(SurfaceNum), Rect1, DDBLTFAST_WAIT)
'Second (Right Hand) section
ddrval = backbuffer.BltFast(XPos, 0, Section(SurfaceNum + 1), Rect2, DDBLTFAST_WAIT)
|
|
|
|
Now; we should be able to
change a global variable "XCoordinate" and the program will adapt and
work the rest out itself - Easy! Should you want more sections it will be fairly
easy to do, but remember that fullscreen surfaces will use up lots of memory and
possibly stop working completely. Using sections that are smaller than the width
of the screen is easy now, just modify the correct lines above and it'll work...
You can download a working
example from the top of this page, or from the downloads
page.
|