user10609235
user10609235

Reputation:

Game loop stuttering

Im a beginner at Java. I tried to create a simple program with Swing where many balls are bouncing around. The program was running fine, smooth 60 fps and no stutter. However CPU was constantly running at 20%. Later I read somewhere that I can limit the CPU usage by adding Thread.sleep method at the end of the loop. However if I do that, program sometimes stutter. I have no idea why, I didnt change anything else. It doesnt always stutter, sometimes it doesn`t stutter at all even if im running the program for long times. But sometimes it starts stuttering as soon as I open the program. Also when it stutters, FPS is still showing 60. So is there something I did wrong?

This is the game loop:

    long currentTime;
    long lastTime = System.nanoTime();
    int targetFps = 60;
    int timePerTick = 1000000000 / targetFps;
    long delta = 0;
    long fpsTimer = 0;
    int fpsCounter = 0;

    while(running) {
        currentTime = System.nanoTime();
        delta += currentTime - lastTime;
        fpsTimer += currentTime - lastTime;
        lastTime = currentTime;
        if(delta >= timePerTick) {
            fpsCounter++;
            update();
            render();
            delta -= timePerTick;

        }
        if(fpsTimer >= 1000000000) {
            System.out.println("FPS: " + fpsCounter);
            fpsTimer = 0;
            fpsCounter = 0;
        }

        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

Upvotes: 1

Views: 1145

Answers (3)

FredK
FredK

Reputation: 4084

You should use a Swing Timer rather than writing your own loop.

Upvotes: 0

that other guy
that other guy

Reputation: 123490

You should not aim at getting 60 frames per second. Instead, you should aim at getting 1 frame per 1/60th of a second.

The difference, and the reason why you're seeing lag at 60FPS, is that currently if you see a 200ms lag for whichever reason, you simply render 59 frames in the remaining 800ms. This still comes out to 60 FPS, but clearly not in a way that's meaningful to the experience.

You can instead allot ~16ms to each frame. If a frame takes less time, sleep for the remainder. If it takes more time, skip the render() for the next frame (but keep the update() unless you can rewrite it to support fluid time steps). This way, your FPS numbers will be more representative, and will show all the various scheduling and GC hiccups that you're currently obscuring by averaging them out over a long period.

Upvotes: 2

kkica
kkica

Reputation: 4104

The fact that the program stutters does not mean that you have lower fps. In this case it just means that you have the same frame multiple times (because you put the thread to sleep and nothing changes in the UI).

Why it stutters? Probably because of context switching. When you put the thread to sleep, the system can "give" the processor to some other task X, and it takes longer than 1ms for your code to run again, because your code would execute after that task X has executed for some time slot.

What you want to do. Adding a Thread.sleep(1) call is not the right thing to do. You need to make sure that the code runs and the UI is updated in periodic intervals possibly that it behaves the same in slow and fast systems. You should look into game loops in more detail.

EDIT

I am no expert, but @Sedrick suggested in the comments this link that seems to explain what you want to do and how to do it.

Upvotes: 1

Related Questions