-1
\$\begingroup\$

For some reason, this game loop renders the movement of a simple rectangle with no stuttering.

    double currTime;
    double prevTime = System.nanoTime() / NANO_TO_SEC;
    double FPSTIMER = System.nanoTime();
    double maxTimeDiff = 100.0 / 1000.0;
    double delta = 1.0 / 60.0;
    int processes = 0, frames = 0;

    while(true){
        currTime = System.nanoTime() / NANO_TO_SEC;
        if(currTime - prevTime > maxTimeDiff) prevTime = currTime;
        if(currTime >= prevTime){
            process();
            processes++;
            prevTime += delta;
            if(currTime < prevTime){
                render();
                frames++;
            } 
        }
        else{
            try{
                Thread.sleep((long) (1000 * (prevTime - currTime)));
            }
            catch(Exception e){}
        }

        if(System.nanoTime() - FPSTIMER > 1000000000.0){
            System.out.println("Process: " + (1000 / processes) + "ms FPS: " + (1000 / frames) + "ms");
            processes = frames = 0;
            FPSTIMER += 1000000000.0;
        }
    }

But for this game loop, I get really minor stuttering where the movement does not look smooth.

    long prevTime = System.currentTimeMillis();
    long prevRenderTime = 0;
    long currRenderTime = 0;
    long delta = 0;
    long msPerTick = 1000 / 60;
    int frames = 0;
    int ticks = 0;
    double FPSTIMER = System.currentTimeMillis();

    while (true){
        long currTime = System.currentTimeMillis();
        delta += (currTime - prevTime) / msPerTick;
        prevTime = currTime;

        while (delta >= 1){
            ticks++;
            process();
            delta -= 1;
        }

        prevRenderTime = System.currentTimeMillis();
        render();
        frames++;
        currRenderTime = System.currentTimeMillis();

        try{
            Thread.sleep((long) ((1000 / FPS) - (currRenderTime - prevRenderTime)));
        }
        catch(Exception e){}

        if(System.currentTimeMillis() - FPSTIMER > 1000.0){
            System.out.println("Process: " + (1000.0 / ticks) + "ms FPS: " + (1000.0 / frames) + "ms");
            ticks = frames = 0;
            FPSTIMER += 1000.0;
        }

Is there any critical difference that I'm missing here? The one thing I noticed is that if I uncap the fps for the second game loop, the stuttering goes away. It doesn't make sense to me. Also, the second game loop came from Notch's Minicraft code with just my thread sleeping code added in.

\$\endgroup\$
0
\$\begingroup\$

I agree don't use sleep.

Use a timer based on system time

eg:

take system time snapshot (snapA),

compare it every loop frame to the current time in miliseconds or snapB.

some pseudocode

snapA = systemtime.milliseconds;

while(running)
{
     snapB = systemtime.milliseconds;

     if (snapB >= snapA+(1000/desiredframerate))
     {
         snapA = snapB
         drawFrame;
     }
     else 
         continue;
}

This is a good way to do it by my tests in the past. This allows frames to drop (go missing) when necessary () but allow a other things to happen on other threads if this loop/thread hangs for any reason.

Eg: if your animation and movement within the scene is on one thread and this is on another, if this thread hangs (such is the nature of java) then the other thread continues allowing movement to continue and this thread will drop frames till it picks up the current frame from the scene. It also means that the animation/ movement isn't relying on the graphics frame rate.

java can be funny with threads. When we were taught about threads for our java oracle professional exam it was explained that sometimes the JVM will kill/sleep/join or continue a thread and I quote "because it feels like it" so be careful and don't sleep a thread unless precision is unimportant.

also

(Notch)

Thread.sleep((long) (1000 * (prevTime - currTime)));

is not the same as

(you)

Thread.sleep((long) ((1000 / FPS) - (currRenderTime - prevRenderTime)));

Logically speaking.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.