Java 使球弹起停止

Java 使球弹起停止,java,physics,bounce,Java,Physics,Bounce,我有一个包含以下变量的ball类: int x,y,width,height; double velX,velY; 我想让它,每当球碰到一个方块,它就会反弹,并失去一些速度 //Gravity & movement for the ball ball.setVelY(ball.getVelY() + 0.2); ball.setY((int)(ball.getY() + ball.getVelY())); //Make the ball bounce. if(ball.getBou

我有一个包含以下变量的ball类:

int x,y,width,height;
double velX,velY;
我想让它,每当球碰到一个方块,它就会反弹,并失去一些速度

//Gravity & movement for the ball
ball.setVelY(ball.getVelY() + 0.2);

ball.setY((int)(ball.getY() + ball.getVelY()));

//Make the ball bounce.
if(ball.getBounds().intersects(block.getBounds()){
     ball.setVelY(ball.getVelY() * -0.7);          
}

我认为这会使球缓慢反弹,直到它完全移动为止(我会进行测试,然后让球完全停止),但事实并非如此。球通常会反弹几次,每次反弹都比之前的小。但是,经过几次反弹后,球的反弹速度将停止低于先前的反弹速度。为什么会这样?我应该怎么做才能解决它?

这里的问题是,你基本上是在对球施加小的力,不连续地。即使你正在缩小动量,你也在不断地将这个值
0.2
加到球的动量上

作为一个类比,你周期性地施加重力,就是短时间地向下敲击球,给它提供动量。如果你想象一个静止的篮球在地面上,或者略高于地面,然后你开始快速敲击它,它就有可能使球反弹。然而,如果你想象用你的手向球施加一个恒定的向下的力(就像重力一样),那么球将无法反弹


因为不可能让你的程序以连续的方式运行,可以说,你必须找到一种方法来解决这个问题。一种解决方案是简单地检查撞击地面时的最小动量阈值,如果低于该阈值,则将其动量设置为0,并将其设置为与地面齐平。

问题可能是数值问题。写作时你在做什么

ball.setVelY(ball.getVelY() + 0.2);
ball.setY(ball.getY() + ball.getVelY());
是使用。事实上,这是对以下内容的简化:

ball.setVelY(ball.getVelY() + g * DeltaTime); // g = 9.8m/s² for earth gravity
ball.setY(ball.getY() + ball.getVelY() * DeltaTime);
其中,
DeltaTime
是积分时间步长,为简单起见,积分时间步长等于1

不幸的是,Euler方法只在条件上是稳定的,这意味着您可能会在速度发散的情况下结束(或这种类型的永无止境的振荡)。为了恢复稳定性,最好的方法是减小时间步长,在您的情况下,这意味着减小速度,或者更确切地说减小重力。尝试将g从0.2设置为0.05,并将计时器的频率增加4以验证这一点


如果你对数学感兴趣,你也可以看看无条件稳定的方法,比如。

我同意这个评估。最好以连续方式应用力,然后检查阈值(例如0或更小)。通过这种方式,您可以避免它必须周期性地更新,而只是让它不断地运动,直到其他力/等影响它。