Way back in March, Marl provided a great demo program for doing UV scrolling with a parallax type effect:
http://forum.thegamecreators.com/?m=forum_view&t=194972&b=41
I really liked the effect and decided to use it in my game.
For testing purposes, I borrowed one of his images to create a new one that was the same dimensions as the resolution I'm using for my game.
I crunched the code to remove what I didn't need and set it for a single scrolled area.
Constants, UDTs and globals:
#constant NUM_LAYERS 2
#constant MAX_SCROLLX 96.0
#constant MAX_SCROLLY 48.0
#constant FRAMERATE 60.0
#constant MIN_SCALE 0.1
TYPE uvScrollType
maxStepX# AS float
maxStepY# AS float
count AS integer
tileWidth AS float
tileHeight AS float
scrollX# AS float
scrollY# AS float
speedX# AS float
speedY# AS float
changeCount AS integer
ENDTYPE
TYPE uvLayerType
i_sid AS integer
scale AS float
rand AS float
ENDTYPE
global g_uvscroll AS uvScrollType
global dim g_uvlayer[NUM_LAYERS] AS uvLayerType
Setup and scrolling functions:
function initialiseUVlayers()
// convert constant values to maximum scroll speed per frame
g_uvscroll.maxStepX# = MAX_SCROLLX / FRAMERATE
g_uvscroll.maxStepY# = MAX_SCROLLY / FRAMERATE
// Set changecount to zero so speed change occurs first loop
g_uvscroll.changeCount = 0
// initialise counter
g_uvscroll.count = 0
// get width of loaded image and set texture repeat on
g_uvscroll.tileWidth = getImageWidth(STAR_FIELD_ID)
g_uvscroll.tileHeight = getImageHeight(STAR_FIELD_ID)
// Set initial scroll position half way across the tile
g_uvscroll.scrollX# = g_uvscroll.tileWidth / 2.0
g_uvscroll.scrollY# = g_uvscroll.tileHeight / 2.0
// set up for wrapping
SetImageWrapU(STAR_FIELD_ID, 1)
SetImageWrapV(STAR_FIELD_ID, 1)
// Initialise layer sprites
for layer = 1 to NUM_LAYERS
// Precalculate scaling for layers; 1.0 for first to MIN_SCALE for last
g_uvlayer[layer].scale = 1.0 - (layer - 1.0) * (1.0 - MIN_SCALE) / ( NUM_LAYERS - 1.0 )
// random layer offset - prevents obvious repeat tiling across layers
g_uvlayer[layer].rand = random( 0 , 100 ) / 100.0
// Create Sprite and set depth, position and colour
g_uvlayer[layer].i_sid = createTheSpriteAuto(STAR_FIELD_ID)
// Set sprite depth based on layer, layer 1 is at the front
setSpriteDepth(g_uvlayer[layer].i_sid, ((BACK_DEPTH_GAME-NUM_LAYERS-1)+layer))
// If non transparent, set alpha to 255 and darken colour of layers further back
thisCol = 223.0 * g_uvlayer[layer].scale + 32.0
setSpriteColor(g_uvlayer[layer].i_sid, thisCol, thisCol, thisCol, 255)
// Set sprite position and texture scale
setSpritePosition(g_uvlayer[layer].i_sid, 0.0, 0.0)
setSpriteUVScale(g_uvlayer[layer].i_sid, g_uvlayer[layer].scale, g_uvlayer[layer].scale)
next layer
endfunction
function doUVscroll()
// Increment counter
inc g_uvscroll.count
// If counter has passed change count for this area and area is not controlled by joystick
if g_uvscroll.count > g_uvscroll.changeCount
// Set next change for a random time between 1 and 8 seconds from now
g_uvscroll.changeCount = random( FRAMERATE , FRAMERATE * 8.0 )
g_uvscroll.count = 0
// get a random value between -1.0 and +1.0 using frame rate for value spacing
// then multiply by maximum Step for each axis for new random scroll speed
g_uvscroll.speedX# = ( random( -FRAMERATE , FRAMERATE ) / FRAMERATE ) * g_uvscroll.maxStepX#
g_uvscroll.speedY# = ( random( -FRAMERATE , FRAMERATE ) / FRAMERATE ) * g_uvscroll.maxStepY#
endif
// move scroll position for each axis
g_uvscroll.scrollX# = g_uvscroll.scrollX# + g_uvscroll.speedX#
g_uvscroll.scrollY# = g_uvscroll.scrollY# + g_uvscroll.speedY#
// convert scroll position in pixels to texture offset values
thisUOffset# = g_uvscroll.scrollX# / g_uvscroll.tileWidth
thisVOffset# = g_uvscroll.scrollY# / g_uvscroll.tileHeight
// Cycle through layers, changing texture offsets of sprites
for layer = 1 to NUM_LAYERS
SetSpriteUVOffset(g_uvlayer[layer].i_sid, thisUOffset#+g_uvlayer[layer].rand, thisVOffset#+g_uvlayer[layer].rand)
next layer
endfunction
'initialiseUVlayers()' is called after all images have been loaded up and 'doUVscroll()' is called once per sync cycle during game play.
It looks quite cool. And works great in Windows and on my iPad (iOS 5.1, 16GB, run from Xcode on my Mac Mini). Both continue to have the same fast FPS. However, when I run it on my iPod Touch (iOS 5.1, 32GB), the FPS slows to a crawl, about 12.
I don't know why the UV Scrolling has this impact on only my iPod. I haven't tested on my Android, yet.
Without the scrolling, the iPod runs as fast as the iPad and Windows.
It's sad because the iPad is the primary target for my game. And I won't be able to do the very cool effect.
Oh well. Maybe I'll do seperate builds for the different platforms that support the UV scrolling effect.
Oh, and did anyone else spot the AppGameKit for Pascal showing up in thte TGC My Products page? Now I need to find a good Pascal compiler. It's been years since I was able to play in Pascal.
Cheers,
Ancient Lady