Collisions
Blitz3D Forums/Blitz3D Beginners Area/Collisions
| ||
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. |
| ||
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. |
| ||
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. |
| ||
see above i think you posted the same time as me :) |
| ||
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. |