这可能是一个非常基本的问题,但我似乎无法找到任何其他文章。
无论如何,我用Java编写了一个小弹跳球程序,试图扩展我的基本技能。该程序只是一个简单的弹跳球,它会下降并且希望反弹一段时间。原始程序工作正常,但现在我已经尝试将重力添加到程序中。重力实际上可以正常运行一段时间但是一旦弹跳变得非常小,动画在很短的时间内变得不稳定,那么球的位置就会不断减小。我试图找出问题,但我只是看不到它。任何帮助都是最受欢迎的。
public final class Ball extends Rectangle {
float xspeed = 1.0f; float yspeed = 1.0f; float gravity = 0.4f;
public Ball(float x, float y, float width, float height) {
super(x, y, width, height);
}
public void update(){
yspeed += gravity;
move(xspeed, yspeed);
if(getX() < 0){
xspeed = 1;
}
if(getX() + getWidth() > 320){
xspeed = -1;
}
if(getY() < 0){
yspeed = 1;
}
if(getY() + getHeight() > 200 && yspeed > 0){
yspeed *= -0.98f;
}
if(getY() + getHeight() > 200 && yspeed < 0){
yspeed *= 0.98f;
}
}
public void move(float x, float y){
this.setX(getX()+x);
this.setY(getY()+y);
}
}
编辑:谢谢,这似乎已经排除了飘忽不定的运动。我仍然在努力想看看当它停止弹跳时我怎么能阻止我的球向下移动。现在它将移动停止弹跳然后继续向下移动通过“地板”。我认为这与我的yspeed + =重力线有关。我只是看不出如何停止运动。
答案 0 :(得分:3)
当你这样做时
yspeed += gravity;
你假设球有空间移动距离dx = v_i * t + 1/2(-g)t ^ 2。当你离地板很近时,这可能不是真的。如果出现失败:
此错误会导致您的模拟停止节约能源,从而导致您在低振幅下看到的不稳定行为。
您可以通过使用较小的时间步骤来减少问题,如果您在离开房间时进行测试计算以及选择的安全时间步骤,则可以彻底摆脱它 iteration(即除非出现问题,否则总是使用默认值,然后计算最佳时间步长)。
但是,您在此处使用的基本近似值也存在其他问题。查看任何数值分析文本,以获得数值求解微分方程的讨论。
答案 1 :(得分:1)
我怀疑是因为当球反弹时,它实际上会略低于“地面”,而在低速时,它不会在一个刻度线上移回地面 - 所以下一次更新()会看到它仍然低于地面,并再次反弹 - 但这次向下,所以循环继续。
你需要在弹跳时将球移回地面,如下所示:
if(getY() + getHeight() > 200){
yspeed *= -0.981;
setY(200 - getHeight());
}
答案 2 :(得分:1)
首先要做的事情:当你在窗口顶部反弹时将y速度设置为1是不正确的,你应该将yspeed设置为-yspeed(但是如果你在边框内开始,它应该永远不会反弹到顶部反正)。
其次,当你在底部反弹时,你乘以-0.981是可以的,但我关注的是每次迭代都会将常数0.4重力加到yspeed上。我认为这是导致你在底部摆动的原因,因为你在检查之前进行了移动,这可能导致球落到地面以下。
我会尝试通过以下方式替换移动来确保y值永远不会低于地面水平:
if (getY() + getHeight() + yspeed > 200) {
move(xspeed, 200 - getY() - getHeight());
} else {
move(xspeed, yspeed);
}
答案 3 :(得分:1)
问题是当反弹变得非常小时,
yspeed *= -0.981;
行将在短时间内被调用。球将低于底部,开始回升,但仍然低于底部(因为0.981 <1.0)最终,并且它将表现出根本性。以下是解决问题的方法:
if(getY() + getHeight() > 200){
yspeed *= -0.981;
setY(400 - getY() - getHeight()); // I believe this is right.
}
通过固定位置,你不会在减速和增加之间交替,并且不会在它总是在减少的情况下卡住,因为它总是低于界限。
答案 4 :(得分:1)
[编辑:我想我误解了,所以这可能没用多少:)]
if(getY() + getHeight() > 200){
yspeed *= -0.981;
}
你在每次更新时都否定了垂直速度。我可能会尝试在更新大小的切片中处理重力。假设您每秒进行30次更新(30fps),可能类似
// Define some constants
SecondsPerUpdate = (1.0f / 30);
AccelDueToGravity = 0.981;
if(getY() + getHeight() > 200){
yspeed -= (AccelDueToGravity * SecondsPerUpdate);
}