Sign in to follow this  
DishSoap

Problem With 2D Acceleration

Recommended Posts

I am using Euler integration to update my position, velocity, and acceleration on a 2D plane. I move characters on screen by a point and click mechanic. I compute the vector the character travels along by taking the destinationVec - positionVec, normalize the resultant vector then mutiply that by some scalar that represents a characters acceleration value. The result is strange, on further distances traveled the character will completely miss the target and start circling around the point I clicked. When I remove the scalar multiplication it works fine with just the normalized vector. I must be rusty on my math or something? So I will post the code:

 

 

void navigateToDestination(CollidableObject &character)
{
    sf::Vector2f destinationPx = character.getDestination();
    sf::Vector2f positionPx = character.getPosition();
    sf::Vector2f acceleration = character.getAcceleration();
    sf::Vector2f direction = destinationPx - positionPx;
    vecMath::normalize(direction);
    
    ....

    if(character.getIsMoving())
    {
        acceleration.x = direction.x * character.getAccelerationValue(); <- Which is some float, 10.0f, in this instance
        acceleration.y = direction.y * character.getAccelerationValue(); <- When this acceleration value is removed the path works
    }

    ....

    character.setAcceleration(acceleration);
}

..... Later called function

void updatePosition(double dt) 
{
    setCollisionRect();
    m_position += sf::Vector2f(m_velocity.x * dt, m_velocity.y * dt);
    m_velocity += sf::Vector2f(m_acceleration.x * dt, m_acceleration.y * dt);
    updateCharacter(); // Just limits the acceleration/velocity based on character specific limits
}
 

 

 

I've limited the code to what I think might be the problem so I realize you may need to see more to catch something. Please feel free to ask me to post more. Thanks a lot!

 

Best,

    DishSoap

 

 

Share this post


Link to post
Share on other sites

If I think about this conceptually, what I see is the character's velocity continually getting larger and larger the further he travels.  Thus, as he approaches the destination, there is a good chance he will "over-shoot" the destination since his velocity may be so large he skips over it during one frame.

 

A solution would be to check if, during the next update, the character's location difference changes signs (ie, from + to -, or - to +) relative to the destination for a particular axis.  Then, the amount moved (ie, velocity) should be lowered to be the distance from the character to the destination.  Then you would not over-shoot the destination.

 

Now, I don't know what you do in UpdateCharacter that you causes the character to either Stop, or be re-route (which would cause the circling), but I assume you could do it there.

 

Good luck!

Share this post


Link to post
Share on other sites

You can try de-accelerating as you aapproach near the destination. That will make the steps small enough that it won't go right through the destination. (just a theory, haven't tested)

 

It's like a dropping a ball from rest. At first it has low speed, then reaches max speed right before and right after touching the ground. Then when it goes back up, the speed decreases.

Edited by ultramailman

Share this post


Link to post
Share on other sites

The problem is not the object going through his destination. He vears off either right or left right before arriving at his destination. I have tested the, going through destination, possibility by maxing his velocity and moving him to a nearby point. When clicking close to the character he appropriately arrives, and stops, at his point. It is when he has a fair distance to travel that he vears off before hitting his destination and enters an elliptical or circular path as he tries to correct his acceleration to arrive at the point.

 

The updateCharacter() method simply sets limits to his acceleration/velocity based on the specific unit. So the velocity and acceleration does not infinitely grow.

 

I would add an image to show you but I can't figure out how to add images on this website. laugh.png

Share this post


Link to post
Share on other sites

    m_position += sf::Vector2f(m_velocity.x * dt, m_velocity.y * dt);
    m_velocity += sf::Vector2f(m_acceleration.x * dt, m_acceleration.y * dt);

 

That's explicit euler's method, which is well known to be unstable and diverge.  Try semi-implicit euler's instead (integrate velocity first)  :

 

    m_velocity += sf::Vector2f(m_acceleration.x * dt, m_acceleration.y * dt);

    m_position += sf::Vector2f(m_velocity.x * dt, m_velocity.y * dt);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this