Android The main game loop FPS independent

Started by
4 comments, last by cmac 6 years, 6 months ago

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

Newbie developer

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)

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.

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

 

Newbie developer

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.

This topic is closed to new replies.

Advertisement