Results 1 to 4 of 4

Thread: OT: Physics, need help!

  1. #1
    Member Contributor
    Join Date
    Feb 2000
    Bremen, Bremen, Germany

    OT: Physics, need help!


    I have a question on how to implement physics.

    My current physics:

    I have a CMotion class that accepts motion vectors. In my message loop,
    I call the ApplyMotion(dwTimeElapsedSinceLastCall); function of this
    class. Since all my motion behavior (like speed, acceleration) are defined
    for one second, my class has to look how many time has elapsed and then
    scale the things to this time. Things like gravity and gravity acceleration
    are also applied from this class.
    This works very well, but I have problems to convert keyboard & mouse input
    to vectors for my class. If I pass a forward vector to my class every time
    my HandleKeyboard() function realizes the forward key is pressed, my acceleration
    would depend on how often this function could be called. Bad. So I have to
    scale this too. I call something like AddForwardVector(dwTimeElapsedSinceLastCall);
    and the forward vector is so scaled that the whole acceleration is applied when
    I hold my forward key a full second down, regardless of how often HandleKeyboard()
    is called.

    My problem:

    This method requires for all forces to be applied over the time. I want to let the player
    jump, but to jump you shouldn't have to hold the mouse button down like walking. But when
    I call my Jump(); it adds a vector to my CMotion class which will be smoothed out quickly
    by the other ones.

    Here is my source (sorry):
    ================================================== ============================

    // Init motion behavior with standard values. Every values is meant
    // to be applied in 1000ms

    m_SlowDown = 7.5f;
    m_MidAirSlowDown = 0.1f;
    m_GravityAcceleration = 2.5;
    m_Gravity[x] = 0.0f;
    m_Gravity[y] = -0.15f;
    m_Gravity[z] = 0.0f;

    // Init other member variables

    m_MidAir = FALSE;
    m_SmallestForce = 0.01f;
    m_AccelerationTime = 100;
    m_MidAirAccelerationTime = 500;
    m_JumpForce[x] = 0.0f;
    m_JumpForce[y] = 1.0f;
    m_JumpForce[z] = 0.0f;
    m_CurrentGravity[x] = 0.0f;
    m_CurrentGravity[y] = 0.0f;
    m_CurrentGravity[z] = 0.0f;



    void CMotion::ApplyMotionPhysics(DWORD dwTimeElapsed)
    // Calculate the movement that would happen in dwTimeElapsed ms

    // Copy the current motion vector to cFinalForce
    CForce cFinalForce = m_Force;

    // Is camera in the air ?

    // Apply gravity to the final movement vector
    if (m_MidAir)
    // Camera is diving, apply gravity acelleration
    m_CurrentGravity[x] += ScaleToElapsedTime(m_CurrentGravity[x] * m_GravityAcceleration, dwTimeElapsed);
    m_CurrentGravity[y] += ScaleToElapsedTime(m_CurrentGravity[y] * m_GravityAcceleration, dwTimeElapsed);
    m_CurrentGravity[z] += ScaleToElapsedTime(m_CurrentGravity[z] * m_GravityAcceleration, dwTimeElapsed);
    // Apply gravity
    cFinalForce += m_CurrentGravity;
    // Camera is on the ground, set current gravity to default gravity
    m_CurrentGravity = m_Gravity;

    // Scale the final motion vector relative to dwTimeElapsed
    cFinalForce[x] = ScaleToElapsedTime(cFinalForce[x], dwTimeElapsed);
    cFinalForce[y] = ScaleToElapsedTime(cFinalForce[y], dwTimeElapsed);
    cFinalForce[z] = ScaleToElapsedTime(cFinalForce[z], dwTimeElapsed);

    // Pass the position after the motion to the CCamera class
    SetXPos(GetXPos() + cFinalForce[x]);
    SetYPos(GetYPos() + cFinalForce[y]);
    SetZPos(GetZPos() + cFinalForce[z]);

    // Lift the camera up to the terrain if he has descended below it
    float fHeight = GetSurfaceHeight();
    if (GetYPos() < fHeight)
    // Lift camera up
    // No acceleration upwards
    m_Force[y] = 0.0f;

    // Slow the motion down

    // Use m_MidAirSlowDown when camera is in the air
    if (m_MidAir)
    // Reduce force as specified in m_MidAirSlowDown. Scale to the elapsed time
    m_Force.SlowDown(ScaleToElapsedTime(m_MidAirSlowDo wn, dwTimeElapsed));
    // Reduce force as specified in m_SlowDown. Scale to the elapsed time
    m_Force.SlowDown(ScaleToElapsedTime(m_SlowDown, dwTimeElapsed));

    // Set it to zero if it is to small
    if (fabs(m_Force[x]) + fabs(m_Force[y]) +
    fabs(m_Force[z]) < m_SmallestForce)


    void CMotion::SetCustomMotion(float fForwardSpeed, float fBackwardSpeed, float fLeftSpeed, float fRightSpeed,
    float fUpSpeed, float fDownSpeed, DWORD dwTimeElapsed)
    // Add the given forces to the current force. Do scale the given forces relative to the
    // elapsed time. Do not exceed maximum speed.

    // Holds the new motion
    CForce cAddForce;

    // Calculate the given forces
    if (fForwardSpeed > 0.0f)
    CForce cForward;
    cForward[x] = -(sinf(GetYRotation() * PI_OVER_180) * fForwardSpeed);
    cForward[y] = 0.0f;
    cForward[z] = -(cosf(GetYRotation() * PI_OVER_180) * fForwardSpeed);
    cAddForce += cForward;
    if (fBackwardSpeed > 0.0f)
    CForce cBackward;
    cBackward[x] = sinf(GetYRotation() * PI_OVER_180) * fBackwardSpeed;
    cBackward[y] = 0.0f;
    cBackward[z] = cosf(GetYRotation() * PI_OVER_180) * fBackwardSpeed;
    cAddForce += cBackward;
    if (fLeftSpeed > 0.0f)
    CForce cLeft;
    cLeft[x] = sinf((GetYRotation() - 90.0f) * PI_OVER_180) * fLeftSpeed;
    cLeft[y] = 0.0f;
    cLeft[z] = cosf((GetYRotation() - 90.0f) * PI_OVER_180) * fLeftSpeed;
    cAddForce += cLeft;
    if (fRightSpeed > 0.0f)
    CForce cRight;
    cRight[x] = sinf((GetYRotation() + 90.0f) * PI_OVER_180) * fRightSpeed;
    cRight[y] = 0.0f;
    cRight[z] = cosf((GetYRotation() + 90.0f) * PI_OVER_180) * fRightSpeed;
    cAddForce += cRight;
    if (fUpSpeed > 0.0f)
    CForce cUp;
    cUp[x] = 0.0f;
    cUp[y] = fUpSpeed;
    cUp[z] = 0.0f;
    cAddForce += cUp;
    if (fDownSpeed > 0.0f)
    CForce cDown;
    cDown[x] = 0.0f;
    cDown[y] = -fDownSpeed;
    cDown[z] = 0.0f;
    cAddForce += cDown;

    // Is camera in the air ?

    // Scale length of additional force vector relative to the acceleration time
    if (m_MidAir)
    cAddForce.SetVectorLength((GetSpeed() / m_MidAirAccelerationTime) * dwTimeElapsed);
    cAddForce.SetVectorLength((GetSpeed() / m_AccelerationTime) * dwTimeElapsed);

    // Add the additional force vector to the current force
    m_Force += cAddForce;

    // Do not exceed maximum speed

    void CMotion::SetDefaultMotion(bool bForward, bool bBackward, bool bLeft, bool bRight,
    bool bUp, bool bDown, DWORD dwTimeElapsed)
    // Add the enabled motion vectors with default accelerations to the array

    // Convert parameters for SetCustomMotion() and pass them
    SetCustomMotion(bForward * GetSpeed(), bBackward * GetSpeed(),
    bLeft * GetSpeed(), bRight * GetSpeed(),
    bUp * GetSpeed(), bDown * GetSpeed(), dwTimeElapsed);

    void CMotion::Jump()
    // Add jump acceleration to there current force if player
    // is on the ground


    if (!m_MidAir)
    m_Force += m_JumpForce;

    void CMotion::CheckMidAir()
    // Checks if the camera is in the air

    // Use offset to avoid calculation accurancy problems
    if (GetYPos() > GetSurfaceHeight() + 0.0000001f)
    m_MidAir = TRUE;
    m_MidAir = FALSE;
    ================================================== ============================

    Any ideas ? I think my physics code is good, but my way to keep the motion vector
    in sync with the mouse + keyboard input is bad...

    Any ideas would be great !!!

    Hope my English was good enough to make myself clear

    (Sorry again for being off-topic. If you don't want to reply on the board, please
    mail me)


  2. #2
    Junior Member Newbie
    Join Date
    Feb 2000

    Re: OT: Physics, need help!

    calculate all your physics with respect to an independant time variable, perhaps based on the system clock, so acceleration would be based on time, not the number of times the function is called.

  3. #3
    Member Contributor
    Join Date
    Feb 2000

    Re: OT: Physics, need help!

    I think that you should treat input as a set of states, related to the controlling devices. I mean, in each game loop, you read the input values and update your internal states. You'd then use stored information during the physics calculations, based on a delta time. I.e. keys can be pressed or depressed, not too much difficult to handle. For actions, like jumping, you should use a FSM, and switch states on appropriate events from the input state. This should be a fine solution, it lets you to implement acceleration in the FSM state handler.
    Combine this, with a function modulating acceleration over time, and you should get smooth reactions.
    Paolo M.

  4. #4
    Member Contributor
    Join Date
    Feb 2000
    Bremen, Bremen, Germany

    Re: OT: Physics, need help!

    I think you don't understand my problem. If you look at my SetCustomMotion function, which is called from my keyboard handler, you'll notice that it takes a dwElapsedTime parameter, so that the acceleration don't depends on how often the engine could check the keyboard. But I have problems to keep acceleration with continius keydown's ,like moving forward, in sync with single keystrokes like jumping....


Similar Threads

  1. Physics
    By vivek vyas in forum OpenGL: General
    Replies: 2
    Last Post: 07-06-2009, 03:01 AM
  2. Replies: 1
    Last Post: 11-26-2007, 05:28 AM
  3. physics on gpu
    By Nyad in forum OpenGL: GLSL
    Replies: 12
    Last Post: 11-01-2007, 08:04 PM
  4. Physics
    By Jochen in forum OpenGL: General
    Replies: 53
    Last Post: 07-05-2006, 08:04 AM
  5. Physics
    By Schlogenburg in forum OpenGL: Basic Coding
    Replies: 1
    Last Post: 12-19-2000, 02:35 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
Proudly hosted by Digital Ocean