speed with CollideImage

BlitzMax Forums/BlitzMax Programming/speed with CollideImage

Nathan(Posted 2005) [#1]
I noticed that the framerate of BlitzMax can drop dramatically with CollideImage. Take e.g. the following code I found on this forum.

Graphics 640,480,32

Global tList:TList = New TList

Type img
	Field image:timage
	Field x:Float,y:Float
	Field sx:Float,sy:Float
	Field r:Float,sr:Float
	
	Function Create:img(f:String)
		i:img = New img
		i.image = LoadImage(f)
		i.x		= Rnd(20,620)
		i.y		= Rnd(20,460)
		i.sx	= Rnd(-3,3)
		i.sy	= Rnd(-3,3)
		i.r		= Rnd(0,360)
		i.sr	= Rnd(-5,5)
		tList.Addlast i
		Return i
	End Function
	
	Method Update()
		x :+ sx
		y :+ sy
		r :+ sr
		If x>620 And sx>0
			sx = -sx
		ElseIf x<20 And sx<0
			sx = -sx			
		EndIf
		If y>460 And sy>0
			sy = -sy
		ElseIf y<20 And sy<0
			sy = -sy
		EndIf
		
		SetBlend ALPHABLEND
		SetScale 0.3,0.3
		SetRotation r
		SetColor 255,255,255
		
		' Draw this image in collision layer 1
		CollideImage(image,x,y,0,0,1)
		' Test all other images with collision layer 1
		For Local i:img = EachIn tList
			If i<>Self
				' This tests i.image for collision with layer 1
				If CollideImage(i.image,i.x,i.y,0,1,0)
					' We have a collision so let's make it red!
					SetColor 255,0,0
				EndIf
			EndIf
		Next
		' Clear all collision layers
		ResetCollisions()
		DrawImage image,x,y
	End Method
	
End Type

For j = 0 To 9
	i:img = img.create("bmax120.png")
Next

Repeat
	
	Cls
	
	For i:img = EachIn tList
		i.Update()
	Next
	
	Flip
	FlushMem
	
Until KeyHit(KEY_ESCAPE)


With nine images everything runs fine, but increasing the number of images to 50 the app becomes very slow. Is something wrong with this code?

Thanks.


TeaVirus(Posted 2005) [#2]
Not sure if there's anything wrong but you could try doing a simple circle or box collision check first before doing a CollideImage check. I'm sure CollideImage is somewhat costly since it's pixel perfect.


tonyg(Posted 2005) [#3]
I think the 50 image test is doing about 30 times the 'work' as the 10 image test. I get 1ms and 25ms which seems about right.


Dreamora(Posted 2005) [#4]
50 images = 50! ( 50 * 49 * 48 * ... * 2 * 1 ) tests if they are on the same layer, perhaps this is a reason?
Seperating into different layers speeds the stuff up


xlsior(Posted 2005) [#5]
50! seems like an awfully huge number of operations to have to wait for: 3.04140932 × 10^64

Doesn't sound right...


Bot Builder(Posted 2005) [#6]
Its not 50! this would be insane. Its like 50! but with addition instead of multiplication.

(1+N)(N/2)
(1+50)(50/2)
60*25
1550 checks

Still alot, but much more reasonable XD. A box or circle check would speed this up immensly. Keep in mind when comparing distances you dont have to have square roots anywhere. So, you take the sum of the squares of the components in the vector representing the difference in position. Then, compare to the sum of the radii squared. In bmax, it is faster to multiply the radii by itself (same for the other squares). Oriented Bounding Boxes could work, but without accessing the internals of bmax (for the matrices) it would probably be slower than a circle test.


Nathan(Posted 2005) [#7]
Every image has to check 50 other images. So it's 50+50+50+...=50*50=2500 instead of 9*9=81. So I guess tonyg is correct with about 30 times the 'work', however I remember that BlitzPlus didn't have this trouble with 50 images. I don't have my PC here so I can't check.

[EDIT} Bot Builder I posted together with you. I'll take your advice and try this first (after having some sleep).


Bot Builder(Posted 2005) [#8]
An optimised system will check 50+49+48+47+... an unoptimized system will check 50+50+50+... you only need to check a specific pair once.


skidracer(Posted 2005) [#9]
To optimize I would try the following main loop-

While PLAYING
ResetCollisions
Update each object - move and write new position to collide mask
Collide each object - use collision read to change object states

Render each object
Wend

the killer in the above code could be all the ResetCollisions calls and the above design should help.

Running the code in debug mode will be much more noticable for performance also, processor intense bmx code is far more effected than graphics intense testing.

We could do with a CollideOval command also of course.