Search code examples
javalwjgltrigonometryangle

Moving an entity at an angle?


i've literally been searching half an hour for this question and i did'nt find what i've been looking for. This is my first lwjgl program. Most of the stuff here is temporary, im just getting used to LWGJL so i can eventually turn this into a game. I'm just getting some basic functions up and running.

So basically, i want my entity to move in the direction of it's angle.

This is my movement code:

public static void moveAtAngle(Entity entity) {
    float x = entity.getX();
    float y = entity.getY();
    float xv = entity.getXV();
    float yv = entity.getYV();
    float angle = entity.getAngle();

    x += xv * Math.cos(Math.toRadians(angle - 90));
    y += yv * Math.cos(Math.toRadians(angle - 90));

    entity.setXAndY(x, y);
}

public static void move(Entity entity, float vel, float anglevel) {
    entity.setXV(entity.getXV() * vel);
    entity.setX(entity.getX() + entity.getXV());
    entity.setYV(entity.getYV() * vel);
    entity.setY(entity.getY() + entity.getYV());
    entity.setAV(entity.getAV() * anglevel);
    entity.setAngle(entity.getAngle() + entity.getAV());
}

This is my main update code:

public static void update() {
    Graphics.move(Entity.sprite, 0.95F, 0.99F);

    Graphics.moveAtAngle(Entity.sprite);

    if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
        Entity.sprite.setAV(Entity.sprite.getAV() + 0.1F);
    }
    if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
        Entity.sprite.setAV(Entity.sprite.getAV() - 0.1F);
    }
    if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
        Entity.sprite.setYV(Entity.sprite.getYV() - 1);
    }
    if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
        Entity.sprite.setYV(Entity.sprite.getYV() + 1);
    }
}

public static void updateGraphics() {
    glMatrixMode(GL_PROJECTION);
    glOrtho(0, SLDisplay.getWidth(), SLDisplay.getHeight(), 0, 1, -1);
    glMatrixMode(GL_MODELVIEW);

    while (!Display.isCloseRequested()) {
        update();

        glPushMatrix();
            glClear(GL_COLOR_BUFFER_BIT);
            glLoadIdentity();
            Graphics.rotate(Entity.sprite);
            Graphics.drawTriangle(Entity.sprite.getX(), Entity.sprite.getY(), 150F, (byte) 150,  (byte) 200, (byte) 255, (byte) 0);
        glPopMatrix();

        Display.update();
        Display.sync(60);
    }

    destroy(false);
}

And my rotate code just for good measures:

public static void rotate(Entity entity) {
    glTranslatef(entity.getX(), entity.getY(), 0);
    glRotatef(-entity.getAngle(), 0, 0, 1);
    glTranslatef(-entity.getX(), -entity.getY(), 0);

    if (entity.getAngle() <= 0){
        entity.setAngle(entity.getAngle() + 360);
    } else if (entity.getAngle() >= 360) {
        entity.setAngle(entity.getAngle() - 360);
    }
}

Please ask if you want to see anything else.

Thanks!


Solution

  • There are two problems:

    Firstly, Your problem is that you are technically using two directions at once to move your object. 1. You have an angle 2. You have vx and vy which is technically a vector with a direction.

    Here are two methods using either of them :

    Assuming 0 degrees is positive x

    Keep angle

    If you want to keep your angle variable you would need to have a general speed variable and then do this for each time you update the x and y:

    float radAngle = Math.toRadians(angle);
    x += speed * cos(radAngle); 
    y += speed * sin(radAngle);
    

    Keep velocities

    This method required only using the trig functions each time the velocities change but it also uses the expensive sqrt function with the trigonometry functions. You would need to use vx and vy only. For updates you only would need to do this:

    x += vx;
    y += vy;
    

    And then for setting vx and vy:

    public void setAngle(float angle){
         angle = Math.toRadians(angle);
         float speed = Math.sqrt(vx * vx + vy * vy); //magnitude of movement vector
         vx = speed * Math.cos(angle);
         vy = speed * Math.sin(angle);
    }
    

    The second problem is this code:

     glTranslatef(entity.getX(), entity.getY(), 0); 
     glRotatef(-entity.getAngle(), 0, 0, 1);    
     glTranslatef(-entity.getX(), -entity.getY(), 0); 
    

    You will only need to translate it by its x and y why values once as it's x and y values are calculated according to the angle already. (You also seem to be moving the object back to it's original position with the negative translate)

    And most java and lwjgl methods will require radians not degrees, so you would need to put

    Math.toRadians(angle);
    

    Into glRotate (why a negative before your angle I do not know though)