Search code examples
c++game-physicssfml

SFML Game Development Book by Haller 2D Diagonal Movement


The SFML Game Development book in Ch. 4 gives guidance that when you increase velocity by both directions (e.g. right and top), then the movement will be faster than in one direction.

From research, I understand that the observed behavior is that you will reach the diagonal distance in the same period as if you were moving left or right or top or down. This is wrong as the diagonal distance is longer.

The book corrects this problem by dividing by sqrt of 2:

sf::Vector2f velocity = mPlayerAircraft->getVelocity();

// If moving diagonally, reduce velocity (to have always same velocity)
if (velocity.x != 0.f && velocity.y != 0.f)
    mPlayerAircraft->setVelocity(velocity / std::sqrt(2.f));

From additional research, I found that the solution can be achieved by multiplying the velocity by the normalized vector of the velocity.

velocity = mPlayerAircraft->getVelocity();

if (velocity.x != 0.f && velocity.y != 0.f) {
    float velocityxsq = velocity.x * velocity.x;
    float velocityysq = velocity.y * velocity.y;
    float magnitude =  std::sqrt(velocityxsq + velocityysq);
    sf::Vector2f normalizedVector = velocity / magnitude;
    velocity.x = velocity.x * std::abs(normalizedVector.x);
    velocity.y = velocity.y * std::abs(normalizedVector.y);
    mPlayerAircraft->setVelocity(velocity);
}

The behavior seems to be correct by both implementations but the normalization values are not always 1/sqrt(2). The only time the calculations are the same are when the game starts and I do a diagonal movement initially. If I move any direction and then make a diagonal movement, the values differ.

Did I do the normalization incorrect? Why does the book statically use sqrt(2)?


Solution

  • While I actually own the book, I haven't had time to read it, so the following is just a logical assumption.

    The book simply assumes the velocity vector's directional components are always either -1, 0, or 1. That's about it.

    You're indeed correct that the proper solution would be to normalize the vector by dividing both components using the vector's length (or magnitude).

    In case of the book this is skipped, so for simplification it's possible to remove the whole calculation by basically using a compile time constant, sqrt(2.f).