Tutorial 9         My mouse said move did it not?

My mouse said move did it not?

Wow, this is fun. We have a sky, we have some terrain, and we even have a plane. But the controls suck, and flies like a rock.
Guess we better do something about that then. We are going to be working exclusively with TutorialFrameListener.
First we need to add some variables to the header file. These variables need to be added below mbFirstPerson:

Real mfAfterburner;
Real mfSpeed;
Real mfPitch;
Real mfYaw;
Real mfRoll;
Real mfShipRoll;
Real mfShipPitch;
float rotX;
float rotY;


Now we are going to change the code in TutorialFrameListener::frameStarted(). First, delete the code that is associated with the checks of KC_UP, KC_DOWN, KC_LEFT and KC_RIGHT. All you should have left in the method is the following:

bool TutorialFrameListener::frameStarted(const FrameEvent& evt)
{
    Real MoveFactor = 80.0 * evt.timeSinceLastFrame;
    mInputDevice->capture();
    if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE))
        return false;
    if(mInputDevice->isKeyDown(Ogre::KC_F))
    {
        while (mInputDevice->isKeyDown(Ogre::KC_F))
        mInputDevice->capture();
        if (mbFirstPerson)
        {
            // third person
            mCameraNode->setPosition( Vector3( 0, 50, -200) );
            mbFirstPerson = false;
        }
        else
        {
            // first person
            mCameraNode->setPosition( Vector3( 0, 5, 40) );
            mbFirstPerson = true;
        };
    }
    return true;
}


Now add the following code after the check for KC_ESCAPE and before the check for KC_F:

// Increase speed
if (mInputDevice->isKeyDown(KC_EQUALS) || mInputDevice->isKeyDown(KC_ADD))
{
    mfSpeed += 10;
    if (mfSpeed > 200)
        mfSpeed = 200;
}
// Decrease speed
if (mInputDevice->isKeyDown(KC_MINUS) || mInputDevice->isKeyDown(KC_SUBTRACT))
{
    mfSpeed -= 5;
    if (mfSpeed < 0)
        mfSpeed = 0;
}
// hit our afterburners
mfAfterburner = 0;
if (mInputDevice->isKeyDown(KC_TAB) )
{
    mfAfterburner = 500;
}

This code adjusts our speed, faster, slower, or afterburners.

rotX = -mInputDevice->getMouseRelativeX() * 0.5;
rotY = mInputDevice->getMouseRelativeY() * 0.5;
// process mfYaw (rudder function):
mfYaw += rotX;
mfShipRoll -= rotX / 5;
// process mfPitch (elevator function):
mfPitch += rotY;
mfShipPitch += rotY / 5;
if (mfPitch > 45) // (higher value, turn sharper)
    mfPitch = 45;
if (mfPitch < -45)
    mfPitch = -45;
if (mfYaw > 45)
    mfYaw = 45;
if (mfYaw < -45)
    mfYaw = -45;
if (mfRoll > 45)
    mfRoll = 45;
if (mfRoll < -45)
    mfRoll = -45;
if (mfShipPitch > 35)
    mfShipPitch = 35;
if (mfShipPitch < -35)
    mfShipPitch = -35;
if (mfShipRoll > 90)
    mfShipRoll = 90;
if (mfShipRoll < -90)
    mfShipRoll = -90;

We use our mouse to get yaw and pitch values. We do a valid values check so we don’t get odd behavior.

// dampen the changes
mfPitch *= 0.9;
mfYaw *= 0.9;
mfRoll *= 0.9;
mfShipPitch *= 0.95;
mfShipRoll *= 0.95;

Let’s remove the angle changes over time. Basically the ship will re-center.

// set angles for controlNode
if ((Math::Abs( mfPitch ) > 0.01) ||
    (Math::Abs( mfYaw ) > 0.01) ||
    (Math::Abs( mfRoll ) > 0.01))
{
    mControlNode->roll(Radian (Degree (mfRoll * evt.timeSinceLastFrame )));
    mControlNode->pitch(Radian (Degree  (mfPitch * evt.timeSinceLastFrame )));
    mControlNode->yaw(Radian (Degree( mfYaw * evt.timeSinceLastFrame )));
};

Adjust the controlNodes angles, this will change our view of the terrain.

// set angles for ship node to make it looked banked in third person
if ((Math::Abs( mfShipRoll ) > 0.01) ||
    (Math::Abs( mfShipPitch ) > 0.01))
{
    Quaternion qRoll, qPitch;
    qRoll.FromAngleAxis(Radian (Degree (mfShipRoll)), Vector3::UNIT_Z);
    qPitch.FromAngleAxis(Radian (Degree (mfShipPitch)), Vector3::UNIT_X);    
    mShipNode->setOrientation( qRoll * qPitch );
};

This is cool. In third person, the ship will roll doing a turn and pitch when going up and down.

static Vector3 vec;
vec = Vector3::ZERO;
vec.z = (mfSpeed + mfAfterburner) * evt.timeSinceLastFrame;
// Translate the controlNode by the speed
Vector3 trans = mControlNode->getOrientation() * vec;
mControlNode->translate(trans);

This little bit of code will move us around the terrain a number of units depending on the speed in the
direction we are looking.

Ok, COMPILE AND RUN!!!!!!!!!

xorekis9_1.png

If everything worked as planned. You should have aircraft like controls now, and can fly your ship around.
If someone else comes up with a better way of doing aircraft controls, I would be interested in updating this
tutorial.

Congratulation, You have created a Simple Flight Simulator With Ogre !!! :-)

Tutorial 10