Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm making a menu for my game with SDL, when you click on an option a sub menu slides down and is shown, just sliding down is really boring, so I want it to accelerate(like if gravity was pulling it) and bounce when it reaches the end. I don't care if it is physically accurate so I don't need exact 9.8m/s^2 acceleration, the acceleration I'm using is 1pixel/milisecond^2, now I don't really care about the final speed but I do need that it is always the same and that the animation takes always the same time, but my code doesn't, I perform a check on the speed at the end of the animation but It is not always the same, it is close though but just not the same, how can I make this last always exactly the same time and finish with the same speed?

float start_time = SDL_GetTicks();
float previous_time = start_time;
int speed = 500;    //500px/ms^2
int position = -569;

while(!return_button_clicked)
{
    float current_time = SDL_GetTicks();
    float elapsed_time = current_time - previous_time;
    previous_time = current_time;

    if(position < 0)   //if position the animation hasn't finished yet
    {
        speed += 1 * elapsed_time;     //I know the 1 is unnecessary
        position += speed * elapsed_time / 1000;
        if(position > 0)
        {
            position = 0;
        }
        RenderTheMenuInItsCurrentPosition();
        if(position == 0)    //If it is at the bottom
        {
            while(speed > 0) //bounce back
            {
                current_time = SDL_GetTicks();
                elapsed_time = current_time - previous_time;
                previous_time = current_time;

                speed -= 10 * elapsed_time;    //10 because I want the bouncing to be faster.
                position -= speed * elapsed_time / 1000;
                if(speed < 0)
                {
                    speed = 0;
                }
                RenderTheMenuInItsCurrentPosition();
            }
            while(position < 0) //fall again
            {
                current_time = SDL_GetTicks();
                elapsed_time = current_time - previous_time;
                previous_time = current_time;

                speed += 10 * elapsed_time;    //10 because I want the bouncing to be faster.
                position -= speed * elapsed_time / 1000;
                if(position > 0)
                {
                    position = 0;
                    printf("final speed is: %d\n", speed); //if position is 0 the animation has finished(almost) so tell me the speed
                    printf("Time taken is: %d\n", SDL_GetTicks - start_speed);    //Tell me the time elapsed since the beginning.
                }
                RenderTheMenuInItsCurrentPosition();
            }
        }
    }

    checkForButtonsClicked();

    if(!return_button_clicked)//if the user requested to go back, go back
    {
        while(position > -568)
        {
        /*Here, sometimes a negative speed is reached before
        getting to the desired position
        causing the menu to go in the
        opposite direction, this doesn't
        happen all the time but it is
        unpredictable (to me at least),
       so it means that it doesn't accelerate
       and decelerate at the same pace always
       also that's why it doesn't throw
       the same speed value all the time.*/
            speed -= 1 * elapsed_time;
            position -= speed * elapsed_time / 1000;
            RenderTheMenuInItsCurrentPosition();
        }
    }
}
share|improve this question

1 Answer 1

Sounds like a job for an easing function! These are widely used to program animations, they are easy and flexible to use. An easing function usually takes an input between 0 and 1 (representing the progress of your animation, which plays from 0 to 1), and the output is also a number somewhere between 0 and 1, which you can use to multiply your position, or colour, or whatever it is you're animating.

Say you want to animate the movement of a variable y from y0 to y1, from start_time to end_time. You'll use an easing function like this:

time_interval = end_time - start_time;
y_interval = y1 - y0;
y = easing_function((time - start_time) / time_interval) * y_interval + y0;

From your description, it sounds like the easeOutBounce function will suit. Its output accelerates from start to end, but then bounces three times.

enter image description here

There is a C implementation of the easing functions here: https://github.com/warrenm/AHEasing

You can use it as-is, or if you want to make your own custom function (such as a bounce that bounces less, or quicker), take a look at the code - it's fairly easy to understand.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.