Scrolling Image ...Slow...

BlitzMax Forums/BlitzMax Programming/Scrolling Image ...Slow...

CoderLaureate(Posted 2005) [#1]
Hi guys, I'm trying to write a function that will wrap an image (scroll it in one direction and wrap it around to the other side).

I've got this:
Function WrapImage(img:TImage, frame = 0, stepsize = 20, dir = 1)
	Local w:Int = img.Width
	Local h:Int = img.Height	
	Local tStep:TImage
	Local tOther:Timage

	Cls
	
	DrawImage img,0,0,0
	
	Select dir
		Case	1		'Left to Right
			tStep = CreateImage(stepsize,h)
			tOther = CreateImage(w - stepsize,h)
			GrabImage(tStep,w - stepsize,0)
			GrabImage(tOther,0,0)
			Cls
			DrawImage tStep,0,0
			DrawImage tOther,stepsize,0
			GrabImage(img,0,0)
	End Select
	
End Function

But it's slow as molasses in January.

Is there a way to speed this code up?


Fetze(Posted 2005) [#2]
That's because GrabImage is very slow and you even use it three times. I think you should try to modify the texture's u and v-coords.


anawiki(Posted 2005) [#3]
why you just dont draw it offscreen? ie.

drawimage img, -10, 0
drawimage img, -10+imagewidth, 0

of course it's not the same as in your example, but if you scroll full screen width it should no matter :)


CoderLaureate(Posted 2005) [#4]
I suppose there's no equivalent to the "CopyRect" command in BMax is there.

Modify the texture's u/v coords you say?

I'll check into that.
Thanks!


tonyg(Posted 2005) [#5]
There's some code which will emulate the old drawimagerect function (either using UV or setviewport). You might be able to display the image twice, once from point 0,0 in the image and the other
0+xchange,0+ychange but it's fiddly.


IPete2(Posted 2005) [#6]
I would draw the image twice, side by side and scroll both in the direction you want, then once the first image has completely left the screen simply move it back the full width of the screen. This is a variation of the coarse scroll used in Atari's days.

IPete2.


Fetze(Posted 2005) [#7]
Yeah, sounds better than modifying u/v-coords *g*
You should take a look at SetViewport as tonyg said.


CoderLaureate(Posted 2005) [#8]
I like your idea IPete2.

However,

I just wrote this little ditty.
Kind of like the early stages of a tile mapping object or something:
Strict

Type TTiledImage
	Field StepSize = 10      
    Field ColumnCount:Int
    Field RowCount:Int
	Field Tiles:TImage[]
	Field Direction:Int     
	Field WinWidth:Int
	Field WinHeight:Int
	  
	Field GetImageCallback(tw:TTiledImage)
	                         
	'Create from image
	Method FromFIle:Int(url:Object,StepSize = 10)
		Local temp:TImage = LoadImage(url)
		If ImageWidth(temp) Mod StepSize = 0 and ImageHeight(temp) Mod StepSize = 0 Then
			RowCount = ImageHeight(temp) / StepSize
			ColumnCount = ImageWidth(temp) / StepSize     
			WinWidth = ColumnCount
			WinHeight = RowCount
			Tiles = New TImage[ColumnCount * RowCount]
			Cls
			DrawImage temp,0,0
			For Local r:Int = 0 To RowCount - 1
				For Local c:Int = 0 To ColumnCount - 1 
					Local tt:TImage = CreateImage(StepSize,StepSize)
					GrabImage(tt,c * StepSize,r * StepSize)
					Tiles[c + r * ColumnCount] = tt        
					If GetImageCallback <> Null Then GetImageCallback(Self)
				Next
			Next       
			Cls
			Return True
		Else
			RuntimeError ("Step size must divide evenly into image width and height.")
		End If
	End Method
	
	Method Render(posX:Int, posY:Int,oX:Int, oY:Int, w:Int = -1, h:Int = -1)
		Local c:Int = ColumnCount - oX
		Local r:Int = RowCount - oY 
		If w <> -1 Then WinWidth = w
		If h <> -1 Then WinHeight = h
		For Local ir:Int = 0 To WinHeight   - 1
			For Local ic:Int = 0 To WinWidth - 1
				If c = ColumnCount Then c = 0
				If r = RowCount Then r = 0       
				DrawImage Tiles[c + r * ColumnCount],posX + ic * StepSize, posY + ir * StepSize
				c:+ 1
			Next  
			c = ColumnCount - oX
			r:+ 1
		Next
	End Method
	
End Type 


'Test Code
Graphics 640,480,0

Local map:TTiledImage = New TTiledImage    
map.FromFIle("Panda-Kiss.jpg")

Local ox:Int = 0      
Local oy:Int = 0

While not KeyHit(KEY_ESCAPE)
	Cls
	map.Render(10,10,ox,oy)     
	'ox:+ 1; oy:+ 1
	If KeyDown(KEY_UP) Then oy:-1
	If KeyDown(KEY_DOWN) Then oy:+1
	If KeyDown(KEY_LEFT) Then ox:-1
	If KeyDown(KEY_RIGHT) Then ox:+1
	If ox = map.ColumnCount Then ox = 0
	If ox < 0 Then ox = map.ColumnCount  - 1
	If oy = map.RowCount Then oy = 0
	If oy < 0 Then oy = map.RowCount - 1
	
	Flip                                     
	'Delay 1000
Wend


Try it with this photo: