# velocity issues with gravity and player

22 replies to this topic

### #1paul0n0n

Member

• Members
• 37 posts

Posted 17 March 2009 - 03:59 PM

I'm new here and I hope this is something that is easy to answer.

I have a sun and planets, the planets orbit the sun with gravity. the player can orbit both the sun or planets or depending on the trajectory a combination of many. but i will just use the sun, now the sun is set in some x,y,z place.

sun(x,y,z)
player(x,y,z)

the gravity from the sun to the player works on velocities that effect the x,y,z of the player and are calculated as xv,yv,zv

player(x-xv,y-yv,z-zv) and would update player(x,y,z) with the new coordinates

this part works.

i also have the player velocities: player(pxv,pyv,pzv)
and there are player angles: Player(pitch,yaw,roll)
and the player moves by combining them. This works as well.

Now my problem, I cannot figure out how to alter the xv,yv,zv and the player(pxv,pyv,pzv):Player(pitch,yaw,roll) into a harmonious act.

example experienced: say the player is gravitating to the sun,and the player moves to the sun as well, when then i stop the velocity increase of the player the gravitating velocity does not change with the player's velocity increase.

and it's not just to the gravitating body, its in any direction. Any help would be great. Thank you.

### #2monjardin

Senior Member

• Members
• 1033 posts

Posted 17 March 2009 - 05:15 PM

Try integrating accelerations (or better yet forces) to get velocities instead.
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

### #3paul0n0n

Member

• Members
• 37 posts

Posted 18 March 2009 - 02:17 PM

I suppose i should show the gravity code. basic/sudo code

;---------------------------CREATE GRAVITY---------------------------
;gravityforce                   - is a constant gravity value
;gravity_x#			- x axis point of source of gravity
;gravity_y#			- y axis point of source of gravity
;gravity_z#			- z axis point of source of gravity
;mass# 				- combined mass of the objects
;MovingBody_x# 		- x axis point of the effected object
;MovingBody_y#		- y axis point of the effected object
;MovingBody_z#		- z axis point of the effected object
;MovingVx#			- x axis velocity of the effected object
;MovingVy#			- y axis velocity of the effected object
;MovingVz#			- z axis velocity of the effected object
;NOTE: MovingVx#, MovingVy#,MovingVz# must be global and assigned outside of the function
;                          -----EXAMPLE-----
;MovingVx# = players_x_velocity#
;MovingVy# = players_y_velocity#
;MovingVz# = players_z_velocity#
;players_x_velocity# = MovingVx#
;players_y_velocity# = MovingVy#
;players_z_velocity# = MovingVz#
;                          ---END EXAMPLE---
;Or simply use MovingVx# And MovingVy# as your main x,y velocity variables for 2d gravity. (not tested)

sd# = Abs(Distance#(MovingBody_x#,MovingBody_y#,MovingBody_z#,gravity_x#,gravity_y#,Gravity_z#))

drag# = 1
If sd# <= Atmospheric_radius# Then drag# = .98
MovingVx# =0
MovingVy# =0
MovingVz# =0
Return
EndIf

XYa# = Angle#(gravity_x#,gravity_y#,MovingBody_x#,MovingBody_y#)
YZa# = Angle#(gravity_y#,Gravity_z#,MovingBody_y#,MovingBody_z#)
ZXa# = Angle#(Gravity_z#,gravity_x#,MovingBody_z#,MovingBody_x#)
MovingVx# = ((MovingVx#+(((Sin(XYa#)+Cos(ZXa#))* gravityforce*mass#))/sd#)*drag#)
MovingVy# = ((MovingVy#+(((Sin(YZa#)+Cos(XYa#))* gravityforce*mass#))/sd#)*drag#)
MovingVz# = ((MovingVz#+(((Sin(ZXa#)+Cos(YZa#))* gravityforce*mass#))/sd#)*drag#)
EndIf
End Function

so as the player gets closer to the source of gravity it accelerates and moves around the object (unless the player is headed basically straight at it). I thought i was using acceleration or forces but I'm probably wrong.

I guess another way of stating my issue is, I cannot coordinate independent angular accelerations/movements (player) with independent positioning accelerations/movements (gravity). I hope this helps define my problem a bit more. Thank you for helping.

### #4paul0n0n

Member

• Members
• 37 posts

Posted 18 March 2009 - 03:22 PM

ooh just noticed my gravity is a bit funked. hmm. maybe i just need help with that?
nvm I think i just fixed it. I still have my original problem though.

### #5Reedbeta

DevMaster Staff

• 5307 posts
• LocationBellevue, WA

Posted 18 March 2009 - 04:07 PM

Please use [code]...[/code] tags to post code; it keeps the formatting.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #6paul0n0n

Member

• Members
• 37 posts

Posted 18 March 2009 - 04:18 PM

sorry, I forgot how to do that. Thank you.

### #7paul0n0n

Member

• Members
• 37 posts

Posted 19 March 2009 - 02:15 PM

I will be more descriptive. I have been working on this issue for many days now and cant get it right. So.. here it goes.

basic/sudo code:

;returns the angle of 2 points.
Function Angle#(x1#,y1#,x2#,y2#)
Return ((ATan2(x2# - x1#,y2# - y1#)+180) Mod 360)
End Function

I am using this to find the angle between the players(x,y,z) location and an invisible point in space that is always 5 steps in front of the player, no matter what angle/direction the player is facing. (if the point were visible, the player would always see it directly in front if them)

;Calculate gravity
MovingVx# = xv#
MovingVy# = yv#
MovingVz# = zv#
xv# = MovingVx#
yv# = MovingVy#
zv# = MovingVz#

;Set thrust, moving force.
thrust# = 0
if leftmouseclick = true then thrust# = .5

;Get angles
XYa# = Angle2#(player(x),player(y),invisiblepoint(x),invisiblepoint(y))
YZa# = Angle2#(player(y),player(z),invisiblepoint(y),invisiblepoint(z))
ZXa# = Angle2#(player(z),player(x),invisiblepoint(z),invisiblepoint(x))

;Get players velocity on above angle
player(pxv#) = ((Sin(XYa#)-Cos(ZXa#))* (thrust#))
player(pyv#) = ((Sin(YZa#)-Cos(XYa#))* (thrust#))
player(czv#) = ((Sin(ZXa#)-Cos(YZa#))* (thrust#))

;Add players velocity to gravitational velocity
xv# = xv#+player(pxv#)
yv# = yv#+player(pyv#)
zv# = zv#+player(pzv#)

;Update the players position
mx# = player(x)+xv#*timestep#
my# = player(y)+yv#*timestep#
mz# = player(z)+zv#*timestep#
Position player,mx#,my#,mz#


In theory the above should work(i think). But I've narrowed the problem down to getting my angles for the player incorrectly or used improperly for determining the velocity in the right direction. I said before that the player movement was working, it's not. sorry about that.

### #8paul0n0n

Member

• Members
• 37 posts

Posted 19 March 2009 - 03:50 PM

I figured it out.. my problem was with my angle# function

;returns the angle of 2 points.
Function Angle#(x1#,y1#,x2#,y2#)
Return ((ATan2(x2# - x1#,y2# - y1#)+180) Mod 360)
End Function
should have been
;returns the angle of 2 points.
Function Angle2#(x1#,y1#,x2#,y2#)
Return ATan2(x2# - x1#,y2# - y1#)
End Function

Its weird though.. cause the first angle works for the gravity but not for player movement?? I am using both versions of the angle function now.
everything works how I envisioned it.
thank you

### #9paul0n0n

Member

• Members
• 37 posts

Posted 25 March 2009 - 03:29 PM

I'm still having problems. What i have above tends to jump around a lot and in some directions it will gravitate toward the sun but not directly to it until a certain angle is reached then it will. Basically it's not accurately fallowing a gravitational path. I have some new code that gets better accuracy but it still just isn't right. I am changing from the previous description of the problem to better fit the issue at hand. For this description I shall use player(x,y,z), an invisible point invP(x,y,z) that is 10 steps in front of the player(x,y,z) point ,and shot(xv,yv,zv) . I will reference the angle# function from above in the code.

In this description the player is firing a weapon. the player will always be at player(0,0,0) for this example. when the player fires the weapon the shot should appear directly in front of them (center of the screen) no matter what direction the player is facing. With the code below, pitch works fine, yaw is inverted (and i cant just swap key's around cause i'm using a mouse for the player's control) .

here's what i got so far:


x#=Angle#(invP(y),invP(z),player(y),player(z)) //pitch

y#=Angle#(invP(x),invP(z),player(x),player(z)) //yaw

z#=Angle#(invP(x),invP(Y),player(x),player(y)) //roll

xv = 0     // x axis velocity

yv = 0     // y axis velocity

zv = 2     // z axis velocity

//roll

tx = ((Cos(z#) * xv) - (Sin(z#) * yv))

ty = ((Sin(z#) * xv) + (Cos(Z#) * yv))

//yaw

tx = ((Cos(y#) * xv) - (Sin(y#) * zv))

tz = ((Sin(y#) * xv) + (Cos(y#) * zv))

//pitch

tz = ((Cos(X#) * zv) - (Sin(x#) * yv))

ty = ((Sin(X#) * zv) + (Cos(x#) * yv))

shot(xv) = tx

shot(yv) = ty

shot(zv) = tz



I have looked everywhere online for tutorials and forums but none have anything that works completely. The above works for pitch and the ones from tutorials work for yaw, but not both. If you can please, please help.
Thank you.

### #10Reedbeta

DevMaster Staff

• 5307 posts
• LocationBellevue, WA

Posted 25 March 2009 - 05:09 PM

If the yaw is inverted, can't you just negate the angle to fix it?
reedbeta.com - developer blog, OpenGL demos, and other projects

### #11paul0n0n

Member

• Members
• 37 posts

Posted 25 March 2009 - 05:53 PM

Thats what i thought as well, but if i invert the yaw then both the pitch and yaw have a peek or dip at 90 and -90 degree's.
if the player rotates on the yaw axis it looks like
-----v----
where --- is the rotation and v is the dip.

### #12monjardin

Senior Member

• Members
• 1033 posts

Posted 25 March 2009 - 07:20 PM

This code would be a lot easier to read and write if you incorporated vector and matrix math routines.

If all you want is where to put the shot then the answer is trivial. Subtract the player position from the imaginary point "10 steps in front of the player" and divide by 10 to get a normalized direction vector for the player. The location of the shot is then the distance in front of the player you want the shot to appear multiplied by the unit direction vector plus the player position -- no trig functions required.
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

### #13monjardin

Senior Member

• Members
• 1033 posts

Posted 25 March 2009 - 07:28 PM

Also, you have a typo:
xv = 0     // x axis velocity
yv = 0     // y axis velocity <-- shouldn't that be a 1?
zv = 2     // z axis velocity


monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

### #14Reedbeta

DevMaster Staff

• 5307 posts
• LocationBellevue, WA

Posted 25 March 2009 - 08:06 PM

paul0n0n said:

Thats what i thought as well, but if i invert the yaw then both the pitch and yaw have a peek or dip at 90 and -90 degree's.
if the player rotates on the yaw axis it looks like
-----v----
where --- is the rotation and v is the dip.

Sounds like you're having trouble with angles wrapping around and making the trig functions do unintended things. It's not totally clear to me how your control scheme works, but if you're having the player rotate the camera with the mouse, you should just let the mouse movement change the yaw and pitch variables directly, then calculate the vector you need using spherical coordinates. Look at the spherical->Cartesian conversion on that page - it's a standard formula that's known to work right for all values of the angles.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #15paul0n0n

Member

• Members
• 37 posts

Posted 26 March 2009 - 02:08 PM

Reedbeta said:

calculate the vector you need using spherical coordinates

omg thank you this works perfectly. Talk about over thinking the problem!

now how do i get it to work if the player moves away from 0,0,0 ? That was easy enough.
but then the farther away i get from 0,0,0 the shot starts jumping around.. is there a fix for this?
so far this is what I am doing. shot has x,y,z as well, shot(x,y,z)

//start Cartesian coordinate system always at 0,0,0
// this works since the invP(x,y,z) is always 10 steps in front of the player (x,y,z) directional facing.
shot(x) = player(x)
shot(y) = player(y)
shot(z) = player(z)
tx = player(x)-invP(x)
ty = player(y)-invP(y)
tz = player(z)-invp(z)

//set up the initial velocity on each axis for use as a radial distance
xv = 0
yv = 0
zv = 2

// Cartesian coordinates to spherical coordinates
radialDistance = (xv^2+yv^2+zv^2)    //uses the velocity's
azimuth = ATan2(ty,tx)                      //uses the invP
zenith =  ATan2(SquareRoot(tx^2+ty^2),tz) //uses the invP

//convert spherical coordinates into Cartesian coordinates
shot(xv) = radialDistance * sin(zenith) * cos(azimuth)
shot(yv) = radialDistance * sin(zenith) * sin(azimuth)


### #16Reedbeta

DevMaster Staff

• 5307 posts
• LocationBellevue, WA

Posted 26 March 2009 - 04:50 PM

That code looks like it should work. However, you don't need to convert to spherical coordinates and back again - all you're doing there is scaling the tx, ty, tv vector to match the desired speed for the shot. You could do that just as well in Cartesian coordinates.

I wonder if the problem you're seeing is with how the invP point is being calculated. I don't see the need for invP at all. You can just keep track of (and/or let the user control) the desired azimuth and zenith, then convert those to Cartesian coordinates whenever needed.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #17paul0n0n

Member

• Members
• 37 posts

Posted 26 March 2009 - 11:26 PM

Reedbeta said:

That code looks like it should work. However, you don't need to convert to spherical coordinates and back again - all you're doing there is scaling the tx, ty, tv vector to match the desired speed for the shot. You could do that just as well in Cartesian coordinates.

I was trying to do that I think, but it wasn't working or I was doing it wrong. I'm still not sure how to do it, a wiki page?

### #18Reedbeta

DevMaster Staff

• 5307 posts
• LocationBellevue, WA

Posted 27 March 2009 - 02:34 AM

To scale a vector in Cartesian coordinates, all you have to do is multiply each component by the scaling factor. So if the vector is (tx, ty, tz), then (2*tx, 2*ty, 2*tz) is a vector in the same direction but twice as long.

Now if you want a vector to have a particular length, say 5, you first have to normalize it, which means scaling it to have length 1. Then you can scale it by 5, and it will have length 5. To normalize it, you just divide each component by the vector's length, which is sqrt(tx*tx + ty*ty + tz*tz).
reedbeta.com - developer blog, OpenGL demos, and other projects

### #19paul0n0n

Member

• Members
• 37 posts

Posted 27 March 2009 - 04:18 PM

Reedbeta said:

To scale a vector in Cartesian coordinates, all you have to do is multiply each component by the scaling factor. So if the vector is (tx, ty, tz), then (2*tx, 2*ty, 2*tz) is a vector in the same direction but twice as long.

Now if you want a vector to have a particular length, say 5, you first have to normalize it, which means scaling it to have length 1. Then you can scale it by 5, and it will have length 5. To normalize it, you just divide each component by the vector's length, which is sqrt(tx*tx + ty*ty + tz*tz).

I'm not sure but isn't scaling relative to the position of the object and not to the direction of the object is facing? anyway I also figured out how to use Cartesian coordinates to rotate in the same way spherical coordinates do. it's pretty easy actually, I was close yet so far away. it is done like so:

xv =0:yv=0:zv=2

sx = Sin(player(pitch))
cx = Cos(player(pitch))
sy = Sin(player(yaw))
cy = Cos(player(yaw))
sz = Sin(player(roll))
cz = Cos(player(roll))

// rotation around x
xy = cx*yv - sx*zv
xz = sx*yv + cx*zv
// rotation around y
yz = cy*xz - sy*xv
yx = sy*xz + cy*xv
// rotation around z
zx = cz*yx - sz*xy
zy = sz*yx + cz*xy

tx = zx
ty = zy
tz = yz

shot(xv) = tx
shot(yv) = ty
shot(zv) = tz


Your absolutely right about not needing invP. Though i still get the jumping around of the shot after player moves farther then about 1,000,000 steps in any direction. Strange there are no tutorials for this or anything in the wiki as well.

### #20Reedbeta

DevMaster Staff

• 5307 posts
• LocationBellevue, WA

Posted 27 March 2009 - 04:42 PM

In this case the vector you're scaling is the view direction, which has nothing to do with where the player is. A vector is just an arrow and scaling just lengthens or shortens it.
reedbeta.com - developer blog, OpenGL demos, and other projects

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users