tags:

views:

275

answers:

4

I've scored the internet for sources and have found a lot of useful information, but they are math sites trying to tell me how to solve what angle an object has to be at to reach y location. However, I'm trying to run a simulation, and haven't found any solid equations that can be implemented to code to simulate a parabolic curve. Can those with some knowledge of physics help me on this?

+4  A: 

Don't use the equations for position. Instead, use the equations for velocity. Calculate the new velocity each loop of your simulation from the object's old velocity and apply it to your object. You will need to know the elapsed time between each loop of the simulation. Of course, this works for vertical or horizontal velocity.

v_new = v_old + acceleration * delta_time  (from wikipedia)

Then apply:

position_new = position_old + v_new * delta_time;

You can use a simple acceleration of -9.8 m/s (don't forget that "down" on the screen is really an increase in the vertical position! So you can use +9.8 for simplicity). Or you could get fancy and add variable acceleration (for example, from wind, if you are also modeling the horizontal motion of the object).

Basically, the acceleration you apply is based on the sum of forces applied to the object (force of gravity, friction, jet propulsion, etc.).

F_final = F1 + F2 + ... + Fn

The following can help you with that.

If you are modeling a force applied to the object, first break the force into it's horizontal and vertical components using:

F_horiz = F * sin( angle )
F_vert =  F * cos( angle )  where angle is the angle between the force and the horizontal.

Then calculate the acceleration from the force using:

a = F / mass

(I give all credit for this knowledge to my first programming experience: GORILLA.BAS =) )

Benny Jobigan
Thanks for this lead. I'll go about checking some equations on my own as well.
DMan
big +1 for gorilla basic reference. Good times!!!
Pierreten
I just played the Gorilla game... and sucked at it :(
DMan
position_new = position_old + v_new * delta_time;Nope. That doesn't work, because the velocity is not constant during the time interval. In fact, the acceleration isn't either, unless you are simply dropping the object. Back to the drawing board. Take a peek at the answer by pheelicks if you get stuck.
Jive Dadson
@Jive: Acceleration is constant if you're neglecting air resistance and other subtler points . . . it's just the acceleration due to gravity. This is true whether dropping it or throwing it -- the difference between the two is just the initial velocity. It's true that the velocity isn't constant, but if you choose your time interval small enough you can closely approximate the true trajectory with linear segments (i.e. with velocity constant within each segment).
Tim Goodman
You are stuck with having the velocity and whatnot constant during the time interval--that's how computers work. Fortunately, computers these days are fast enough to use small enough time intervals to be able to display the motion smoothly. That's why this is a simulation, and not real life.
Benny Jobigan
+2  A: 

Some definitions:

x = x-coordinate (horizontal)
y = y-coordinate (vertical)
Vx = x-velocity
Vy = y-veloctiy
t = time
A = initial angle
V0 = intial velocity
g = acceleration due to gravity

Some equations:

Vx = V0*cos(A)
Vy = V0*sin(A) - g*t
x = V0*cos(A)*t
y = V0*sin(A)*t - (1/2)*g*t^2
Tim Goodman
Here I'm calling the initial position `x=0`, `y=0` I'm also neglecting air resistance and various other effects such as the Coriolis force due to the rotation of the Earth -- which would matter if, say, we were talking about the trajectory of an ICBM or something.
Tim Goodman
So I'm guessing I add vx and vy to x and y respectively?
DMan
You can either add `Vx` and `Vy` to the previous position at every step, or just calculate the new position using the formula for `x` and `y` as functions of `t`.
Tim Goodman
Thanks, I'll try both methods.
DMan
Incidentally with integral calculus one can see that the equations for `x` and `y` are just the equations for `Vx` and `Vy` integrated with respect to `t`. For that matter, the equations for velocity are just the time integrals of the equations for acceleration, `Ax = 0` and `Ay = -g`. So if you know how to take an integral you never have to worry about remembering these -- the derivation is immediate.
Tim Goodman
That may be more than you wanted to know, and if you don't know calculus feel free to ignore it, but I think it's nice to have some understanding of where the equations come from.
Tim Goodman
I put those equations into my game, and my object travels downwards as expected. However, how would I get it to go up first, then down (to achieve a curve)?
DMan
Give it some initial speed (`V0` in my equations) and choose an angle `A` between zero and pi radians so that that `Vy > 0` at `t = 0`
Tim Goodman
My code ends up being vx = 3 * (float)Math.Cos(0.785398); and vy = 3 * (float)Math.Sin(0.785398) - 0.4f * (float)gameTime.ElapsedGameTime.Seconds;- I'm still getting the same result?
DMan
It seems then `Vy` is positive until roughly `time = 5.3 seconds`, meaning the object is initially moving upwards. Are you saying this is not the case?
Tim Goodman
Yes, a more updated code of what I have is found here: http://pastebin.com/gHreRXLQ
DMan
Does ElapsedGameTime start at zero? Then surely `vy = 3 * (float)Math.Sin(0.785398)` is initially a positive number. It's 2.12132... What value do you get?
Tim Goodman
Hmm. I did get zero. I changed it to ElaspedGameTime.Milliseconds and got 18, but now my object only rises and never comes back down. Do you mind whipping up a sample (doesn't have to be in C#/XNA) for me to look at?
DMan
I'm wonder if the problem with your code is outside of the part you posted . . . can I see what the actual loop looks like, and where you're declaring `vx`, `vy`, `x` and `y`? You made sure that the variables themselves are floats or something as opposed to integers, right?
Tim Goodman
Also what is the change in the time interval with each repetition of the loop? And what is the latest time that you measured? It's possible to think it "only goes up" because you just didn't watch long enough to see the downward acceleration dominate the initial upward velocity.
Tim Goodman
Here is my complete code (runs under XNA if you have it): http://pastebin.com/SnvxYcmj
DMan
Try this:`vy = 0.3f * (float)Math.Sin(0.785398) - 2f * (float)gameTime.ElapsedGameTime.Milliseconds / 1000f;` If you use seconds, as you originally had it, then effectively you're treating it as a constant velocity for a full second, which I think is too long. But if you use Milliseconds, that number is going to get really big really fast and overwhelm the positive term. Really I think you want your *unit* to be seconds but with millisecond precision, which is what milliseconds / 1000f gives you.
Tim Goodman
Unless I'm doing something wrong, it always starts at Y=0 then increases (so it drops). Do I need to sent y to a different initial position?
DMan
Upon further consideration, I think perhaps the problem is that milliseconds is just giving you the *milliseconds part* of the time, when what you want is the *total* elapsed milliseconds. Is `ElapsedGameTime` a `TimeSpan`? If so, it should have a `TotalMilliseconds` property, which is what you will want to use instead of `Milliseconds`.
Tim Goodman
In other words, something like this: `vy = 0.3f * (float)Math.Sin(0.785398) - 2f * (float)gameTime.ElapsedGameTime.TotalMilliseconds / 1000f;`
Tim Goodman
It still goes down. I don't think it's your fault, there must be something I'm doing wrong.
DMan
Can you print a table of time values and the corresponding value of `vy` at each of those times? From the equations `vy` ought to be positive for small time and negative after that . . . if the numbers are coming out wrong, seeing what numbers you *are* getting could help determine why.
Tim Goodman
I got it working, thanks.
DMan
+1  A: 

Heres a nice library that might help you

http://sites.google.com/site/physics2d/

I haven't looked into it too much to be honest, I came across it in Scott Whitlock's code project article.

http://www.codeproject.com/KB/WPF/SoapBoxCorePinBallDemo.aspx

bic
+1  A: 

While Benny's answer is good, especially in its generality, you can solve your problem exactly rather than using finite integration steps. The equation you want is:

s = u*t + 0.5*a*t^2;

Look here for an explanation of where this comes from.

Here s is the displacement, u is the initial speed, a is the acceleration and t is time. This equation is only 1 dimensional, but can be easily used for your problem. All you need to do is split the motion of your projectile into two components: one parallel to your acceleration and one perpendicular. If we let Sx describe the displacement in the x direction and Sy the displacement in the y direction we get:

Sx = Ux*t + 0.5*Ax*t; 
Sy = Uy*t + 0.5*Ay*t;

Now in your particular example Ax is 0 as the only acceleration is due to gravity, which is in the y direction, ie Ay = -g. The minus comes from the fact that gravity will be acting in the opposite direction to the original motion of the object. Ux and Uy come from simple trigonometry:

Ux = U*cos(angle);
Uy = U*sin(angle);

Putting this all together you get two equations describing where the projectile will be at a time t after being launched, relative to its starting position:

Sx = U*cos(angle)*t;
Sy = U*sin(angle)*t - 0.5*g*t^2;
pheelicks
Unless I really screwed up on this, my guy doesn't move at all. Code is here http://pastebin.com/zecMTnDi- then these values are added to the x and y values.
DMan
Link does not work. I'd imagine that the reason your guy isn't moving is that your not updating your time variable t. So on every frame you should be doing something like t += 0.05;
pheelicks
Well, my time variable is gameTime, which in XNA represents the time elapsed either between frames, or the total time elapsed since the game started. Neither works.
DMan
I can't see why it wouldn't work. There must be a problem with your code elsewhere. In the equations I've given you it is clear that Sx and Sy will change if t changes, so a stationary object implies that either your t is not changing or you're not updating the position of the projectile correctly.I would avoid using gameTime as this assumes the projectile is launched when the game starts. Instead have a variable t which is set to 0 at launch and increases by a finite amount on each frame, e.g. t += 0.05
pheelicks