3D Asteroids Movement Question

Blitz3D Forums/Blitz3D Beginners Area/3D Asteroids Movement Question

Crazy4Code(Posted 2006) [#1]
OK, well if you remember, I made a 2D asteroids game a while ago. Now, as my first step in to 3D, I'm remaking that game in 3D, except I'm only using the x and z axis so you can't move in all 3 dimensions, but it's made of meshes. So anyways,I'm having trouble with the ship physics. In my 2D version, I used this to find the direction the ship should move based on the way it's facing:
dx#=dx#+Sin(dir#)*speed#
dy#=dy#+Cos(dir#)*speed#

Then I would add dx# to the player's x and dy# to the player's y.
I tried to apply this to the 3D version:
pdx# = pdx#+Sin(-EntityYaw(ship))*pds#
pdy# = pdy#+Cos(-EntityYaw(ship))*pds#

Then I add pdx# to px#(player's x) and pdy# to py#(player's z which I treat as a y since I'm only using 2 dimensions)
The whole 'y' part of it works fine, but I'm having a problem with the 'x' part. pdx# ends up as very weird numbers i.e 3.23464e-006, therefore px# ends up a weird number like that and when I position the ship at px# it just stays at 0, I'm guessing because it can't position itself at 3.23464e-006 or a number like that.
Why is this and what can I do to fix it?


octothorpe(Posted 2006) [#2]
3.23464e-006 is not a very weird number, it's a very small number. It means 3.23464 * 10 ^ -006, which is .00000323464.

As far as I can tell, there's nothing wrong with what you're trying to do or the code you've posted. Maybe you should be using Roll or Pitch instead of Yaw - I wouldn't be sure without testing. Post enough code to demonstrate the problem.


Sledge(Posted 2006) [#3]
I'm just finishing off something similar - off the top of my head you should use Roll with x and y; or stick with Yaw and adopt x and z. If you're "looking down" on the scene then it's Yaw you want to use to rotate objects and it's the x and z axis' that they need to move along - this would seem to be the more technically correct approach to my mind.

The code itself looks odd to me. If pdx and pdy are x and y modification values then they should not accumilate, but maybe we don't have the full story as the code is only a snippet. Also, introducing a negative into both the Sin and Cos calculations seems strange - should it not be one or the other?

But yes, post code that compiles and shows us the problem, as octothorpe suggests, and we can be much more helpful.


Crazy4Code(Posted 2006) [#4]
I am looking down on the scene, so roll and pitch don't do anything. pdx and pdy are the speed at which the position of the ship changes, so that's why it accumulates. When you press forward, the speed (pdx and pdy) become larger numbers, so you end up going faster. Well anyways, I'll just post all the code so far. I'm not far into the project, so it's not too much:
;***INITIALIZATION***;
Graphics3D 1024,768,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

;***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,.1,.1,.1
PositionEntity ship,0,0,0
PointEntity ship,cam

;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

;***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)

;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 

;Game Initialization Functions
CreateAsteroids()

;MAIN LOOP
While Not KeyHit(1)
TestInput()
UpdateShip()
UpdateAsteroids()
UpdateWorld
RenderWorld
Print pdx#
Print pdy#
Flip
Wend
End

;***FUNCTIONS***
Function TestInput()
If KeyDown(203)
TurnEntity ship,0,0,-2
Else If KeyDown(205)
TurnEntity ship,0,0,2
End If 
If KeyDown(200)
AsteroidPhysics()
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)
Next
End Function 

Function UpdateAsteroids()
For a.asteroid = Each asteroid
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
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#
End Function 

and you can download the .bb file and all the media at http://www.antibox.net/grant/Asteroid Belt 3D.zip

another odd thing I notice that is probably part of the problem, is that EntityYaw(ship) is always either equal to 0.0 or -180.0. That can't be good right?


Crazy4Code(Posted 2006) [#5]
Nevermind, I got it! I just had to do a lot of rotating and testing and stuff, but it turns out the mesh wasn't rotated right, and the axis were all messed up and stuff, lol. But anyways, I think I got it all working now.


Sledge(Posted 2006) [#6]

pdx and pdy are the speed at which the position of the ship changes, so that's why it accumulates. When you press forward, the speed (pdx and pdy) become larger numbers, so you end up going faster


...and faster and faster and faster, and there's no way to model inertia when you change direction with this "direct" approach. If you start thinking about those Sin and Cos calculations in terms of generating a thrust effect which can then be applied to th ship's x and y velocities, things will fall into place. By the time you're through I'd be very surprised if you hadn't renamed pds# and changed it from a constant to a variable.


octothorpe(Posted 2006) [#7]
Sledge: eh? Inertia is being modelled here.

pdx and pdy are components of the velocity vector of the ship. px and py are the position. Presumably, the d stands for delta, which I believe is mostly correct. Personally, I would have named them pvx and pvy.

pds would be better named pa, as it's the acceleration the ship undergoes when thrust is applied, but the code is fine. Unless the ship is going to be retrofitted with a different engine than the Asteroids factory default, there's no need to replace the constant with a variable.


Sledge(Posted 2006) [#8]
No, you are right - I patched up the rotation bug he mentioned and ran it, and it didn't behave like asteroids, but only because pds is too big. It just looked like the ship was accelerating from zero rather than fighting against its previous motion everytime I rotated and thrusted... scale down pds, though, and it becomes clear that it is behaving as you'd expect. So my bad on that one and sorry if I sounded a bit patronising - shoulda' looked more thoroughly at what his code was doing.

I still think, where speed-capping is concerned, it makes more sense to stop thinking in terms of pds as a speed constant and replace it with a variable amount of thrust. As things stand he's going to have to cap pdx and pdy separately, so the ship is going to have a higher top speed diagonally (with max pdx and max pdy combined) than vertically (with max pdx alone) and horizontally (with max pdy alone). I still think a lot of the "action" is occuring on the wrong side of those Sin and Cos equations!

Anyway, my tweaks (no capping) are posted below - the new pds value shows things off a bit better and the pivot work might give Grant a few ideas, what with 'im being new to this 3D malarkey. Ooh also - don't Print, it shifts the display (debug with Text then either use a bitmap or sprite-based font system for release).




octothorpe(Posted 2006) [#9]
You don't have to cap the components of the vector (pdx and pdy) seperately. Just normalize the vector to MAX_SPEED (a constant) if the magnitude of the vector is greater than MAX_SPEED.

pdm# = sqr(pdx^2 + pdy^2)
if pdm > MAX_SPEED then
	pdx = (pdx / pdm) * MAX_SPEED
	pdy = (pdy / pdm) * MAX_SPEED
endif


I'm not sure what you're trying to get at by saying that the "action" is occuring on the wrong side of the Sin and Cos equations. Calculating a thrust force and adding it to a velocity vector makes perfect sense to me.


Sledge(Posted 2006) [#10]

I'm not sure what you're trying to get at by saying that the "action" is occuring on the wrong side of the Sin and Cos equations.



Dead simple - I never have to normalise the vector in my method because thrust is never allowed to exceed the point at which it generates the ship's maximum speed. ie I cap the input to those Sin and Cos equations, not the output of them. Each to their own I suppose.


Just normalize the vector


Y'know, that never even occured to me - thanks for pointing it out.