0
votes

In my game the user controls an airplane (seen from the top), flying over the earth (a Sphere object). The airplane can rotate (steer) left or right (by pressing the LEFT or RIGHT arrow keys) and it can accelerate by pressing the UP arrow key. So the airplane always has a direction (rotation) and a certain speed (velocity) based on user input, stored in vx & vy variables.

In the render loop the vx & vy variables are used to rotate the globe. So the airplane does not actually move, it is the globe below the airplane that rotates to give the impression of the airplane flying over the earth.

This is all wonderful, until the player "reaches" the other side of the globe with his airplane. Now when the user flies "to the right" of the screen, the earth also rotates to the right, which makes it look that the airplane is flying backwards. The issue comes from trying to fit in some old 2D code of a previous airplane game of mine into this 3D game.

I would like to know how to solve this issue with quaternions. I am certain that I need those, but I just don't understand them fully. I figure that my vx and vy variables could still be useful for this, as they could make some kind of "new location" vector. From what I read is that I should normalize vectors, get an axis and an angle, but I am not sure of what and how to get these. Any help would be greatly appreciated!


Below is the code that rotates the earth when the user flies in a certain x/y direction plus an image to get a better picture of the game situation.

// AIRPLANE VARS
var friction = 0.85;
var vr = 7.5; // Rotate-velocity
var thrust = 0.5;
var max_speed = 20;
var vx = 0; // X-velocity
var vy = 0; // Y-velocity

// RENDER LOOP
function render() {

    // check states

    if (rotate_left) {
        player.rotation.y = player.rotation.y + (vr * (Math.PI / 180));
    } else if (rotate_right) {
        player.rotation.y = player.rotation.y - (vr * (Math.PI / 180));
    }

    if(throttle){
        //var radians = ((player.rotation.y * Math.PI) / 180);
        var radians = player.rotation.y;
        var ax = (Math.cos(radians) * thrust);
        var ay = (Math.sin(radians) * thrust);

        vx = vx + ax;
        vy = vy + ay;
    } else {
        //ship.gotoAndStop(1);
        vx = vx * friction;
        vy = vy * friction;
    }

    // rotate the globe in the opposite direction of the airplane movement
    globe.rotation.x = globe.rotation.x - (-vx/100);
    globe.rotation.y = globe.rotation.y - (vy/100);
}

simple explanation of the game

1

1 Answers

1
votes

I am not familiar with your implementation framework, which appears from your tags to be three.js. It is also a bit difficult to see how your 'turn' controls affect the player, because you did not mention how the axes of the plane is defined. I may not be much help but I can give you some starting tips.

Firstly familiarise yourself with the structure of a quaternion and the implementation of it in three.js. In many texts they appear as q = [w, x, y, z], however it seems in three.js they are defined as q = [x, y, z, w]. Don't worry too much about what those numbers are as they are very counter-intuitive to read.

There are a few ways to rotate the quaternion with respect to your velocity.

I think this is your best shot: rotate the quaternion by using the derivative equation given here, by calculating the angular velocity of the plane around the earth (and thus the earth around the plane). This is given by the 3D particle equation here. You can add the time-scaled derivative (dt*dqdt) to the quaternion q, then renormalise it in order to animate the rotation.

Another way is to pick a quaternion rotation that you want to end at, and use the slerp operation (built in to three.js).

If you give me some more details about how your sphere, plane and global frames are defined, I may be able to help more.