Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 游戏循环更新太快_Java_Game Loop - Fatal编程技术网

Java 游戏循环更新太快

Java 游戏循环更新太快,java,game-loop,Java,Game Loop,我想为乒乓球克隆创建一个开始菜单,背景中的球从边缘反弹。但是,游戏循环会更新为fast,因此球的坐标在你看到它之前就已经超出了JFrame,并且它会移动到fast。我是通过sysouts发现的 我想这与线程有关,但我不确定。 主类将这个类称为线程,但重要的部分是在类BackgroundBallMovement中 packagemain; 公共类BackgroundBallMovement实现Runnable{ 私有布尔运行=真; @凌驾 公开募捐{ long lastTime=System.na

我想为乒乓球克隆创建一个开始菜单,背景中的球从边缘反弹。但是,游戏循环会更新为fast,因此球的坐标在你看到它之前就已经超出了JFrame,并且它会移动到fast。我是通过sysouts发现的

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

packagemain;
公共类BackgroundBallMovement实现Runnable{
私有布尔运行=真;
@凌驾
公开募捐{
long lastTime=System.nanoTime();
最终双ns=100000000.0/60;
双增量=0;
(跑步时){
long now=System.nanoTime();
增量+=(现在-上次)/ns;
而(增量>=1){
更新();
δ=0;
System.out.println(“X-Koordinate”+Var.ballX+”+“Y-Koordinate”+Var.ballY);
}
render();
}
}
//斯皮洛吉克更新
私有同步的无效更新(){
变量ballX+=1;
巴利变量+=1;
}
//泽克宁目标酒店
私有同步的void render(){
Var.drawStartMenue.repaint();
}
}

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

是,
(now-lastTime)/ns
是自引擎启动后应渲染的帧数。因此,您的代码简化为:

while (true) {
    delta = framesSinceStart();
    while (delta >= 1) {
        renderFrame();
        delta = 0;        
    }
}
这相当于

while (true) {
    if (framesSinceStart() >= 1) {
        renderFrame();
    }
}
也就是说,您的代码正确地等待渲染第一帧,但不记录它已渲染该帧,因此始终认为它已延迟,并且不再等待

相反,您可以尝试以下方法:

while (true) {
    if (framesSinceStart() - framesRendered >= 1) {
        renderFrame();
        framesRendered++;
    }
}
顺便说一句,仅仅停留在一个无休止的循环中花费时间并不是很节能。最好使用Thread.sleep()之类的工具来等待,但是手工计算它应该等待的时间有点麻烦。幸运的是,Java API附带了很好的助手类:

ThreadPoolExecutor executor = Executors.newSingleThreadExecutor();
executor.scheduleAtFixedRate(() -> renderFrame(), 0, 1000 / 60, TimeUnit.ms);

您没有使用Thread.sleep()。而是等待System.nanoTime()发生更改。这意味着CPU一直在运行(不好)

此外,此循环:

while(delta >= 1) {
    ...
    delta = 0;
    ...
}
没有意义,因为它可以被if替换

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

delta += (now - lastTime) / ns;
将产生一个二次函数,因为它将产生如下结果(每次循环执行):

然后,因为在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);
    }
}
尝试
Thread.sleep(长毫秒)

你可以尝试的另一件事是降低球的速度

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

    }

我很抱歉。我不明白。delta=framesSinceStart()?我不知道你想用它实现什么。我应该在哪里等?我想渲染尽可能多的帧以获得流畅的效果,是吗?我想通过总结不必要的细节来告诉你哪里出了问题。关键问题是你的数学错了。在决定更新时,您要检查第一次更新是否应该在此时发生,而不是检查更新是否少于帧速率所指示的更新。不,您不希望render()比update()更频繁,因为这相当于反复在屏幕上重新绘制相同的图片,这会产生明显的差异,但不必要地浪费CPU和GPU时间。ballX和ballY变量是整数。即使它们不是整数,我也不认为有1/100的像素,是吗?每调用100次,它就会移动1个像素。
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;

    }