游戏循环更新太快

时间:2019-08-10 14:11:59

标签: java game-loop

我想为Pong克隆创建一个开始菜单,其中背景中的球从边缘反弹。但是,游戏循环更新为快速,因此球的坐标已经在JFrame之外,您才能看到它,并且它会快速移动。我通过sysouts发现了这一点。

我想这与线程有关,但我不确定。 主类将该类称为线程,但重要的部分在类BackgroundBallMovement

package main;

public class BackgroundBallMovement implements Runnable{

    private boolean running = true;


    @Override
    public void run() {

        long lastTime = System.nanoTime();
        final double ns = 1000000000.0 / 60;        
        double delta = 0;

        while(running) {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            while(delta >= 1) {
                update();
                delta = 0;
                System.out.println("X-Koordinate " + Var.ballX + " " + "Y-Koordinate " + Var.ballY);
            }
            render();
        }
    }

        //Spiellogik updaten
        private synchronized void update() {
            Var.ballX += 1;
            Var.ballY += 1;

        }

        //Objekte zeichnen
        private synchronized void render() {
             Var.drawStartMenue.repaint();
        }

}

3 个答案:

答案 0 :(得分:1)

您没有使用Thread.sleep()。相反,您正在等System.nanoTime()更改。这意味着CPU一直在运行(不好)。

也是这个循环:

while(delta >= 1) {
    ...
    delta = 0;
    ...
}

没有意义,因为可以用if代替它。

那么您就永远不会更新 lastTime 变量。所以这行:

delta += (now - lastTime) / ns;

将导致二次函数,因为它将导致如下所示(每次循环执行):

delta += 0.1;
delta += 0.2;
delta += 0.3;
...

然后,因为您永远不会在条件1s后更新 lastTime 变量

while(delta >= 1)

将始终满足您的要求,并且您的球将以惊人的速度移动。

您的第一种方法可能是这样的:

@Override
public void run()
{
    while(running)
    {
        update();
        render()
        System.out.println("X-Koordinate " + Var.ballX + " " + "Y-Koordinate " + Var.ballY);
        Thread.sleep(1000L/60L);
    }
}

答案 1 :(得分:0)

那是因为您的数学很烂;-)

是的,aggregate(q~gender, transform(df, q = q01*2+q02), mean) 是引擎启动以来应该渲染的帧数。因此,您的代码可简化为:

(now - lastTime) / ns

等效于

while (true) {
    delta = framesSinceStart();
    while (delta >= 1) {
        renderFrame();
        delta = 0;        
    }
}

也就是说,您的代码正确地等待渲染第一帧,但是没有记录它已经渲染了该帧,因此始终认为它已经晚了,不再等待。

相反,您可以尝试类似的操作:

while (true) {
    if (framesSinceStart() >= 1) {
        renderFrame();
    }
}

顺便说一句,仅仅停留在一个无休止的循环中来消磨时间并不是很省电。最好使用Thread.sleep()之类的东西等待-但是计算它应该手动等待的时间有点麻烦。幸运的是,Java API附带了很好的帮助程序类供使用:

while (true) {
    if (framesSinceStart() - framesRendered >= 1) {
        renderFrame();
        framesRendered++;
    }
}

答案 2 :(得分:0)

尝试Thread.sleep(long millis)

while(running) {
        long now = System.nanoTime();
        delta += (now - lastTime) / ns;
        while(delta >= 1) {
            update();
            delta = 0;

            try{
                Thread.sleep(1000);
            } catch(Exception e) { }

            System.out.println("X-Koordinate " + Var.ballX + " " + "Y-Koordinate " + Var.ballY);
        }
        render();
    }

您还可以尝试降低球速。

private synchronized void update() {
        Var.ballX += 0.01;
        Var.ballY += 0.01;

    }