简体   繁体   English

使球弹跳停止

[英]Make ball bounce to a stop

I have a ball class with the following variables: 我有一个带有以下变量的球类:

int x,y,width,height;
double velX,velY;

I want to make it so that whenever the ball hits a block, it bounces and it looses some velocity. 我想这样做,以使每当球碰到一个障碍物时,它都会反弹并失去一些速度。

//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);          
}

I thought this would make the ball bounce slowly until it was barley moving at all (which I would test for and then have the ball stop completely,) but this is not the case. 我认为这会使球缓慢弹起,直到大麦完全移动为止(我会进行测试,然后将球完全停下来),但事实并非如此。 The ball will bounce several times normally with each bounce being smaller than the one before. 球通常会弹跳几次,每次弹跳都小于之前的弹跳。 However, after a few bounces, the ball will stop bouncing lower than previous bounces. 但是,经过几次弹跳后,球将停止弹跳,低于先前的弹跳。 Why is this and what should I do to fix it? 为什么会这样,我应该怎么做才能解决?

The problem here is that you are essentially applying small bursts of force to the ball, discretely. 这里的问题是,您实际上是在向球离散地施加小的力。 Even though you are scaling the momentum down, you are constantly adding this value of 0.2 to the ball's momentum. 即使您将动量按比例减小,您仍会不断将0.2值添加到球的动量上。

As an analogy, what you are doing by periodically applying gravity, is tapping the ball downwards in short bursts, giving it momentum. 打个比方,您通过定期施加重力来执行的操作是短暂地向下击球,以使其具有动量。 If you imagine a still basket ball that is on, or slightly above the ground, and you start tapping it rapidly, it's possible to make the ball bounce. 如果您想象一个静止的篮子球在上面或稍稍高于地面,并且开始快速敲击它,则有可能使球反弹。 However, if you imagine applying a constant downwards force to the ball with your hand (like gravity truly is), then the ball will fail to bounce. 但是,如果您想象用一只手向球施加恒定的向下力(确实像重力一样),那么球将无法弹跳。

As it's impossible to have your program run in a continuous manner, so to speak, you have to find a way around this. 因为不可能以连续的方式运行程序,所以可以说,您必须找到解决方法。 One solution is to simply check for a minimum threshold of momentum upon impact with the floor, and if it is below this threshold then set its momentum to 0, and set it so that it is plush with the surface. 一种解决方案是简单地检查与地板碰撞时的最小动量阈值,如果低于此阈值,则将其动量设置为0,并将其设置为与表面平齐。

The problem might be a numerical one. 问题可能是数字上的。 What you are doing when writting 写作时你在做什么

ball.setVelY(ball.getVelY() + 0.2);
ball.setY(ball.getY() + ball.getVelY());

is integrating a differential equation using the Euler method . 使用Euler方法积分微分方程。 In fact, it's a simplification of: 实际上,它是对以下内容的简化:

ball.setVelY(ball.getVelY() + g * DeltaTime); // g = 9.8m/s² for earth gravity
ball.setY(ball.getY() + ball.getVelY() * DeltaTime);

where DeltaTime is your integration time step , which you take equal to one, for simplicity. 为了简单起见,其中DeltaTime是您的积分时间步长 ,等于1。

Unfortunately, the Euler method is only conditionally stable , which means you can end up in situations where the velocity diverges (or this type of never-ending oscillations). 不幸的是,欧拉方法仅在条件上稳定 ,这意味着您可能会遇到速度发散(或这种永无止境的振荡)的情况。 In order to recover stability, the best way is to decrease the time step , which in your case means to decrease the velocity, or rather decrease the gravity. 为了恢复稳定性,最好的方法是减少时间步长 ,在您的情况下,这意味着降低速度,或者降低重力。 Try setting g from 0.2 to 0.05, and increase the frequency of your timer by 4 to verify this. 尝试将g从0.2设置为0.05,然后将计时器的频率增加4进行验证。

If you are into maths, you could also take a look at unconditionally stable methods, such as the backward Euler method . 如果您喜欢数学,还可以看看无条件稳定的方法,例如后向Euler方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM