3
\$\begingroup\$

So far I have this implementation of "FYTS".

However I am facing several problems.

    final int TICKS_PER_S = 60;
    double accumulator = 0.0;
    //The timestep
    final double dt = 1/(double)TICKS_PER_S;
    long previousTime = System.currentTimeMillis();

    //State previous;
    //State current;
    while(running){

        long currentTime = System.currentTimeMillis();
        double frameTime = (currentTime - previousTime)/1000;

        if(frameTime > 0.25){
            frameTime = 0.25;
        }
        previousTime = currentTime;
        accumulator += frameTime;

        while(accumulator >= dt){

            //previousState = currentState;
            this.gamePanel.update(dt);
            accumulator -= dt;
        }

        //Interpolation
        // final double alpha = currentState * alpha +
        //               previousState * (1.0 - alpha);

        //This is the draw call. Not yet using interpolation
        this.gamePanel.postInvalidate();
    }

Problem 1:

frameTime is always 0 meaning that the game is never updating. It seems obvious: In the beginning it is 0, but that should change, shouldn't it?

Problem 2:

Let's assume that Problem 1 wouldn't exist. I understand that you take an arbitrary frameTime and split it up into discrete timesteps and then update the game. But what's the point of updating in a separate nested loop anyways? Most of the time you are left with a little remainder at the end of finishing the inner update loop. That remainder is how much of the simulation is left to complete until the running loop starts again and takes a new frameTime on which a part of the simulation has to be performed on. But what does the interpolation do that's worth to even consider doing it Isn't the inner update loop just a waste of time?

Problem 3:

The outer loop is running without any limitations at max speed. Isn't that just wasting clock cycles (and draining the battery life on mobile devices)? Is there anything I could do to counteract that?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

I'll only deal with Problem 1 here since the rest should be clear to your from experimentation, once this bug is fixed.

It's Java: I think you need to convert long <-> double correctly. That would be why you're getting zero. Set up a very simple example where you just cast a double to a long and do vice versa with two separate variables, and see what happens. You should quickly see the problem. I believe the value is being truncated or somesuch. You can alternatively try using long for everything.

You are also involving an integer literal (1000) in that expression, further complicating type concerns. I suggest explicitly casting each term to double, and making 1000.0 i.e. a double.

\$\endgroup\$
4
  • \$\begingroup\$ Thank you for your help. After applying your advice my game is finally running. The FPS are very inconsistent. The game is mostly stuttering and sometimes even completely stopping. I haven't applied the interpolation yet, because I would like to have it working at least on a very basic level before I change my rendering "engine". I assume the inconsistent FPS are a result of my outer loop which calls postInvalidate() (the draw call) as much as possible. What could I do to remove the stuttering? \$\endgroup\$ Oct 30, 2016 at 20:49
  • \$\begingroup\$ Update: I have been able to get rid of most of the stutter (there is still some subtle sutter, but I hope interpolation will fix that). What I did was that I implemented this idea. I introduced a boolean that is set to true inside the nested loop (meaning the game updates) and only if that condition is true postInvalidate is called. The problem is that after (around) 20 seconds of running my game it suddenly drops a lot of frames and then goes back to normal. Do you know what could be the cause of that instability? \$\endgroup\$ Oct 30, 2016 at 21:06
  • \$\begingroup\$ Update 2: Seems like Update 1 doesn't seem to work as well as I thought. I still drop a lot of frames and the game still has the same issues. Please help \$\endgroup\$ Oct 30, 2016 at 22:37
  • \$\begingroup\$ @ThomasHartmann I don't know; why don't you output the numbers, frame by frame, in order to see what's happening? Sounds like your accumulator reaches some critical value after 20 sec, perhaps? One does not simply implement a solution like this without really understanding what the code it is doing, at every step. \$\endgroup\$
    – Engineer
    Oct 31, 2016 at 7:20
0
\$\begingroup\$

Problem 1

The frameTime shouldn't be zero. That would mean your CPU is cycling through the operations in the loop within a millisecond of the system time. Does printing the frameTime value at the end of the loop always show it to be zero? If so, make sure your timing function provides you with the resolution you need to successfully determine the frame time.

Problem 2

The point of the nested update loop is to let the update() call catch up to missed frames. Physics simulations work best when the time step is fixed. If, for example, frames are dropped at some point during the simulation, the time step would usually change drastically leading to unpredictable simulation results. It is not possible to write reliable tests in such an environment.

Using an accumulator for the frame time makes it possible to re-update the game or simulation state for as many frames as were missed, keeping the update result consistent, predictable, and testable.

Problem 3

The impact of the outer run loop on performance depends on the operations it is performing. If you're only updating the accumulator during this time, the cost of the outer loop is negligible in comparison to the update loop. However, if you're drawing at the end of the outer loop, then you could have something to worry about.

In that case, you can run the draw call at a different rate, or only run it when the state is updated with changes that will be reflected by drawing.

\$\endgroup\$
7
  • \$\begingroup\$ "Problem 1: That would mean your CPU is cycling through the operations in the loop within a millisecond of the system time" - no such concern. This is purely a numeric type issue. I've experienced it before. \$\endgroup\$
    – Engineer
    Oct 30, 2016 at 7:28
  • \$\begingroup\$ Precisely why I specified to check the granularity of the timing function. \$\endgroup\$
    – Domagoj
    Oct 30, 2016 at 7:41
  • \$\begingroup\$ Granularity is not the same as failure to correctly convert between numeric types. \$\endgroup\$
    – Engineer
    Oct 30, 2016 at 7:44
  • \$\begingroup\$ Thank you for your help. Problem 1 is solved. My game is running, however the FPS are really inconsistent. The game stutters a lot and sometimes even stops completely. I assume this is because of postInvalidate() (the draw call) being called as much as possible. I should mention that I haven't applied the interpolation yet, but that can't be the reason as it would only provide a subtle improvement as to smoothness? Do you know by any chance where the stuttering comes from and if so how I could resolve it? \$\endgroup\$ Oct 30, 2016 at 20:52
  • \$\begingroup\$ Update: I have been able to get rid of most of the stutter (there is still some subtle sutter, but I hope interpolation will fix that). What I did was that I implemented this idea. I introduced a boolean that is set to true inside the nested loop (meaning the game updates) and only if that condition is true postInvalidate is called. The problem is that after (around) 20 seconds of running my game it suddenly drops a lot of frames and then goes back to normal. Do you know what could be the cause of that instability? \$\endgroup\$ Oct 30, 2016 at 21:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .