Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling strafing / side stepping in a 3D game

Tags:

game-physics

I am quite new to game development and have successfully modelled a 3D terrain, and have a camera that is able to freely move around in the game world, I have however run into a snag that I am unable to figure out.

Currently, to move forward / backwards I have methods as follows:

void Player::moveForward(const float speed)
{
    Vector3 pos = getPosition();

    float cosYaw = cosf(degreesToRadians(m_yaw));
    float sinYaw = sinf(degreesToRadians(m_yaw));
    pos.x += float(cosYaw)*speed;
    pos.z += float(sinYaw)*speed;

    setPosition(pos);
}

Where Vector3 is a simple X, Y, Z struct, and degrees to radians is:

inline float degreesToRadians(const float degrees) {
    const float PIOver180 = 3.14159f / 180.0f;
    return degrees * PIOver180;
}

To handle moving forward I simply place a positive float into the argument, and to move backwards a negative float.

This allows me to of course move forward and backwards - I can also move upwards by changing the pos.y of the position however I can't figure out how to side step / strafe left and right.

Flipping the x and z results in me being able to side step provided the yaw is 360/0, 270, 180 or 90 however anywhere between them angles causes the camera to forward-sidestep/backward-sidestep or move forward/backwards.

Anyway, this had been bothering me so I attempted to find a solution on paper - this worked:

inline float degreesToStrafe(const float degrees)
{
    const float PIOver90 = 3.14159f / 90.0f;
    return degrees * PIOver90;
}

However, in game this is exactly the same as swapping the x and z results.

Any help would be greatly appreciated; I struggled to find anything on the web regarding this however it's possible I was just searching incorrectly!

like image 224
chrisburke.io Avatar asked Dec 15 '11 15:12

chrisburke.io


1 Answers

I don't think you can just swap the x and z results. Consider the case where cosYaw == sinYaw: flipping them will result in the same direction as unflipped, which is obviously unwanted behavior because you're trying to move the vector by 90 degrees, not go the same direction.

Instead, you want to do the same thing that you are doing for the MoveForward, just rotate your yaw by 90 degrees first. You are basically breaking down the known resultant velocity into its x and z components, and you can do this because you know the angle. If you consider the difference in angle between moving forward and strafing, it's 90 degrees, so just subtract or add 90 degrees to your yaw and then use the same math.

void Player::strafe(const float speed)
{
    Vector3 pos = getPosition();

    float cosYaw = cosf(degreesToRadians(m_yaw - 90.f));
    float sinYaw = sinf(degreesToRadians(m_yaw - 90.f));
    pos.x += float(cosYaw)*speed;
    pos.z += float(sinYaw)*speed;

    setPosition(pos);
}
like image 68
Andrew Rasmussen Avatar answered Oct 16 '22 16:10

Andrew Rasmussen