Thread: Force and Velocity Physics

  1. #1
    Registered User IdioticCreation's Avatar
    Join Date
    Nov 2006
    Location
    Lurking about
    Posts
    229

    Force and Velocity Physics

    I'm having trouble with the physics in my asteroid game. This is how I'm doing it now:

    For the ship I know:
    • It's heading in degrees (I'm thinking using degrees was a bad idea now.)
    • It's speed
    • It's position
    • It's direction of momentum (The direction it's moving).


    Basically when thrust is pressed, the direction of momentum is set to the ships current heading, then the ship is moved based off of that.

    Now, it doesn't look that bad, except when you accelerate in a straight line, stop accelerating and change the direction of the ship, then thrust in the new direction. Instead of make a kind of arc like you would expect, it suddenly changes to the new direction.

    I have some vague ideas of how fix this, but I wanted your advice

    David
    Last edited by IdioticCreation; 12-16-2007 at 05:40 PM.

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Storing its heading is good, though you may want to store it in radians, given that that's what the trig functions in C++ use.

    Storing speed and momentum direction separately is a bad idea. You need to store a movement vector. (Basically, its direction multiplied by the speed.) Every time unit, you simply add the vector to the position vector, and you've got the new position.

    For thrust, you simply add sin(heading) to the x component of speed, and cos(heading) to the y component. If you want, you can multiply those by the thrust strength (e.g. if there's a power booster or something, or if it's simply off scale). You may also have to multiply it by the time delta. E.g. if you say that the spaceship accelerates by 1 per time unit, and 0.4 time units have elapsed since your last loop, you need to multiply by 0.4. If the player collects a thrust boost powerup, making his acceleraton 2.5 per time unit, then the next frame (0.6 time units later) must multiply by 1.5.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Registered User IdioticCreation's Avatar
    Join Date
    Nov 2006
    Location
    Lurking about
    Posts
    229
    Storing its heading is good, though you may want to store it in radians, given that that's what the trig functions in C++ use.
    Yeah, I should, because I was just converting it on the fly for the trig functions.

    Storing speed and momentum direction separately is a bad idea. You need to store a movement vector. (Basically, its direction multiplied by the speed.) Every time unit, you simply add the vector to the position vector, and you've got the new position.
    So a movement vector has, say rads multiplied by the speed?

    I don't think this will fix the problem I'm really having trouble with. Here if you are on Windows you can test this and see what I mean.
    http://idioticproductions.net/stuff/Asteroids2.zip
    Just accelerate in one direction, stop accelerating and change direction then accelerate again.
    You will see it just doesn't look right.

    Thanks for your help though.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You add the vectors together to get what you want.

    velocity.x += thrust.x;
    velocity.y += thrust.y;
    Last edited by VirtualAce; 12-16-2007 at 11:08 AM.

  5. #5
    Registered User IdioticCreation's Avatar
    Join Date
    Nov 2006
    Location
    Lurking about
    Posts
    229
    I really appreciate the effort, but I just can't comprehend it. Would you mind giving me a quick example?

  6. #6
    Registered User
    Join Date
    Apr 2006
    Posts
    43
    This is what CornedBee and Bubba was talking about.

    Store your positions, velocities and forces in vectors, that is something like
    Code:
    float speed[2];
    (or create a vector class with operator overloading.)

    Let the first value in the vector be the x value and the second value be the y value.

    Then your position update function would be something like this:

    Code:
    // angle is the direction of the object in radians.
    force[0] = cos(angle) * thrust;
    force[1] = sin(angle) * thrust;
    
    for (i = 0; i < 2; i++) {
      // mass is a float with the mass of the object and time_step is the time between each frame.
      velocity[i] += mass * force[i] * time_step;
      position[i] += velocity[i] * time_step;
    }
    And then you just draw the object at its new position.

    Try searching google for vector class implementations (most are 3d but that doesn't matter).

    Good luck.

    /f

  7. #7
    Registered User IdioticCreation's Avatar
    Join Date
    Nov 2006
    Location
    Lurking about
    Posts
    229
    OK, wow. The first time I read through that I didn't really get what you were doing, but then it just clicked. Once I get it all working nicely I'll post it in the games sticky.

    Thank you so much guys!

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I don't take into account the mass but do the same thing.

    Code:
    void PlayerShip::Thrust()
    {
    
        m_vecVel.x -= (sinf(m_Angle)*1.5f);
        m_vecVel.y += (cosf(m_Angle)*1.5f);
    
    
    }
    
    void PlayerShip::Update(float fTimeDelta)
    {
        m_vecPos.x += (m_vecVel.x * fTimeDelta);
        m_vecPos.y += (m_vecVel.y * fTimeDelta);
        ...
    The - and + in Thrust() are to align my coordinates.

    BTW you should probably divide by mass since a large mass in that posted equation will result in a large overall velocity which is inverse of what should really happen.

    It's F=ma but in this case we are trying to find out the acceleration, not the force. The force being applied is the thrust vector. So the result is A= F/m.
    Last edited by VirtualAce; 12-17-2007 at 01:20 AM.

  9. #9
    Registered User IdioticCreation's Avatar
    Join Date
    Nov 2006
    Location
    Lurking about
    Posts
    229
    OK, well I think is what is throwing me off, is when you are using (x,y) I don't know if you mean them as coordinates or as vector x and y components?

    So for this example that you gave:
    velocity.x += thrust.x;
    velocity.y += thrust.y;

    velocity x and y aren't coordinates, they must be the a and b of the triangle formed by the velocity vector?

    Sorry I'm slow about this stuff, I just haven't had any courses over it yet, and it's hard for me to learn this stuff off internet tutorials.

    EDIT: Yah! sweet, that did the trick. It works great now.
    Last edited by IdioticCreation; 12-17-2007 at 09:57 PM.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by IdioticCreation View Post
    OK, well I think is what is throwing me off, is when you are using (x,y) I don't know if you mean them as coordinates or as vector x and y components?
    With vectors, there isn't much difference. It's only in the usage. When the vector describes a position, x and y are coordinates. When it describes movement, they are offsets. When it describes thrust, they are force components. And so on.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered User
    Join Date
    Apr 2006
    Posts
    43
    As Bubba pointed out, I should of course have written that you should multiply with the inverse of the mass...

    Code:
    // angle is the direction of the object in radians.
    force[0] = cos(angle) * thrust;
    force[1] = sin(angle) * thrust;
    
    for (i = 0; i < 2; i++) {
      // mass is a float with the mass of the object and time_step is the time between each frame.
      velocity[i] += inv_mass * force[i] * time_step;
      position[i] += velocity[i] * time_step;
    }
    /f

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by fractality View Post
    This is what CornedBee and Bubba was talking about.

    Code:
      velocity[i] += mass * force[i] * time_step;
    That simply isn't right. According to this, objects with larger masses will accelerate more quickly than objects with smaller masses. Get back to the basic equation:

    F = ma
    a = F / m

    Make the finite difference approximation:

    a = dv/dt ~= delta_v / delta_t = F / m
    delta_v = F / m * delta_t.

    In other words, you must divide by mass, not multiply by it.

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Hey brewbuck we already caught that up there somewhere. My last post talks about the issue.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with gravity engine
    By madmech in forum Game Programming
    Replies: 11
    Last Post: 07-03-2005, 02:41 PM
  2. Question to make you think
    By Darkness in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-05-2005, 07:29 PM
  3. another physics question (momentum)
    By Leeman_s in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 12-23-2003, 05:28 AM