Help with optimisation needed

Blitz3D Forums/Blitz3D Programming/Help with optimisation needed

Neo Genesis10(Posted 2003) [#1]
Got some trouble with Trouble! Anyone who has played my puzzle game would notice some slowdown whenever large numbers of conveyor belts are used in a map. This is because currently I'm checking every conveyor against every moveable block every loop.

What I'd like is to be able to optimise this so I get the same effect without killing off too many clock cycles. Here's the code.
Function MoveBlocks()

	For p.pushblok = Each pushblok
		If Not p\locked
			If p\moving And p\movcnt > 0
				Select p\dir
				Case dirNorth
					nx = p\x
					ny = p\y - 4
				Case dirSouth
					nx = p\x
					ny = p\y + 4
				Case dirEast
					nx = p\x + 4
					ny = p\y
				Case dirWest
					nx = p\x - 4
					ny = p\y
				End Select
			Else
				nx = p\x
				ny = p\y
				p\moving = False
				p\movcnt = 0
			EndIf
				
			Select CheckBColl( p, nx, ny )
			Case collision
				p\moving = False
				p\movcnt = 0
			Case destroy
				Delete p
			Case conveyor
				p\x = nx
				p\y = ny
				p\movcnt = 32
			Case reset
				Return
			Default
				p\x = nx
				p\y = ny
				p\movcnt = p\movcnt - 4
				If p\tpe = 5 And p\movcnt = 0
					p\movcnt = 32
				EndIf
			End Select
		EndIf
	Next

End Function

Function CheckBColl(p.pushblok, x, y)

	If ImagesOverlap(pushgfx, x, y, Cchr, p1\x, p1\y+15)
		Select p\dir
		Case dirNorth
			If CheckPColl(p1\x, p1\y - 4)
				If version$ = "1.4"
					LoadMap "maps\puzzle" + cur_map + ".puz"
				Else
					LoadMap "maps\map" + cur_map + ".puz"
				EndIf
				nodoor = False
				Return reset
			Else
				p1\y = p1\y - 4
			EndIf
		Case dirSouth
			If CheckPColl(p1\x, p1\y + 4)
				If version$ = "1.4"
					LoadMap "maps\puzzle" + cur_map + ".puz"
				Else
					LoadMap "maps\map" + cur_map + ".puz"
				EndIf
				nodoor = False
				Return reset
			Else
				p1\y = p1\y + 4
			EndIf
		Case dirEast
			If CheckPColl(p1\x + 4, p1\y)
				If version$ = "1.4"
					LoadMap "maps\puzzle" + cur_map + ".puz"
				Else
					LoadMap "maps\map" + cur_map + ".puz"
				EndIf
				nodoor = False
				Return reset
			Else
				p1\x = p1\x + 4
			EndIf
		Case dirWest
			If CheckPColl(p1\x - 4, p1\y)
				If version$ = "1.4"
					LoadMap "maps\puzzle" + cur_map + ".puz"
				Else
					LoadMap "maps\map" + cur_map + ".puz"
				EndIf
				nodoor = False
				Return reset
			Else
				p1\x = p1\x - 4
			EndIf
		End Select
	EndIf

	For b.pushblok = Each pushblok
		If b <> p
			If ImagesOverlap(pushgfx, b\x, b\y, pushgfx, x, y)
				Return collision
			EndIf
		EndIf
	Next

	For pn.panel = Each panel
		If ImagesOverlap(pushgfx, x, y, tiles, pn\x, pn\y)
			If Between(x - pn\x, -6, 6) And Between(y - pn\y, -6, 6)
				If pn\tpe = p\tpe
					p\locked = True
					p\x = pn\x
					p\y = pn\y
					pn\active = True
					Return True
				EndIf
			EndIf
		EndIf
	Next
	
	For s.specialzone = Each specialzone
		If ImagesOverlap(pushgfx, x, y, special, s\x, s\y)
			Select s\tpe
			Case spHole, spHole2
				If Between( x - s\x, -12, 12 ) And Between( y - s\y, -12, 12 )
					an.animfx = New animfx
					an\x = s\x
					an\y = s\y
					an\clr = p\tpe
					an\tpe = animFall
					Return destroy
				EndIf
			Case spIce
				If p\tpe = 6
					If between( x - s\x, -16, 16 ) And between( y - s\y, -16, 16)
						Delete s
					EndIf
				Else
					If x = s\x And y = s\y
						p\movcnt = p\movcnt + 32
					EndIf
				EndIf
			Case spHeat
				If p\tpe = 5
					If Between( x - s\x, -16, 16 ) And Between( y - s\y, -16, 16 )
						DeleteSmoke( s\ID )
						Delete s
					EndIf
				EndIf
			Case spConv
				If x = s\x And y = s\y
					p\moving = True
					p\dir = s\dir
					Return conveyor
				EndIf
			End Select
		EndIf
	Next
	
	For d.doorway = Each doorway
		If d\reset = 0
			If ImagesOverlap(pushgfx, x, y, door, d\x, d\y)
				If Between( x - d\x, -6, 6 ) And Between( y - d\y, -6, 6 )
					If d\anim = 0
						p\locked = True
						d\anim = danimDrop
						p\x = d\x
						p\y = d\y
						Return collision
					EndIf
				EndIf
			EndIf
		EndIf
	Next

End Function
Thanks in advance guys.


Who was John Galt?(Posted 2003) [#2]
Well not sure of the ins and outs of your game, but is one
conveyor made of a single graphic or a line of tile blocks?
If the answer is the latter you could write your own routine
to test if two rectangles overlap, and you would only need a single collision check between each movable object and each straight segment of conveyor. If it's the latter, then you could only check for collisions if the object moved in the last game loop. If neither, sorry I don't have any ideas.


Neo Genesis10(Posted 2003) [#3]
If it's the latter, then you could only check for collisions if the object moved in the last game loop
Hmm... the trouble I have is that when blocks are pushed against each other, blocking the path for example, I want the player to be able to push one block and have the others continue along the conveyor so this method will not work (as the block was stationary).

I suppose I *could* store the information of which blocks are on which conveyor and only update those which have blocks on them to save a few frames, but it still requires me to cycle through each of the special tiles multiple times.