0

I'm making games in Java. I'm using this game loop:

public void run() {

    this.requestFocus();

    double firstTime = 0;
    double lastTime = System.nanoTime() / 1000000000.0;
    double unprocessedTime = 0;
    double passedTime = 0;
    boolean render = false;
    double frameTime = 0;
    int frames = 0;
    int fps = 0;

    while (running) {

        render = false;

        firstTime = System.nanoTime() / 1000000000.0;
        passedTime = firstTime - lastTime;
        lastTime = firstTime;

        unprocessedTime += passedTime;
        frameTime += passedTime;

        while (unprocessedTime >= UPDATE_CAP) {
            unprocessedTime -= UPDATE_CAP;
            render = true;
            // TODO: update game
            if (frameTime >= 1.0) {

                fps = frames;
                frameTime = 0;
                frames = 0;
                System.out.println("FPS: " + fps);

            }
        }

        if (render) {

            frames++;
            tick();
            render();
        } else {

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

    stop();
}

I have a problem - FPS are dropping very low, even when there's only menu opened and pretty much nothing is happening.

FPS: 60
FPS: 61
FPS: 61
FPS: 61
FPS: 61
FPS: 48
FPS: 25
FPS: 8
FPS: 3
FPS: 4
FPS: 61

I have no idea why this is happening. If you want I can share more game code.

..................................

boyernek
  • 45
  • 8
  • 2
    1. NEVER rely on Thread.sleep() for delay. It is very unreliable. 2. How much memory did you assign to the process? It is possible that a garbage collection is slowing down the application. Can you check it? –  Jan 30 '21 at 13:37
  • @tibetiroka: Would you elaborate why `Thread.sleep()` is not reliable for delay? – Nikolas Charalambidis Jan 30 '21 at 14:25
  • @NikolasCharalambidis The [javadoc](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/Thread.html#sleep(long)) mentions that the accuracy depends on the os. [This](https://stackoverflow.com/questions/23169557/thread-sleep-and-precise-timing) and [this](https://stackoverflow.com/questions/18736681/how-accurate-is-thread-sleep) question also mentions it. Generally, it has roughly the same accuracy as System.currentTimeMillis(), which is known to be +-30ms on most Windows-based systems. –  Jan 30 '21 at 14:34
  • I did a small benchmark once and it turned out that the java.util.Timer is more accurate than the javax.swing.Timer, which is still way more accurate than using Thread.sleep. I don't think I still have the results, but I can re-test it in the latest releases if necessary. –  Jan 30 '21 at 14:37
  • @tibetiroka: Thanks for the information. It is useful when you need to delay a thread for *some* time (rough), but not when an exact time is required. – Nikolas Charalambidis Jan 30 '21 at 15:19
  • Well in his case the delay can't be more than 10-15 ms. But yes, if you want to wait for 5-10 seconds then it is alright. –  Jan 30 '21 at 15:48

1 Answers1

2

I know what happened: I was creating a lot of Font objects every tick:

public void render(Graphics g) {
   Font f1 = new Font("SansSherif", Font.BOLD, 20);
   Font f2 = new Font("SansSherif", Font.BOLD, 50);
   Font f3 = new Font("SansSherif", Font.BOLD, 135);
}

Now, I'm creating them only when game starts.

boyernek
  • 45
  • 8