Search code examples
algorithmgame-physicspseudocode

Limit top speed of an object tracked by x and y when moving in a rotation-based direction


Let's imagine I have some character that can rotate in 360 degrees, and I am tracking its position as x and y.

I am using sin and cos to determine its movement:

x += speed * cos(rotation)
y += speed * sin(rotation)

This works fine, but I figure I want an acceleration based system instead. So rather than increasing speed, I increase acceleration which then increases speed:

x_velocity += speed * cos(rotation)
y_velocity += speed * sin(rotation)
x += x_velocity
y += y_velocity

However, I don't want this character to be able to accelerate indefinitely and therefore I want to limit its top speed. Now, I could do this:

if x_velocity > maxspeed then x_velocity = maxspeed
if y_velocity > maxspeed then y_velocity = maxspeed

but this is imperfect, as it means you can travel 44% faster if you move at a perfect diagonal than if you travel in a cardinal direction.

So I use the pythagorean theorem, but I immediately run into a problem.

if sqrt(x_velocity^2 + y_velocity^2) > maxspeed then ???

Is there a solution? I cannot simply define it equal to maxspeed like before, but I also cannot completely allocate all the velocity to one axis, since that would change the direction. How do I determine the velocity to limit it at?


Solution

  • Just use overall velocity

     velocity = Min(max_velocity, velocity + speed) //really acceleration instead of speed
     x_velocity  = velocity * cos(rotation)
     y_velocity  = velocity * sin(rotation)
     x += x_velocity
     y += y_velocity
    

    If you have to maintain x_velocity and y_velocity (by some strange reason), then you can limit overall velocity through it's components with direction preserving:

    ... update x_velocity, y_velocity
    vel = sqrt(x_velocity^2 + y_velocity^2) 
    if vel > max_velocity then
        x_velocity = x_velocity * max_velocity / vel
        y_velocity = y_velocity * max_velocity / vel