Collisions

Blitz3D Forums/Blitz3D Beginners Area/Collisions

PowerPC603(Posted 2009) [#1]
Hi all,

I'm having difficulties understanding blitz3d collisions.

I thought if one object (say a ball) hits another object (a cube) that both objects would have registered a collision, but it's not.
I've written a small testprogram to confirm this:
Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()

; Setup frametimer (2 frames per second)
Global frametimer = CreateTimer(2)

; Setup collision types
Const colball = 1
Const colpaddle = 2

; Create camera and position it
camera = CreateCamera()
PositionEntity camera, 0, 0, -100

; Create a ball and give it a collision type
ball = CreateSphere()
PositionEntity ball, 0, 5, 0
EntityType ball, colball

; Create the paddle and give it a collision type
paddle = CreateCube()
ScaleMesh paddle, 10, 1, 1
EntityType paddle, colpaddle

; Setup collisions (ball -> paddle)
Collisions colball, colpaddle, 2, 0

; Do until "ESC" is hit
While Not KeyHit(1)
	; Wait until timer runs out
	WaitTimer(frametimer)

	; Move the ball
	MoveEntity ball, 0, 0.5, 0

	; Process collisions
	UpdateWorld

	; If the ball gets above a certain point, turn it downwards
	If EntityY(ball) > 8 Then
		TurnEntity ball, 0, 0, 180
	EndIf

	; Check if the paddle got hit
	paddlehit = EntityCollided(ball, colpaddle)

	; If the paddle got hit
	If paddlehit Then
		; turn the ball upwards again
		TurnEntity ball, 0, 0, 180
	EndIf

	; Render the world
	RenderWorld

	; Debuginfo
	Text 0, 0, "Ball: " + ball
	Text 0, 10, "Paddle: " + paddle
	Text 0, 30, "PaddleHit: " + paddlehit
	Text 0, 40, "CountCollisions ball: " + CountCollisions(ball)
	Text 0, 50, "Countcollisions paddle: " + CountCollisions(paddle)

	; Flip frontbuffer and backbuffer
	Flip
Wend

End


In this example, the ball is moving upwards (until a certain height) and downwards (until the cube gets hit).

When the ball hits the cube (paddle), the ball has registered one hit, but the paddle didn't.

How can that be?

Shouldn't both objects have one collision registered?

Now it's very difficult to figure out where the paddle was hit (in the middle, left or right side).
Because using collisionx on the paddle (to figure out where it got hit) would give an error, as you need to give a collision-index between 1 and countcollisions(paddle).
There are no collisions registered on the paddle, so you can't figure out where it got hit.
But the paddle got hit, as entitycollided(ball, colpaddle) contains the handle of the paddle.

This is very strange.
Entitycollided(ball, colpaddle) returned the handle of the paddle when the ball hit the paddle, but if you check how many collisions there were on the paddle, it says 0.

Can someone shed some light on this?

What's even more strange, is when the paddle got created before the ball.
Then it works as expected (both the ball and the paddle registered one collision).
; Create the paddle and give it a collision type
paddle = CreateCube()
ScaleMesh paddle, 10, 1, 1
EntityType paddle, colpaddle

; Create a ball and give it a collision type
ball = CreateSphere()
PositionEntity ball, 0, 5, 0
EntityType ball, colball


Here the paddle is created first, then the ball.
Now everything works as expected.
Very strange behaviour.


D4NM4N(Posted 2009) [#2]
One collides against the other, but not the other way round. If you want to register both collisions you need to apply them both ways because both are moving.

Also there is a problem with blitz collisions where you have 2 moving objects. I fixed this once by having a double logic check ie:
in pseudo-code:

Collisions colball, colpaddle, 2, 0
Collisions colpaddle, colball, 2, 0

main loop
     control and other logic     

     loopcnt=0
     while loopcnt<2
       if loopcnt=0
           apply ball(s) 3d movement
       else
           apply paddle(s) 3d movemnet
       endif
       UpdateWorld
       Perform collision logic
       loopcnt++
    endwhile
  
    renderworld
    2d draw
    flip
end loop

Something like that anyway i cannot remember the precise fix.


PowerPC603(Posted 2009) [#3]
I've tried setting up collision both ways, but it has no effect.
Btw, in the example, the paddle isn't moving at all so that can't be it.

It seems to be the order in which the entities are created, as illustrated in this second example:
Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()

; Setup frametimer (2 frames per second)
Global frametimer = CreateTimer(2)

; Setup collision types
Const colball = 1
Const colpaddle = 2

; Create camera and position it
camera = CreateCamera()
PositionEntity camera, 0, 0, -100

; Create a ball and give it a collision type
ball = CreateSphere()
PositionEntity ball, 0, 5, 0
EntityType ball, colball

; Create the paddle and give it a collision type
paddle = CreateCube()
ScaleMesh paddle, 10, 1, 1
EntityType paddle, colpaddle

; Setup collisions (ball -> paddle)
Collisions colball, colpaddle, 2, 0

; Do until "ESC" is hit
While Not KeyHit(1)
	; Wait until timer runs out
	WaitTimer(frametimer)

	; If "Spacebar" is hit, recreate the ball
	If KeyHit(57) Then
		x = EntityX(ball)
		y = EntityY(ball)
		rotation = EntityRoll(ball)
		FreeEntity ball
		ball = CreateSphere()
		PositionEntity ball, x, y, 0
		TurnEntity ball, 0, 0, rotation
		EntityType ball, colball
		ballrecreated = True
	EndIf

	; Move the ball
	MoveEntity ball, 0, 0.5, 0

	; Process collisions
	UpdateWorld

	; If the ball gets above a certain point, turn it downwards
	If EntityY(ball) > 8 Then
		TurnEntity ball, 0, 0, 180
	EndIf

	; Check if the paddle got hit
	paddlehit = EntityCollided(ball, colpaddle)

	; If the paddle got hit
	If paddlehit Then
		; turn the ball upwards again
		TurnEntity ball, 0, 0, 180
	EndIf

	; Render the world
	RenderWorld

	; Debuginfo
	Text 0, 0, "Ball: " + ball
	Text 0, 10, "Paddle: " + paddle
	Text 0, 30, "PaddleHit: " + paddlehit
	Text 0, 40, "CountCollisions ball: " + CountCollisions(ball)
	Text 0, 50, "Countcollisions paddle: " + CountCollisions(paddle)

	If ballrecreated = True Then Text 0, 70, "Ball recreated"

	; Flip frontbuffer and backbuffer
	Flip
Wend

End


When you run this code, the ball is created first, then the paddle.
When the ball hits the paddle, the ball has registered 1 collision, but the paddle has registered no collision at all, even when the "EntityCollided(ball, colpaddle)" returned the paddle handle, so in fact the paddle was hit by the ball.

If you press spacebar, the ball is re-created, so the new ball is created after tha paddle has been created.
Now both the ball and the paddle register a collision when the ball hits the paddle.

Does the order in which the entities are created have such a big impact on how collisions are processed?

Or is this a bug?
It might have been addressed before, but I can't find any information about it.
I'm using Blitz3D V1.98 btw.


D4NM4N(Posted 2009) [#4]
see above i think you posted the same time as me :)


PowerPC603(Posted 2009) [#5]
LOL, I've read your post, but sometimes I edit a previous post, instead of adding a new one.

I had this problem in my game Arkanoid3D.

First the paddle was created (and can be moved), then the ball was created.
Everything worked fine (using one-way collisions, ball to paddle).

After you picked up a powerup to make the paddle larger/smaller, it went wrong.
When picking up the powerup, the paddle entity was freed and another one (larger/smaller) was created to replace it.
So in fact the balls (which didn't get replaced) existed before the second paddle was created and the new paddle didn't register any collisions, while the first one did.