Jump to content
  • Advertisement
durianodour

Android The main game loop FPS independent

This topic is 395 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am just a newbie game developer, I am trying to create a frame independent game loop.

I am currently using the following code

 private class MainGameThread extends Thread {
        public static final int PAUSE_SLEEP_TIME = 10;
        long previous = getCurrentTimeInMillis();
        long totalElapsed = 0;
        long gameTimeStart = 0;
        long currentTime = getCurrentTimeInMillis();
        long accumulatorTime = 0;

        @Override
        public void run() {
            gameTimeStart = getCurrentTimeInMillis();
            while (mIsRunning) {
                // Pause game
                while (mIsPaused) {
                    try {
                        Thread.sleep(PAUSE_SLEEP_TIME);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                long current = getCurrentTimeInMillis();
                long elapsed = current - previous;
                previous = current;
                processGameInput();
                updateGameState(elapsed);
                totalElapsed += elapsed;
                if (totalElapsed > MainGame.MS_PER_FRAME) {
                    drawGame();
                    totalElapsed -= MainGame.MS_PER_FRAME;
                    if (totalElapsed > MainGame.MS_PER_FRAME) {
                        Log.e("GAME", "Performance warning, rendering or update took too long");
                    }
                }
                checkIfGameShouldStop(gameTimeStart);
            }
            shutdownGracefully();
        }

        private void shutdownGracefully() {
        }
    }

It works, how ever it performs differently on different devices

In my game models update method I am performing the following actions

  mCenterX += (mVelocityVector.x * timeElapsed);
  mCenterY += (mVelocityVector.y * timeElapsed + gameSpeed.getValue())

I have read this article https://gafferongames.com/post/fix_your_timestep/

But I can't understand the final example

double t = 0.0;
double dt = 0.01;

double currentTime = hires_time_in_seconds();
double accumulator = 0.0;

State previous;
State current;

while ( !quit )
{
    double newTime = time();
    double frameTime = newTime - currentTime;
    if ( frameTime > 0.25 )
        frameTime = 0.25;
    currentTime = newTime;

    accumulator += frameTime;

    while ( accumulator >= dt )
    {
        previousState = currentState;
        integrate( currentState, t, dt );
        t += dt;
        accumulator -= dt;
    }

    const double alpha = accumulator / dt;

    State state = currentState * alpha + 
        previousState * ( 1.0 - alpha );

    render( state );
}

What does the State class object mean in this case.

Could someone please help to adapt this example to my case or explain the example from the article and how I could update my loop to be frame independent ?

Thanks

Share this post


Link to post
Share on other sites
Advertisement

I'm familiar with that article and have used it as reference for my own projects. The state object represents the state-of-being of objects being simulated in the game/physics/whatever simulation.

That is, the state contains position, velocity, rotation/orientation, etc. And each game object has 2 states: the most recently computed state (let's call it the previous state), and the one before that (let's call it the ultra-previous state).

Then, all that talk of accumulators and interpolation is saying to compute the "actual current state of the world" by interpolating between the ultra-previous state and the previous state. The motivation of this approach is to always "consume" all of the frame time available, in each cycle of the loop. And it probably helps for when you get into online multiplayer (a big topic on the gafferongames blog) - it probably helps ensure that each instance of the networked game has the same idea of what state each object in the game world is in.

Personally, I prefer not to go that route. Instead, I just carry over whatever remains in the accumulator, for the next game loop cycle. It saves the cost of interpolating between states, and it works well enough for my purposes.

(I just realized I said all that, but didn't say how to change your code, which was a party of your original question. But I'll leave that as an exercise for the reader :-D hopefully the explanation of state helped)

Edited by masskonfuzion

Share this post


Link to post
Share on other sites

As masskonfuzion says, at frame N there will be three states:

  • The Physics state at frame N-1; that is the state of the previous frame (state in this case means position, orientation and scale of all objects; and maybe something else if needed, like velocity)
  • The Physics state at frame N; that is the state of the current frame
  • The graphics state, which is an interpolation somewhere between N-1 and N.

 

1 hour ago, masskonfuzion said:

And it probably helps for when you get into online multiplayer (a big topic on the gafferongames blog) - it probably helps ensure that each instance of the networked game has the same idea of what state each object in the game world is in.

Personally, I prefer not to go that route. Instead, I just carry over whatever remains in the accumulator, for the next game loop cycle. It saves the cost of interpolating between states, and it works well enough for my purposes.

Errr... really the main motivation for interpolating is to detach physics framerate from graphics framerate. So your physics may be updated at 30hz and your graphics rendered at 60hz; or physics at 120hz and graphics at 60hz.

Another big reason is to combine variable frame rate for graphics (which is good for smoothness and performance) and fixed frame for physics (which is good for simulation stability and required for achieving determinism). Without interpolation, you either update at fixed framerate, or at variable framerate. Interpolation gives you both.

You can even go beyond what gafferongames' teaches and put graphics in a separate thread; allowing to do graphics in a different CPU core, but this is a more advanced topic.

Share this post


Link to post
Share on other sites

Thanks everyone for answers. I have much simpler case. I don't need to have all these complex calculations depending on different forces currently acting on an object.

I have  a simple game. I have only one object a ball that is falling down, or a different shape. I need just to catch it or skip. 

So I guess I don't need to integrate and save states between frames.

The only one variable that I change in my update method is 

mCenterX += (mVelocityVector.x * timeElapsed);

mCenterY += (mVelocityVector.y * timeElapsed + gameSpeed.getValue())

These variables just represent the position of a falling shape and that is all. 

The reason I tried to apply described method, just to develop even a simple game following best practices.

So maybe you could suggest me another way to achieve FPS independent rendering considering my requirements. 

I would be grateful for any further help

 

Edited by durianodour

Share this post


Link to post
Share on other sites

At first glance your code looks fine, can you be more specific about how it's inconsistent across different devices?

You haven't provided your drawing code, but note that if you are using Repaint, the screen will not be repainted immediately (it will wait for the next RepaintManager cycle). If you are using Repaint, try changing it to paintImmediately.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!