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 implemented a gameloop found here: http://www.koonsolo.com/news/dewitters-gameloop/ into my OpenGL ES 2.0 Android game. The tutorial was written with the canvas API in mind, not OpenGL so I made a few minor changes:

@Override
public void onDrawFrame(GL10 gl) {

//Main game loop
//This loop will limit the logic update to defined value and also the rendering

        //Reset loop counter
        loops = 0;
        //Is the current time greater than nextGametick and < maxFrameskip?
        //If so, then run logic update and keep doing so, while these conditions are true
        while( System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){
        update();
        Log.v("gameloop","Updating! ");
        //Update nextGameTic by adding skipTics value to it, ready for next comparison
        nextGameTick += skipTicks;
        //Update loops value ready for next comparison in while loop
        loops++;
        }


        //Once thses conditions are no longer true, exit while loop and render
            render();}

    }

}

I set my initial value for nextGameTick in onSurfaceChanged like so:

nextGameTick = System.currentTimeMillis();

It works fine in that it throttles the game updates to whatever I set my tickspersecond to (skipticks here is = to 1000/ticks per second).

So I'm limiting my update to say 30 updates per second. The only problem I have now is that onDrawFrame runs flat out (on a Samsung G Ace, I'm currently getting about 80FPS) so it's drawing a lot of redundant frames.

Question How can I throttle back onDrawFrame without using thread.sleep which I understand huge no no, or should I just leave the loop running flat out? (is battery drain really a major problem here?).

When I used this loop with Canvas I simply tied the rendering to the updating so that the render would only happen if an update had just occured. This doesn't work with openGL as if I use onDrawFrame for my main loop like so:

public void onDrawFrame(){

public void update();  //Break out to update method
public void render();  //Break out to draw method

}

Regarless of whether render() was run or not, onDrawFrame will call eglSwapBuffers and this causes flickering (as it swaps back and forth between frames with old new sprite positions if nothing new has been drawn)

Suggestions on how I should proceed would be welcome.

PS I've read continuously for a couple of days other questions pertaining to this, but I can't get a answer that relates to my particular problem.

share|improve this question
    
What gave you the impression that Thread.sleep was a bad idea? (I'm curious. =) –  leander May 5 '13 at 15:19
2  
stackoverflow.com/questions/14077403/… - "Attempting to use Thread.sleep() to manage the frame rate generally ends badly. You can't know how long the period between vsync is, or how long until the next one arrives. It's different for every device, and on some devices it may be variable. You essentially end up with two clocks, vsync and sleep, beating against each other, and the result is choppy animation. On top of that, Thread.sleep() doesn't make any specific guarantees about accuracy or minimum sleep duration." (among others) –  user22241 May 5 '13 at 15:50
    
That sounds like what I expected. It seems like if you detect that you're exceeding the rate you want to limit to, you might need to swap over to RENDERMODE_WHEN_DIRTY, and manually pump requestRender(): developer.android.com/reference/android/opengl/… -- presumably that would still vsync correctly, kicking off the onDrawFrame on the next vsync. I wonder if you could put that on a timer object or something that would be more precise than Thread.sleep... –  leander May 5 '13 at 16:28
1  
gafferongames.com/game-physics/fix-your-timestep is like dewitters game loop article, but looks at the gameloop from a slightly different perspective. –  sarahm May 5 '13 at 17:08
    
@leander, that's was something I was looking into - using RENDERMODE_WHEN_DIRTY. But I still wasn't thinking about using sleep, rather start another thread and basically call my update() method and requestRender() from within my new thread. Then basically when it doesn't get called, it just skips over and loops until it needs to run Update() or requestRender() - is this what you was thinking? The only reason I've not done it is because I've never heard of anyone using RENDERMODE_WHEN_DIRTY for a game other than a board game! (Mine is a platformer)...Cheers –  user22241 May 5 '13 at 17:50
show 2 more comments

Your Answer

 
discard

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

Browse other questions tagged or ask your own question.