简体   繁体   中英

C++ Asteroids Clone - spaceship movement issues

I am having a hard time understanding how to move my spaceship like in the asteroids clone. I can move it along the world y-axis but not move it forward within its own relative y-axis when I rotate the spaceship. I have commented the code where the if statement is for the spaceship movement. It's near the bottom in the update() method. Thanks for any advice.

#include "Game.h"

Game::Game() 
    : mUColorProgram(0)
    , mVColorProgram(0)
    , mAsteroid(NULL)
    , mSpaceship(NULL)
    , mManualRotation(0.0f)
    , mManualTranslation(0.0f, 0.0f, 0.0f)
    , mSpinnerAngle(0.0f)
    , mSpinnerAngularVelocity(glm::radians(90.0f))
    , mMinX(-1.0f)
    , mMinY(-1.0f)
    , mMaxX(1.0f)
    , mMaxY(1.0f)
    , mBouncerPosition(0.0f, 0.0f, 0.0f)
    , mBouncerVelocity(0.0f, 0.0f, 0.0f)
    , mMinScale(0.5f)
    , mMaxScale(5.0f)
    , mCurrScale(mMinScale)
    , mScalingSpeed(2.0f)
    , mBlendColor1(1.0f, 1.0f, 0.0f, 1.0f)
    , mBlendColor2(1.0f, 0.0f, 0.0f, 1.0f)
    , mAlpha(1.0f)
    , mBlendSpeed(-0.5f)
    , mBlendedColor(mAlpha * mBlendColor1 + (1 - mAlpha) * mBlendColor2)
{
    glsh::InitRandom();  // initialize random number generator

    mBouncerPosition.x = glsh::Random(mMinX, mMaxX);
    mBouncerPosition.y = glsh::Random(mMinY, mMaxY);

    float angle = glm::radians(glsh::Random(-180.0f, 180.0f));
    float speed = 0.75f;
    mBouncerVelocity.x = speed * std::cos(angle);
    mBouncerVelocity.y = speed * std::sin(angle);
}

Game::~Game()
{
}

void Game::initialize(int w, int h)
{
    // set clearing (background) color
    glClearColor(0.25f, 0.25f, 0.25f, 1.0f);

    // import some symbols from glsh namespace
    using glsh::VertexPositionColor;

    // define triangle mesh data (positions only)
    VertexPositionColor asteroid[] = {
        VertexPositionColor(0.0f, 0.40, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(0.0f, 0.4f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(-0.3f, 0.3f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(-0.4f, 0.0f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(-0.1f, -0.3f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(0.1f, -0.4f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(0.3f, -0.2f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(0.4f, 0.2f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
        VertexPositionColor(0.1f, 0.5f, 0.0f, 0.9f, 0.9f, 0.9f, 1.0f),
    };

    // define quad mesh data (positions and colors)
    VertexPositionColor spaceship[] = {
        VertexPositionColor(0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(-0.8f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(0.8f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(0.0f, 0.9f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(-0.5f, -0.9f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(0.0f, -0.5f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(0.0f, 0.9f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(0.0f, -0.5f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),
        VertexPositionColor(0.5f, -0.9f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f),

    };

    // create meshes
    mAsteroid = glsh::CreateMesh(GL_TRIANGLE_FAN, asteroid, 9);
    mSpaceship = glsh::CreateMesh(GL_TRIANGLES, spaceship, 9);

    // build shader programs
    mUColorProgram = glsh::BuildShaderProgram("ucolor-vs.glsl", "ucolor-fs.glsl");
    mVColorProgram = glsh::BuildShaderProgram("vcolor-vs.glsl", "vcolor-fs.glsl");

}

void Game::shutdown()
{
    delete mAsteroid;
    delete mSpaceship;

    glUseProgram(0);
    glDeleteProgram(mUColorProgram);
    glDeleteProgram(mVColorProgram);
}

void Game::resize(int w, int h)
{
    glViewport(0, 0, w, h);
}

void Game::draw()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // activate the per-vertex color shader program
    glUseProgram(mVColorProgram);

    T = glsh::CreateTranslation(mBouncerPosition);
    R = glsh::CreateRotationZ(mSpinnerAngle);
    S = glsh::CreateScale(0.1f, 0.1f, 0.1f);
    glsh::SetShaderUniform("u_Transform", T * R * S);
    mAsteroid->draw();

    T = glsh::CreateTranslation(mManualTranslation);
    R = glsh::CreateRotationZ(mManualRotation);
    S = glsh::CreateScale(0.1f, 0.1f, 0.1f);
    glsh::SetShaderUniform("u_Transform", T * R * S);
    mSpaceship->draw();
}

bool Game::update(float dt)
{
    const glsh::Keyboard* kb = getKeyboard();

    if (kb->keyPressed(glsh::KC_ESCAPE)) {
        return false; // exit
    }

    // Rotation of spaceship
    if (kb->isKeyDown(glsh::KC_LEFT)) {
        mManualRotation += 3.0f * dt;
    }
    else if (kb->isKeyDown(glsh::KC_RIGHT)) {
        mManualRotation -= 3.0f * dt;
    }

    // SPACESHIP MOVEMENT
    // Translation of spaceship
    if (kb->isKeyDown(glsh::KC_UP)) {
        mManualTranslation.y += 0.5f * dt;
    }
    else if (kb->isKeyDown(glsh::KC_DOWN)) {
        mManualTranslation.y -= 0.5f * dt;
    }


    // update spinner angle
    mSpinnerAngle += dt * mSpinnerAngularVelocity;

    // keep the angle in standard range
    if (mSpinnerAngle > 180.0f) {
        mSpinnerAngle -= 360.0f;
    } else if (mSpinnerAngle < -180.0f) {
        mSpinnerAngle += 360.0f;
    }


    // update bouncer position
    mBouncerPosition += dt * mBouncerVelocity;

    // bounce off of the horizontal boundaries of the screen
    if ((mBouncerVelocity.x > 0 && mBouncerPosition.x > mMaxX) ||
        (mBouncerVelocity.x < 0 && mBouncerPosition.x < mMinX))
    {
        mBouncerVelocity.x *= -1;
    }

    // bounce off of the vertical boundaries of the screen
    if ((mBouncerVelocity.y > 0 && mBouncerPosition.y > mMaxY) ||
        (mBouncerVelocity.y < 0 && mBouncerPosition.y < mMinY))
    {
        mBouncerVelocity.y *= -1;
    }

    return true;
}

You seem to be missing a sine and cosine function in the movement code. What you are currently doing with mManualTranslation is just update the Y-coordinate, while I suppose you want the spaceship to move on the horizontal axis as well. To accomplish this, you have to use a sine and cosine.

if (kb->isKeyDown(glsh::KC_UP)) {
    mManualTranslation.x += std::cos(mManualRotation) * 0.5f * dt;
    mManualTranslation.y += std::sin(mManualRotation) * 0.5f * dt;
}
else if (kb->isKeyDown(glsh::KC_DOWN)) {
    mManualTranslation.x -= std::cos(mManualRotation) * 0.5f * dt;
    mManualTranslation.y -= std::sin(mManualRotation) * 0.5f * dt;
}

Also keep in mind to be careful when using degrees for angles (as you appear to be doing) since the standard math functions assume the argument to be in radians.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM