zeboidlund
zeboidlund

Reputation: 10157

Algorithm for Calculating Directional Movement

I'm trying to write a basic Asteroids game in C++ using SFML. While I'm able to move my triangle (the player) around rather easily, the way in which it moves I'm not quite satisfied with.

Currently, the movement isn't relative to the direction it's facing. For example, if I press "w" to move forward, the triangle will simply move up the screen regardless of its direction.

What I'd like for the triangle to do is move forward when the "w" key is pressed, but make the actual direction its moving (in respect to the dimensions of the screen) relative to the actual direction its facing.

So, if the forward tip of the triangle is facing right, when "W" is pressed, it will move right. If "S" is pressed in this case, it will move left. "A" would make it move up, and of course "D" would make it move down.

My current code does not accomplish this one bit - I think there's a really hacky solution to this, but I'd rather approach this from a more mathematical and elegant perspective if possible.

So, what would be the best way to accomplish this?

I have three methods of relevance: one for handling keyboard input, the other for handling mouse movement, and an update method.


Code

void Game::OnKeyPress( void )
{
    int count = 0;

    const float playerCenterMag = Magnitude( mPlayer.GetShape().GetCenter() );
    //Shoddy attempt resulting in absolutely nothing of note
    const float moveRateX = ( cosf( mMouseAoR ) * playerCenterMag ) + mPlayer.MoveSpeed;
    const float moveRateY = ( sinf( mMouseAoR ) * playerCenterMag ) + mPlayer.MoveSpeed;

    if ( mInput.IsKeyDown( sf::Key::W ) ) // Up
    {
        mPlayer.Position.y -= moveRateY;
        ++count;
    }

    if ( mInput.IsKeyDown( sf::Key::S ) ) // Down
    {
        mPlayer.Position.y += moveRateY;
        ++count;
    }

    if ( mInput.IsKeyDown( sf::Key::A ) ) // Left
    {
        mPlayer.Position.x -= moveRateX;
        ++count;
    }

    if ( mInput.IsKeyDown( sf::Key::D ) ) // Right
    {
        mPlayer.Position.x += moveRateX;
        ++count;
    }

    std::cout << "Key Press Rate => " << count << " seconds" << std::endl;
}

void Game::OnMouseEvent( void )
{
    mPlayer.GetShape().Rotate( mMouseAoR + 5 );
}

void Game::Update( void )
{
    const int x = mInput.GetMouseX();
    const int y = mInput.GetMouseY();

    mMouseAoR = ( y == 0 ) ? 0
                           : tanf( x / y );

    PrintInfo();
}

Upvotes: 2

Views: 1178

Answers (1)

LSerni
LSerni

Reputation: 57453

There are two versions of this game. If you want, say, 'W' to "thrust" forward, then you need to add moveRate at each cycle and use W to change the rate.

Here apparently you move only if a button is pressed, so you need to update always both X and Y:

if ( mInput.IsKeyDown( sf::Key::W ) ) // Up
{
    mPlayer.Position.x += moveRateX;
    mPlayer.Position.y += moveRateY;
    ++count;
}

The moveRate changes according to orientation. When moving laterally, you would do

    mPlayer.Position.x += moveRateY;
    mPlayer.Position.y += moveRateX;

when moving left (or right), and -= in the other direction.

Upvotes: 1

Related Questions