Search code examples
c++openglglutglew

Smooth movement in GLUT


I made a very simple engine that basically draws a character and then you can move it around the screen.

But I did the movement in quite a horrible way, I mean it is based on discrete values like this:

void Scene::movePlayer(int dir) {

    switch (dir){
    case 1:     yy = yy + 0.05;
            break;

    case 2:     xx = xx - 0.05;
            break;

    case 3:
            yy = yy - 0.05;
            break;

    case 4:
            xx = xx + 0.05;
            break;

    default:
            break;
}

it works and moves the character, but I don't really like it since it's very jumpy and it isn't smooth.

I'd love to have more smooth movement, just like in mario or something like that.

Could you tell me how to achieve that?


Solution

  • What you are after is acceleration (and maybe deceleration as well – let me think about that while answering).

    The steps to follow are these:

    1. your Mario is standing still at position x. Set speed to 0.0 and acceleration to a small value, such as 0.01.
    2. user presses the Left or Right key. Add acceleration to speed and update his position. Make sure the acceleration has the correct sign – negative for moving left, positive for moving right.
    3. as long as the user does not release the key, keep adding acceleration to speed – but stop as soon as speed reaches a suitable value (your 0.05, for example).
    4. If you want Mario to slide to a halt when the key is released, set acceleration to a negative value such as -0.015 (usually more than when accelerating), and use it to decrease the speed until it is less or equal to 0.0. When it's less, make sure to reset it to exactly 0.0! Floating point operations are inaccurate, and a very small remaining value may make your Mario keep moving ever so slightly.

    This procedure is strongly tied to the actual timing of your entire game loop. You need to add or subtract the acceleration only once per game frame.
    You can make it work with variable update intervals (that is, adjust the speed depending on the time between two successive speed updates) but it's easier to start with a fixed frame rate, such as 25 or 50 frames per second. That way the acceleration can be constant; the right value can be estimated by trial runs. I imagine you ended up with your xx = xx + 0.05; like that through the same process.

    The same procedure can be used for "jumping" and "falling". To jump, set the initial speed to a high value and decrease it in every game loop. Don't worry if it falls below 0, that is necessary to have what went up go down again. To fall, set the speed to 0.0 and increase it using acceleration again.

    This will work fine if your Mario moves along an infinite straight line. You then only have to keep an eye on his yy position – it may not extend below the 'floor'. If you are going to add different vertical levels to move on, you can add a collision check for both moving left and right (make it a dead stop instead of sliding to a halt) and for moving up and down (again, a dead stop if he jumps up and knocks his head on something, but then followed by 'falling', and an increasing speed if he walks off of something, until he hits a block at the bottom).