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