November 24th, 1999

Making a TRUE Pixel Scrolling Engine at Tile Scrolling Speeds

The common QB RPG does NOT have true pixel scrolling when it boasts that it does. True pixel scrolling uses the same logic and theory as a tile scrolling engine. Most of these "pixel" scrollers are merely routines that are tile by tile but the screen is "scrolled" via something like DQB/Dash and there is no actual pixel movement going on. What is happening is that it's a fancy shmancy way of screwing around with vid memory but doing the same exact thing as a tile scrolling engine. True pixel scrolling is not screwing with video memory but is actually updating at the given X,Y coordinate. It's constantly updating, and does not "Scroll" the screen. TRUE pixel scrolling is actually faster than this video ram scrolling method. Also, scrolling the video ram does not allow things like tile animation and such (a tile animation formula will be shown in this article). This can be performed with any language where you have made a clipping put routine. Here is an example of a TRUE pixel scrolling engine.

(Start of example psuedo code)

SUB ShowMap (MapX, MapY)

MapSizeX=(127)*16        'Define these in some other SUB, these are here for notation
MapSizeY=(127)*16        'This is for a 127 by 127 map (128x128 if you add in the 0)

'MapX and MapY are the exact pixel locations to update from.  They center the image onto that
'pixel which is defined in MapX, MapY.  So if you want to update at Map(1,1), MapX would be 16
'and MapY would be 16.

ShowMapx = MapX - 160    'These 2 lines here center the camera.
ShowMapy = MapY - 96

IF ShowMapx < 0 THEN ShowMapx = 0   'If the camera is off the map in the negative area, recenter
IF ShowMapy < 0 THEN ShowMapy = 0   'it at 0,0
IF ShowMapx > (MapSizeX-160) then ShowMapX=(MapSizeX-160)   'if the camera is too far, clip it at 
							    'the max point
IF ShowMapy > (MapSizeY-96) then ShowMapY=(MapSizeY-96)

PixelMapX = ShowMapx \ 16                'Does an integer divide converting the number to its t*t
PixelMapOffsetX = ShowMapx AND 15        'These lines here tell the routine where to start 
PixelMapy = ShowMapy \ 16                'plotting.
PixelMapOffsetY = ShowMapy AND 15 

PositionX = -PixelMapOffsetX
PositionY = -PixelMapOffsetY
IF PositionX < 0 THEN MaxX = 20 ELSE MaxX = 19   'If the sprites are clipped, we must put extra
IF PositionY < 0 THEN MaxY = 13 ELSE MaxY = 12   'sprites in order to place the map without 
						 'holes in the top/bottom/sides
FOR LoopMapy = 0 TO MaxY
FOR LoopMapx = 0 TO MaxX


IF anim(til).frames > 1 THEN til = til + ((frames# \ anim(til).delay) MOD (anim(til).frames))

'This above line here does tile animation for you.  It infinitely loops (with a variable frame
'delay) any number of tiles you want.  So, Tile 4 has a frame count of 4 with a delay of 3.
'Every 3rd frame, we show the next tile in the loop.  When the animation gets to the last frame,
'it uses MOD to go back to the beginning.  Tile animation done VERY quickly with only 1 line.

	putSprite PositionX, PositionY, Tiles(130*til), Solid

'This PutSprite routine must be a clipped put routine.  Whether or not it is pure QB or not is 
'up to you, but an ASM routine would work better. 130 is the amount of bytes for a 16*16 tile.  
'This way you don't have to do 100 stupid Select Cases in your main loop which is VERY slow.

	PositionX = PositionX + 16
 PositionX = -PixelMapOffsetX
 PositionY = PositionY + 16
NEXT LoopMapy

frames#=frames#+1          'Add 1 to the amount of frames we have shown (useful in counting fps)
			   'and needed for the tile animation routine above.  

(end of code)

That is how a true pixel scrolling routine works. It is not "scrolling" the screen in any sense of the word, but merely moving the camera and updating the position of what it "Sees". This is merely psuedo code and should not be implemented into your game. However, the code will work if you adapt it to your engine, and be wary of possible errors. This is a routine that will work for any language (if properly adapted).

By QbProgger