8dir collisiondetection with tweening?!

BlitzMax Forums/BlitzMax Programming/8dir collisiondetection with tweening?!

Trader3564(Posted 2008) [#1]
Below the code thats not working so well, if speed = 1 it works, if speed is greater than 1 it does not.

	'set angle
	If KeyDown(KEY_UP) And KeyDown(KEY_LEFT) 
		player.angle = 135
	Else If KeyDown(KEY_UP) And KeyDown(KEY_RIGHT) 
		player.angle = 45
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_LEFT) 
		player.angle = 225
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_RIGHT) 
		player.angle = 315
	Else If KeyDown(KEY_UP) 
		player.angle = 90
	Else If KeyDown(KEY_DOWN) 
		player.angle = 270
	Else If KeyDown(KEY_LEFT) 
		player.angle = 180
	Else If KeyDown(KEY_RIGHT) 
		player.angle = 0
	End If
	
	'check collisions
	ResetCollisions() 
	RenderLayer(World, WorldX, WorldY, WorldZ, player.layer, player.x, player.y, 1) 'this function renders the map in the collisionlayer... (unfortunatily i cannot include it as its to complicated together with all the map reading and drawing stuff.)

	'custom detection object (WORKS!!) checks for collisions on the give X, Y, using a mask which earlier was set. The last parameter is the detector ID. (e.g. NW, N, NE, etc..) 
	player.detector.Reset() 
	player.detector.Detect(player.x - 1, player.y - 1, 0) 
	player.detector.Detect(player.x, player.y - 1, 1) 
	player.detector.Detect(player.x + 1, player.y - 1, 2) 
	player.detector.Detect(player.x - 1, player.y, 3) 
	player.detector.Detect(player.x + 1, player.y, 4) 
	player.detector.Detect(player.x - 1, player.y + 1, 5) 
	player.detector.Detect(player.x, player.y + 1, 6) 
	player.detector.Detect(player.x + 1, player.y + 1, 7) 

	'add speed
	If KeyDown(KEY_UP) And KeyDown(KEY_LEFT) And Not player.detector.detectors[0] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_UP) And KeyDown(KEY_RIGHT) And Not player.detector.detectors[2] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_LEFT) And Not player.detector.detectors[5] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_RIGHT) And Not player.detector.detectors[7] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_UP) And Not player.detector.detectors[1] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_DOWN) And Not player.detector.detectors[6] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_LEFT) And Not player.detector.detectors[3] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_RIGHT) And Not player.detector.detectors[4] 
		player.speed = player.speed + 0.5
	Else
		player.speed = player.speed / 3
	End If
	
	'limit/cap speed
	If player.speed < 0.5 player.speed = 0
	If player.speed > player.maxspeed player.speed = player.maxspeed
	
	'store old positions
	player.tx = player.x
	player.ty = player.y
	
	'update positions + tweening
	Local speed:Float = (player.speed * 32) / (1000.0 / Float(update_time)) 
	player.x = player.x + Cos(player.angle) * speed
	player.y = player.y - Sin(player.angle) * speed
	
	'some stuff i tried to prevent walking through obstacles, but i failed doing so for speed > 1
	If KeyDown(KEY_LEFT) And (player.detector.detectors[0] Or player.detector.detectors[3] Or player.detector.detectors[5] ) 
		player.speed = 0
		player.x = player.tx
	End If
	If KeyDown(KEY_RIGHT) And (player.detector.detectors[2] Or player.detector.detectors[4] Or player.detector.detectors[7] ) 
		player.speed = 0
		player.x = player.tx
	End If
	If KeyDown(KEY_UP) And(player.detector.detectors[0] Or player.detector.detectors[1] Or player.detector.detectors[2] ) 
		player.speed = 0
		player.y = player.ty
	End If
	If KeyDown(KEY_DOWN) And(player.detector.detectors[5] Or player.detector.detectors[6] Or player.detector.detectors[7] ) 
		player.speed = 0
		player.y = player.ty
	End If



Trader3564(Posted 2008) [#2]
heres another attempt:

	'angle
	If KeyDown(KEY_UP) And KeyDown(KEY_LEFT) 
		player.angle = 135
	Else If KeyDown(KEY_UP) And KeyDown(KEY_RIGHT) 
		player.angle = 45
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_LEFT) 
		player.angle = 225
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_RIGHT) 
		player.angle = 315
	Else If KeyDown(KEY_UP) 
		player.angle = 90
	Else If KeyDown(KEY_DOWN) 
		player.angle = 270
	Else If KeyDown(KEY_LEFT) 
		player.angle = 180
	Else If KeyDown(KEY_RIGHT) 
		player.angle = 0
	End If
	
	'speed
	If KeyDown(KEY_UP) And KeyDown(KEY_LEFT)  'And Not player.detector.detectors[0] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_UP) And KeyDown(KEY_RIGHT)  'And Not player.detector.detectors[2] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_LEFT)  'And Not player.detector.detectors[5] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_DOWN) And KeyDown(KEY_RIGHT)  'And Not player.detector.detectors[7] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_UP)  'And Not player.detector.detectors[1] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_DOWN)  'And Not player.detector.detectors[6] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_LEFT)  'And Not player.detector.detectors[3] 
		player.speed = player.speed + 0.5
	Else If KeyDown(KEY_RIGHT)  'And Not player.detector.detectors[4] 
		player.speed = player.speed + 0.5
	Else
		player.speed = player.speed / 3
	End If
		
	'limit speed
	If player.speed < 0.5 player.speed = 0
	If player.speed > player.maxspeed player.speed = player.maxspeed
	
	If player.speed > 0
		player.vx = Cos(player.angle)  '* (player.speed * 32) / (1000.0 / Float(update_time)) 
		player.vy = -Sin(player.angle)    '* (player.speed * 32) / (1000.0 / Float(update_time)) 
	Else
		player.vx = 0
		player.vy = 0
	End If
	player.oldx = player.x
	player.oldy = player.y

	'collisions
	ResetCollisions() 
	RenderLayer(World, WorldX, WorldY, WorldZ, player.layer, player.x, player.y, 1) 
	
	Local x:Int
	Local y:Int
	For x = 1 To Abs(Ceil(player.vx)) 
		If player.vx > 0 Then
			If Not CollideImage(player.shadow, player.x + 1, player.y, 0, COLLISION_LAYER_1, 0) 
				player.x = player.x + 1
			Else
				player.x = player.oldx
				player.speed = 0
			End If
		Else
			If Not CollideImage(player.shadow, player.x - 1, player.y, 0, COLLISION_LAYER_1, 0) 
				player.x = player.x - 1
			Else
				player.x = player.oldx
				player.speed = 0
			End If
		End If
	Next
	For y = 1 To Abs(Ceil(player.vy)) 
		If player.vy > 0 Then
			If Not CollideImage(player.shadow, player.x, player.y + 1, 0, COLLISION_LAYER_1, 0) 
				player.y = player.y + 1
			Else
				player.y = player.oldy
				player.speed = 0
			End If
		Else
			If Not CollideImage(player.shadow, player.x, player.y - 1, 0, COLLISION_LAYER_1, 0) 
				player.y = player.y - 1
			Else
				player.y = player.oldy
				player.speed = 0
			End If
		End If
	Next



Trader3564(Posted 2008) [#3]
Anyone :P ?


tonyg(Posted 2008) [#4]
No idea from the segment of code you have posted. However, from your description, the problem seems to be when the objects move so quickly they jump through each other in a single cycle so they don't appear to collide. Is that right?
You can limit this by using fixed-rate logic on a smaller timestep. Alternatively look at the physics libs which will either suggest a sweep or axis-aligned bounding box (AABB) test.
p.s. Haven't looked that closely but you seem to be using delta-time and not fixed-rate logic with tweening.
<edit> this is good and this is good too.
If you get to a point when you have too many collisions to test then look for 'Shifted-grid' collisions.


Trader3564(Posted 2008) [#5]
ah, i got it

	player.oldx = player.x
	player.oldy = player.y

	player.x = player.x + Cos(player.angle) * (player.speed * 32) / (1000.0 / Float(update_time)) 
	player.y = player.y - Sin(player.angle) * (player.speed * 32) / (1000.0 / Float(update_time)) 

	'collisions
	ResetCollisions() 
	RenderLayer(World, WorldX, WorldY, WorldZ, player.layer, player.x, player.y, 1) 
	If CollideImage(player.shadow, player.x, player.y, 0, COLLISION_LAYER_1, 0) 
		player.x = player.oldx
		player.y = player.oldy
	End If

I really was over complicating stuff...


Trader3564(Posted 2008) [#6]
ugh. that didnt work. i need to step through the offset from oldX to newX, that should do it i guess.

-EDIT- its fixed. it was a scrolling related problem. The movement was working all the time.


tonyg(Posted 2008) [#7]
btw you'll get more response if you state what it is you're trying to do, post a small working example of what you have so far and explain what the problem is.