游戏循环性能问题

时间:2016-05-26 17:20:00

标签: java game-loop

我正在用Java制作一个炸弹人游戏,游戏似乎正在减缓PC超载处理器和CPU的速度。我在另一个游戏中使用了循环,它工作正常,没有造成任何性能问题。但是我确实注意到只需注释掉gameloop()就会导致重大的性能问题

游戏循环我使用:

public void start() {
    window.setVisible(true);
    running = true;
    int fps = 60;
    double timePerTick = 1e9 / fps;
    double delta = 0;
    long now;
    long lastTime = System.nanoTime();

    while (running) {
        now = System.nanoTime();
        delta += (now - lastTime) / timePerTick;
        lastTime = now;
        if (delta >= 1) {
            gameLoop(); /* commenting this out will cause major performance
                         * problem to the PC */
            delta--;
        }
    }
}

@Override
public void gameLoop() {
    if(!gameover){
        run();
        gui.repaint();
    }
}

这个循环是否有任何问题可能导致问题,或者是否有更好的方法可以减少性能问题

[编辑] 我改变循环以使用计时器执行类似的任务,它工作正常并且不会导致任何性能问题,此方法的任何问题仍然存在(长期问题)?

public void start(int fps){
   window.setVisible(true);
   running = true;
   gameTimer.scheduleAtFixedRate(new GameTimer(), 0, 1000/fps);
}

private class GameTimer extends TimerTask{

   @Override
   public void run(){
      gameLoop();
   }
}

2 个答案:

答案 0 :(得分:1)

您正在进行无限循环而没有任何暂停消耗100%的CPU,在您的情况下根据您的需要,您应该定义您的帧速率并设置相应的睡眠时间,如下所示:

    run();
    gui.repaint();
    // Make the current thread sleeps 1 000 milliseconds which means 1 frame per sec
    Thread.sleep(1000L);

答案 1 :(得分:0)

您正在忙着循环,这将使一个线程永久忙碌。这不可避免地会占用CPU资源,减少对其他任何东西的可用性。

当有足够的时间过去时,你应该预测,而不是经常使用nanoTime()并调用gameloop(),此时下一次调用gameloop()将会发生并调用Thread.sleep ()暂停线程直到到达时间。出于许多目的,它的准确性足以计算下一个滴答到期时的毫秒时间戳,减去当前时间并睡眠该量:

long lastTick = System.currentTimeMillis();
long ticksPerFrame = 1000 / fps;
while (true) {
    long nextTick = lastTick + ticksPerFrame;
    long sleep = nextTick - System.currentTimeMillis();
    if (sleep > 0) {
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    lastTick = nextTick;
    gameloop();
}

(未经过测试的代码,仅用于演示一般方法)

这将仅与系统计时器分辨率加/减睡眠变化一样准确。对于大多数系统而言,这意味着平均几毫秒的变化,对于许多场景都是可接受的,特别是如果你使用AWT / Swing进行渲染的话。如果你以比EDT处理它们更快的速度放置repaint()调用,可以跳过重绘,这在大多数情况下是可取的,因为它允许重绘队列在延迟时赶上。