Okay, now we're getting somewhere. :)
Let's get more specific: I'm looking to adapt the following library of functions (that I'm rather fond of) to work with Sprite Candy (that I'm also rather fond of), and from studying it, I'm sure really the only functions I need to deal with (mainly) are the
Simplscroller_Draw function and the
SimpleScroller_DrawRegions one.
From what I understand, the various functions use the dark arts to split the screen up into regions and determine what tiles need drawing to which region (based on what tiles are animating etc). It draws (using good ole DrawImage) the appropriate tiles to the image in a particular buffer, then uses DrawImageRect to draw the four sections of that buffer to the BackBuffer() before Flipping and livin' la vida loca.
Now, being the 3D mega-ultra-n00b that I am, I'm having trouble
conceptually working out how to exchange out the DrawImage and DrawImageRect commands to replace them with Sprite Candy equivalents. If you know Sprite Candy, then sweet (feel free to tell me!), but otherwise I'm just looking for some guidance on the concept so I can adapt it to Sprite Candy myself.
See? :)
Here's the library I made reference to, if it adds detail to what I've said:
; ******************************************************************************
; SimpleScroller
; by TheKLF (TheKLF on BlitzCoder.com)
; ******************************************************************************
; This file exposes functionality to maintain a 8-way scrolling tilemap using
; any tile sizes (multiple of 16) and any window sizes (multiple of 16).
; The special thing about this scroller is that it uses a seperate 'buffer'
; screen to draw the content on, that wraps around. This way, only the border
; regions will need to be drawn when scrolling, which is FAST! Ofcourse there's
; a performance hit when the total area scrolled is bigger than half the screen
; because every pixel is written twice then (first to the 'buffer', then the
; 'buffer' to the backbuffer itself). But with most games, this should not
; cause problems.
; ******************************************************************************
; Versions:
; 0.0 2003-01-23 - First version
; 0.1 2003-01-25 - More optimized version with friendly functions added
; ******************************************************************************
; Credits:
; Graham N Goring for his Scroller 2002 source code. It told me the tricks :)
; ******************************************************************************
Type SimpleScrollerRegion
Field simplescroller.SimpleScroller
Field screenx ;The pixel position and size on screen of the region
Field screeny
Field screenw
Field screenh
Field mapx ;The absolute pixel position in the map where the region starts
Field mapy
End Type
Type SimpleScroller
;private fields
Field buffer ;The bitmap the buffered scroll graphics are drawn on
Field dividerx ;position of splitpoint on buffer (buffer is wrapped around by this)
Field dividery
Field tilegraphics ;The bitmap that contains the tile grpahics
Field mapbank ;The bank that will contain the tile numbers
Field tilesizebits ;The number of bits to shift for the tilesize
;public fields
Field viewportx ;The position of the viewport that will display the scrolled area
Field viewporty
Field viewportw
Field viewporth
Field tilesize ;The size of the tiles
Field offsetx ;The position of the topleft pixel of the viewport in the map
Field offsety
Field mapw ;The width of the map in number of tiles
Field maph
End Type
;Intialize SimpleScroller
Function SimpleScroller_Create(ss.SimpleScroller, viewportx, viewporty, viewportw, viewporth, tilesize, tilegraphics, mapw, maph)
If (tilesize Mod 4 <> 0) Or (tilesize / (tilesize Shr 1) <> 2) Then RuntimeError "SimpleScroller: tilesize should be 8, 16, 32 or 64"
If (viewportw Mod tilesize <> 0) Or (viewporth Mod tilesize <> 0) Then RuntimeError "SimpleScroller: viewportsize should be exact multiple of tilesize"
ss\viewportx = viewportx
ss\viewporty = viewporty
ss\viewportw = viewportw
ss\viewporth = viewporth
ss\tilesize = tilesize
ss\tilesizebits = -1
;determine the number of bits to shift for this tilesize (for optimization later)
While tilesize > 0
tilesize = tilesize Shr 1
ss\tilesizebits = ss\tilesizebits + 1
Wend
ss\tilegraphics = tilegraphics
ss\offsetx = 0
ss\offsety = 0
ss\dividerx = 0
ss\dividery = 0
ss\buffer = CreateImage(viewportw, viewporth)
ss\mapw = mapw
ss\maph = maph
ss\mapbank = CreateBank(mapw * maph Shl 2)
End Function
;Free SimpleScroller
Function SimpleScroller_Delete(ss.SimpleScroller)
If (ss\buffer) Then FreeImage(ss\buffer)
If (ss\mapbank) Then FreeBank(ss\mapbank)
Delete ss
End Function
;Shortcut functions to get and set a tile from the map
Function GetTile(ss.SimpleScroller, x, y)
Return PeekInt(ss\mapbank, (y * ss\mapw + x) Shl 2)
End Function
Function SetTile(ss.SimpleScroller, x, y, tilenr)
PokeInt ss\mapbank, (y * ss\mapw + x) Shl 2, tilenr
End Function
;Invalidate a tile in the map
Function SimpleScroller_InvalidateTile(ss.SimpleScroller, tilex, tiley)
SimpleScroller_InvalidateRegion(ss, tilex Shl ss\tilesizebits, tiley Shl ss\tilesizebits, ss\tilesize, ss\tilesize)
End Function
;Invalidate a rectangle of tiles in the map
Function SimpleScroller_InvalidateTiles(ss.SimpleScroller, tilex, tiley, tilew, tileh)
SimpleScroller_InvalidateRegion(ss, tilex Shl ss\tilesizebits, tiley Shl ss\tilesizebits, tilew Shl ss\tilesizebits, tileh Shl ss\tilesizebits)
End Function
;Invalidate a region in map pixel coordinates
Function SimpleScroller_InvalidateRegion(ss.SimpleScroller, x, y, w, h)
;If the box starts off the left of the screen we need to chop that edge off of it.
If (x < ss\offsetx) Then
w = w - (ss\offsetx - x)
x = ss\offsetx
EndIf
;If the box starts off the top of the screen, chop!
If (y < ss\offsety) Then
h = h - (ss\offsety - y)
y = ss\offsety
EndIf
;If it trails off the right of the screen...
If (x + w >= ss\viewportw + ss\offsetx) Then
w = (ss\viewportw + ss\offsetx) - x
EndIf
;If it trails off the bottom of the screen...
If (y + h >= ss\viewporth + ss\offsety)
h = (ss\viewporth + ss\offsety) - y
EndIf
;If the box is actually anywhere on the screen
If (w>0) And (h>0) And (x < ss\viewportw + ss\offsetx) And (y < ss\viewporth + ss\offsety)
r.SimpleScrollerRegion = New SimpleScrollerRegion
r\simplescroller = ss
r\mapx = x
r\mapy = y
r\screenx = (x - ss\offsetx) + ss\dividerx
r\screeny = (y - ss\offsety) + ss\dividery
r\screenw = w
r\screenh = h
EndIf
End Function
;Split regions into buffer-compatible regions where they overlap the limits
Function SimpleScroller_SplitRegions(ss.SimpleScroller)
Repeat
flag=0
For r.SimpleScrollerRegion = Each SimpleScrollerRegion
If r\simplescroller = ss Then
; --- code below removed because regions outside screen should be ignored ---
; If ( (r\screenx < 0) And (r\screenx + r\screenw-1 < 0) ) Or ( (r\screenx > ss\viewportw-1) And (r\screenx + r\screenw-1 > ss\viewportw-1) )
; r\screenx = (r\screenx + ss\viewportw) Mod ss\viewportw
; flag=1
; EndIf
; If ( (r\screeny < 0) And (r\screeny + r\screenh-1 < 0) ) Or ( (r\screeny > ss\viewporth-1) And (r\screeny + r\screenh-1 > ss\viewporth-1) )
; r\screeny = (r\screeny + ss\viewporth) Mod ss\viewporth
; flag=1
; EndIf
If (r\screenx < 0) ; box starts off the left edge of screen
r\screenx = r\screenx + ss\viewportw ; bumps it forward so the next line catches it.
EndIf
If (r\screenx + r\screenw > ss\viewportw) ; box goes off right edge of screen
rr.SimpleScrollerRegion = New SimpleScrollerRegion
rr\simplescroller = ss
rr\screenx = 0
rr\screeny = r\screeny
rr\screenw = (r\screenx + r\screenw) - ss\viewportw
rr\screenh = r\screenh
r\screenw = r\screenw - rr\screenw
rr\mapy = r\mapy
rr\mapx = r\mapx + r\screenw
flag = 1
EndIf
If (r\screeny < 0) ; box starts off the top edge of screen
r\screeny = r\screeny + ss\viewporth ; bumps it forward so the next line catches it.
EndIf
If (r\screeny + r\screenh > ss\viewporth) ; box goes off bottom edge of screen
rr.SimpleScrollerRegion = New SimpleScrollerRegion
rr\screeny = 0
rr\simplescroller = ss
rr\screenx = r\screenx
rr\screenh = (r\screeny + r\screenh) - ss\viewporth
rr\screenw = r\screenw
r\screenh = r\screenh - rr\screenh
rr\mapx = r\mapx
rr\mapy = r\mapy + r\screenh
flag = 1
EndIf
EndIf
Next
Until (flag=0)
End Function
;Fill present regions on Buffer with tile graphics
Function SimpleScroller_DrawRegions(ss.SimpleScroller)
SetBuffer ImageBuffer(ss\buffer)
For r.SimpleScrollerRegion = Each SimpleScrollerRegion
If r\simplescroller = ss Then
Viewport r\screenx, r\screeny, r\screenw, r\screenh
Cls
For xx = (r\screenx Shr ss\tilesizebits) To ((r\screenx + r\screenw-1) Shr ss\tilesizebits)
For yy = (r\screeny Shr ss\tilesizebits) To ((r\screeny + r\screenh-1) Shr ss\tilesizebits)
tx = (r\mapx Shr ss\tilesizebits) + (xx - (r\screenx Shr ss\tilesizebits))
ty = (r\mapy Shr ss\tilesizebits) + (yy - (r\screeny Shr ss\tilesizebits))
DrawImage ss\tilegraphics, xx Shl ss\tilesizebits, yy Shl ss\tilesizebits, PeekInt(ss\mapbank, (ty * ss\mapw + tx) Shl 2)
Next
Next
Delete r
EndIf
Next
SetBuffer BackBuffer()
End Function
;Draw buffer to current buffer
Function SimpleScroller_Draw(ss.SimpleScroller)
SimpleScroller_SplitRegions(ss)
SimpleScroller_DrawRegions(ss)
;Bottom-right chunk of the screen
DrawImageRect ss\buffer, ss\viewportx, ss\viewporty, ss\dividerx, ss\dividery, ss\viewportw - ss\dividerx, ss\viewporth - ss\dividery
;Top-left chunk of the screen
DrawImageRect ss\buffer, ss\viewportx + ss\viewportw - ss\dividerx, ss\viewporty + ss\viewporth - ss\dividery, 0,0, ss\dividerx, ss\dividery
;Bottom-left chunk of the screen
DrawImageRect ss\buffer, ss\viewportx, ss\viewporty + ss\viewporth - ss\dividery, ss\dividerx, 0, ss\viewportw - ss\dividerx, ss\dividery
;Top-right chunk of the screen
DrawImageRect ss\buffer, ss\viewportx + ss\viewportw - ss\dividerx, ss\viewporty, 0, ss\dividery, ss\dividerx, ss\viewporth - ss\dividery
End Function
;Scroll the SimpleScroller by a certain amount of pixels in x and y
Function SimpleScroller_Scroll(ss.SimpleScroller, deltax, deltay)
If (deltax > 0)
r.SimpleScrollerRegion = New SimpleScrollerRegion
r\simplescroller = ss
r\screenx = ss\dividerx
r\screeny = ss\dividery + deltay
r\screenw = deltax
r\screenh = ss\viewporth
r\mapx = ss\offsetx + ss\viewportw
r\mapy = ss\offsety + deltay
ElseIf (deltax < 0)
r.SimpleScrollerRegion = New SimpleScrollerRegion
r\simplescroller = ss
r\screenx = ss\dividerx + deltax
r\screeny = ss\dividery + deltay
r\screenw = -deltax
r\screenh = ss\viewporth
r\mapx = ss\offsetx + deltax
r\mapy = ss\offsety + deltay
EndIf
If (deltay>0)
r.SimpleScrollerRegion = New SimpleScrollerRegion
r\simplescroller = ss
r\screenx = ss\dividerx + deltax
r\screeny = ss\dividery
r\screenw = ss\viewportw
r\screenh = deltay
r\mapx = ss\offsetx + deltax
r\mapy = ss\offsety + ss\viewporth
ElseIf (deltay<0)
r.SimpleScrollerRegion = New SimpleScrollerRegion
r\simplescroller = ss
r\screenx = ss\dividerx + deltax
r\screeny = ss\dividery + deltay
r\screenw = ss\viewportw
r\screenh = -deltay
r\mapx = ss\offsetx + deltax
r\mapy = ss\offsety + deltay
EndIf
ss\offsetx = ss\offsetx + deltax
ss\offsety = ss\offsety + deltay
ss\dividerx = (ss\dividerx + deltax + ss\viewportw) Mod ss\viewportw
ss\dividery = (ss\dividery + deltay + ss\viewporth) Mod ss\viewporth
End Function