0

Overview

Having a lot of problem with choppy animations in my game loop. I'm running the loop from onDrawFrame and as you can see, my loop allows for frame skipping if it takes too long (I'm using a fixed time delta and my time 'slice' for 60fps is 16.666666ms).

I've confirmed that the stuttering happens when frames are skipped.

  • When there are frame skips, how can I stop the animation from going choppy?

If it absolutely has to skip frames (I concede there will be times on certain devices when this will happen), how can I mitigate the choppiness?

  • onDrawFrame(GL10 gl) seems to be called up to 24ms since the last time it was called.

On my Google Nexus 10 Tablet, my actual rendering can take anywhere between 5 and 14ms and my game updates only take between 0 and 4ms so most of the time it should fit nicely into the 16.6666 time slice. However, when I remove everything from onDrawFrame, it seems to be called anywhere from 16 to 25ms apart. (Most times, it is above 16ms), therefore, it's skipping a lot of frames - even without rendering or updates being called!!

This seems to go against the whole point of a device running at 60FPS - is this VSync doing this? What's the point of it taking more than 16ms?

Things I've attempted

OK, I tried spawning a separate thread on which I run my updates (again, limiting them to 60 per second). I still get the problem.

I've also tried interpolation but this again, hasn't made any difference. (I am going to be posting a separate question to see if I've got that right).

I'm really struggling with this so I hope someone can help!

Code

float interpolation;
long nextGameTick = System.currentTimeMillis();
//loop counter
int loops;
//This is the amount of frames that we allow our app to skip before logic updating is affected (generally shouldn't happen)
final int maxFrameskip = 5;                             
//Game updates per second
final int ticksPerSecond = 60;
//Amount of time each update should take        
final int skipTicks = (1000 / ticksPerSecond);

    public void onDrawFrame(GL10 gl) {


        //Set/Re-set loop back to 0 to start counting again
        loops=0;

        while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){

        SceneManager.getInstance().getCurrentScene().updateLogic();
        nextGameTick+=skipTicks;
        timeCorrection += (1000d/ticksPerSecond) % 1;
        nextGameTick+=timeCorrection;
        timeCorrection %=1;
        loops++;
        tics++;

     }

        interpolation = (float)(System.currentTimeMillis() + skipTicks - nextGameTick)
              / (float)skipTicks; 

    render(interpolation);
}

Applying interpolation

render(float interpolation){

    //This example shows interpolation for X axis only.  Y position (spriteScreenY is assumed to be valid)
    interpolatedPosX = spriteGridX+(SpriteXVelocity*dt)*interpolation;
    spriteScreenPosX = interpolationPosX * screenWidth;

    drawSprite(spriteScreenX, spriteScreenY);           


}
Zippy
  • 3,826
  • 5
  • 43
  • 96
  • Do you allocate any memory in your game loop (remember that iterating through collections with for-each syntax allocates a an iterator)? GC may cause stuttering. Check logcat debug messages for "D/dalvikvm GC_CONCURRENT freed", it will show you how long it paused. – Matis May 21 '14 at 15:54
  • Hi @thanks for the comment - there is no allocation happening during my loop - this is one of the first things I checked so I ruled that out early on - cheers! – Zippy May 21 '14 at 15:58
  • @Zippy Do you solve the isssue.I have the same problem – Jithin Sunny Jun 13 '14 at 04:48
  • Hi @Sunny, unfortunately, I haven't solved it. I've tried everything but still have choppy animation when frames are skipped. For now, I'm just living with it but need to re-visit it at some point. If you come across any suggestions, would love to hear them!! :-( – Zippy Jun 13 '14 at 08:38

1 Answers1

0

Try using RENDERMODE_WHEN_DIRTY. This means not using onDrawFrame anymore, but instead using requestRender() in your game loop.

tache
  • 173
  • 1
  • 8