Collision Issue

Blitz3D Forums/Blitz3D Beginners Area/Collision Issue

It's hard to explain, but i'm having a problem with the collision between my ship and the asteroids. Download it here and see for yourself. I think it might have something to do with my changing px# and py# instead of using MoveEntity, but I don't know much about that. The ship seems to jump around the screen. I'm thinking it's because px and py keep changing even if the collision happens, so after it's not coliding anymore, it jumps to the spot where px and py are?

Personally I would (and have) ditch(ed) the automated collision system and just use(d) meshesintersect(). If it's too slow, use simpler, invisible collision meshes.

However, you might want to try TranslateEntity() first, as your code already generates the values to translate the ship by. I *think* ellipsoid-to-ellipsoid collisions are supposed to work "both ways" (for ellipsoid-to-polygon, by contrast, the dest_type must be immobile) although you *might* have to define a reverse Collisions statement (ie asteroid-to-ship in addition to the ship-to-asteroid one you have). Plenty to try, there.

Okay, I used MeshesIntersect(), but it still seems a little buggy. It seems to only tell that they are colliding sometimes, and other times it just doesn't. I tried doing reverse collision statements too.

Well I was feeling curious - see what you think of this (and pay particular attention to where the updateworld()'s occur, and how hideentity is used to uninvolve objects from the collision system when warping them from one side of the playfield to the other)...

;***INITIALIZATION***;
Graphics3D 800,600,16,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()

;***VARIABLES***;
Global pdx#, pdy# ;Player's direction in the 2 1/2D world
Global px#, py# ;Player's coordinates
Const pds# = 0.01 ; Player's speed

;Collision Constants
Const SHOTTYPE = 3
Const PLAYER = 1
Const AST = 2

;***ENTITIES***;
;Camera 
Global cam = CreateCamera()
CameraRange cam,1,1000
PositionEntity cam,0,10,0
RotateEntity cam,90,0,0

;Spaceship
Global ship = LoadMesh("fighter.3ds")
ScaleEntity ship,.05,.05,.05
PositionEntity ship,0,0,0
PointEntity cam,ship
RotateMesh ship,270,0,0
EntityType ship,PLAYER

;Main Light
light = CreateLight(1)
RotateEntity light,90,0,0

;Skybox
skybox = CreateSphere()
FlipMesh skybox
skytex = LoadTexture("stars.jpg")
ScaleTexture skytex,.09,.09 
EntityTexture skybox,skytex
ScaleEntity skybox,500,500,500
PositionEntity skybox,0,50,0
EntityOrder skybox,1

;Shot Sprite
Global shotsprite = LoadSprite("shot.bmp")
ScaleSprite shotsprite,.05,.05
SpriteViewMode shotsprite,1
HideEntity shotsprite
EntityType shotsprite,SHOTTYPE

;***ARRAYS***;
Dim astmesh(3)
;Big Asteroid
astmesh(1) = LoadMesh("asteroid.3ds")
ScaleMesh astmesh(1),.1,.1,.1
RotateMesh astmesh(1),0,0,0
HideEntity astmesh(1)
EntityType astmesh(1),AST

;Medium Asteroid
astmesh(2) = CopyMesh(astmesh(1))
ScaleMesh astmesh(2),.5,.5,.5
HideEntity astmesh(2)

;Little Asteroid
astmesh(3) = CopyMesh(astmesh(2))
ScaleMesh astmesh(3),.5,.5,.5
HideEntity astmesh(3)

;***TYPES***;
Type asteroid
Field x#,y# ;Asteroid's position in the 2 1/2D world
Field mesh ;Asteroid's mesh
Field vx#,vy# ;Asteroid's x and y velocities
End Type 

Type shot
Field x#,y# ; shot's 2 1/2D position
Field vx#,vy# ;shot's speeds
Field sprite
Field timer
End Type 

;***COLLISIONS***;
Collisions PLAYER,AST,1,2
Collisions AST,PLAYER,1,2

;Game Initialization Functions
CreateAsteroids()

;MAIN LOOP
While Not KeyHit(1)
TestInput()
TestShipOB()
UpdateShip()
UpdateAsteroids()
UpdateShots()
;UpdateWorld
RenderWorld
Flip
Wend
End

;***FUNCTIONS***
Function TestInput()
If KeyDown(203)
TurnEntity ship,0,1,0
Else If KeyDown(205)
TurnEntity ship,0,-1,0
End If 
If KeyDown(200)
AsteroidPhysics()
End If 
If KeyHit(57)
CreateShot()
End If 
End Function 

Function CreateAsteroids()
For i = 1 To 3
a.asteroid = New asteroid 
a\x# = 0
a\y# = 0
a\mesh = CopyMesh(astmesh(1))
a\vx# = Rnd(-.1,.1)
a\vy# = Rnd(-.1,.1)
EntityType a\mesh,AST
Next
End Function 

Function UpdateAsteroids()
For a.asteroid = Each asteroid
TranslateEntity a\mesh,a\vx#,0,a\vy#
UpdateWorld()
Next
;a\x# = a\x# + a\vx#
;a\y# = a\y# + a\vy#
;If a\x# > 15
;a\x# = -15
;Else If a\x# < -15
;a\x# = 15
;End If 

;If a\y# > 15
;a\y# = -15
;Else If a\y# < -15
;a\y# = 15
;End If
 

;PositionEntity a\mesh,a\x,0,a\y#
;Next

For a.asteroid = Each asteroid
HideEntity a\mesh
If EntityX(a\mesh) > 15
	PositionEntity a\mesh,-15,EntityY(a\mesh),EntityZ(a\mesh)
Else If EntityX(a\mesh) < -15
	PositionEntity a\mesh, 15,EntityY(a\mesh),EntityZ(a\mesh)
End If 

If EntityZ(a\mesh) > 15
	PositionEntity a\mesh,EntityX(a\mesh),EntityY(a\mesh),-15
Else If EntityZ(a\mesh) < -15
	PositionEntity a\mesh, EntityX(a\mesh),EntityY(a\mesh),15
End If 
ShowEntity a\mesh
Next

End Function 

Function AsteroidPhysics()
pdx# = pdx# + Sin(EntityYaw#(ship))*pds# 
pdy# = pdy# + -Cos(EntityYaw#(ship))*pds#
End Function 

Function UpdateShip()
px# = px# + pdx#
py# = py# + pdy#
;PositionEntity ship,px#,0,py#
TranslateEntity ship,pdx,0,pdy
UpdateWorld
End Function 

Function TestShipOB()
HideEntity ship
If EntityX(ship) > 10
	PositionEntity ship,-10,EntityY(ship),EntityZ(ship)
Else If EntityX(ship) < -10
	PositionEntity ship, 10,EntityY(ship),EntityZ(ship)
End If 

If EntityZ(ship) > 10
	PositionEntity ship,EntityX(ship),EntityY(ship),-10
Else If EntityZ(ship) < -10
	PositionEntity ship, EntityX(ship),EntityY(ship),10
End If 
ShowEntity ship 
End Function 

Function CreateShot()
s.shot = New shot
s\x# = px#
s\y# = py#
s\vx# = pdx# + Sin(EntityYaw#(ship))*pds#*4 
s\vy# = pdy# + -Cos(EntityYaw#(ship))*pds#*4
s\timer = 0
s\sprite = CopyEntity(shotsprite)
End Function 

Function UpdateShots()
For s.shot = Each shot
s\x# = s\x# + s\vx#
s\y# = s\y# + s\vy#
s\timer = s\timer + 1
If s\x# > 15
s\x# = -15
Else If s\x# < -15
s\x# = 15
End If 

If s\y# > 15
s\y# = -15
Else If s\y# < -15
s\y# = 15
End If 

PositionEntity s\sprite,s\x#,0,s\y#
If s\timer > 200
FreeEntity s\sprite
Delete s
End If 
Next
End Function 



Okay, I used MeshesIntersect(), but it still seems a little buggy.


That is odd - I have always found it robust (the only thing to take care to ensure is that the meshes in question are not flat, which they aren't here). There's no collision response with the command - meshes will just drift through each other, but for Asteroids this is typically okay because as soon as you hit one you're dead!

Depending what you think of the code I posted above, you might not be interested in MeshesIntersect() any more; but if you want me to cast my eye over the MeshesIntersect code you found troublesome then post away.

Wait, I found a way that it works. I changed my movement system to use TranslateEntity instead of PositionEntity, then the collisions worked fine. The only thing is to make it work I had to have both "Collisions PLAYER,AST,1,2" and "Collisions AST,PLAYER,1,1" is it normal that I would have to have both of those for it to work?


I changed my movement system to use TranslateEntity instead of PositionEntity, then the collisions worked fine.


Great minds... ;)


The only thing is to make it work I had to have both "Collisions PLAYER,AST,1,2" and "Collisions AST,PLAYER,1,1" is it normal that I would have to have both of those for it to work?


I'll say yes, because we're talking about computers and computers are dumb. Just as it is possible to have a one-sided object, it is possible to have one-sided collisions... unlike in the real world, the existence of one "side" does not infer the existence of the other. The first Collisions command is only concerned with what the Ship has hit and until you create an additional command to keep track of what the Asteroids have hit, they can't hit anything.

If you think about it, though, this is smart: If the compiler assumed that every time the ship hit an asteroid you also wanted a record of the asteroid hitting the ship *without you asking for it* the CPU could potentially waste a lot of time collating information that you just don't need. The system is geared for speed and processing no more information than you specifically request.