2017-04-11 60 views
2

所以我一直在尝试编写一个物理模拟。我从模拟一个自由落体开始很小。我在Java中使用Java Jframe和一些来自awt库的方法。然而,我一直面临的问题是调整参数以使我的模拟更加生活。我的游戏while循环以恒定的60 FPS运行,这意味着每个循环都需要16 ms。每次我更新,我执行这些法律:物理模拟,将像素调整为米?

this.velX = this.velX + (accX)*delta; 
this.velY = this.velY + (accY) * delta ; 

this.velY = this.velY * 0.9; 


this.x = this.x + (int) ((this.velX) * delta); 
this.y = this.y + (int) ((this.velY)* delta); 

然而,由于我转换为int的值总是又回到了0,因为它们非常小。而形状的绘制方法只接受int(我认为这是可以理解的,对吧?)我想知道是否会有解决方案?球会卡住,它的运动不会明显(如果它移动的话)。

我试着将delta传递为1,它很好地工作,但它太快了,但我认为它不现实。因此,如果有人能够给我关于这个问题的一般想法,那将是非常有用的。

+1

“16毫升秒” - 16毫秒?我想这应该是“毫秒”=毫秒? – Fildor

+3

这听起来像你正在从渲染他们的同一个地方读你的坐标 - 这正是你眼中问题的原因。尝试将坐标存储在一些专用对象中,这些对象可以以您实际需要的任何形式接受它们(即以'double'或其他形式),然后在渲染它们时仅转换为'int'。 –

+0

是的,抱歉,我编辑了它。 – Robot0110

回答

1

的问题是,在这些线路

this.x = this.x + (int) ((this.velX) * delta); 
this.y = this.y + (int) ((this.velY)* delta); 

让长期方程((this.velX) * delta) and ((this.velY) * delta)的后一部分deltaX and deltaY

所以公式应成为

this.x = this.x + (int) deltaX; 
this.y = this.y + (int) deltaY; 

现在,这里的问题是,您将deltaX and deltaY转换为整数,从而将他们对x and y职位的贡献降至零。

即使长时间(多帧)的变化很小,贡献也会变得很大。

假设变化deltaX.1它应该能够在10帧中添加1像素移位。

如果您的draw函数只带有整数,那么您应该在该行之前转换位置值,但应该是float or double以用于所有其他目的。

所以公式应该是

this.x = this.x + this.velX * delta; //this.x is float 
this.y = this.y + this.velY* delta; //this.x is float 

draw((int)x, (int)y) 

现在应该工作。

注意:另外我不知道你如何保持恒定的帧率,因为Java不能这样做。您将不得不考虑可变帧频。你已经完成了使用delta。 Delta值不应该是恒定的,应该在每帧结束时计算。

+0

非常感谢你!这实际上工作!我正在使用典型的thread.sleep来处理处理输入后16 ms剩下的内容。那是错的吗? – Robot0110

+0

是的,'Thread.sleep()'不能保证线程在指定的确切时间被唤醒。所以你可以使用'System.currentTimeMillis()'来计算睡眠时的实际delta值。这应该完美。 – 11thdimension

+0

@ user70319,更好的办法是使用'java.util.concurrent.ScheduledExecutorService',它有这个方便的方法'scheduleAtFixedRate',它可以让你每x个时间单位运行一些代码。请注意,如果您的计划代码太慢而无法及时完成执行,则应该捕获这些实例并处理它们。 –