如何将重力应用于弹跳球应用?

时间:2022-03-08 07:28:31

I've written a fairly simple java application that allows you to drag your mouse and based on the length of the mouse drag you did, it will shoot a ball in that direction, bouncing off walls as it goes.

我写了一个相当简单的java应用程序,它允许你拖动你的鼠标,并根据你所做的鼠标拖动的长度,它将向那个方向射击一个球,随着它走向墙壁反弹。

Here is a quick screenshot:
alt text http://img222.imageshack.us/img222/3179/ballbouncemf9.png

这是一个快速截图:alt文本http://img222.imageshack.us/img222/3179/ballbouncemf9.png

Each one of the circles on the screen is a Ball object. The balls movement is broken down into an x and y vector;

屏幕上的每个圆圈都是Ball对象。球运动被分解为x和y向量;

public class Ball {
    public int xPos;
    public int yPos;
    public int xVector;
    public int yVector;

    public Ball(int xPos, int yPos, int xVector, int yVector) {
        this.xPos = xPos;
        this.yPos = yPos;
        this.xVector = xVector;
        this.yVector = yVector;
    }

    public void step()
    {
        posX += xVector;
        posY += yVector;

        checkCollisions();
    }

    public void checkCollisions()
    {
        // Check if we have collided with a wall
        // If we have, take the negative of the appropriate vector
        // Depending on which wall you hit
    }

    public void draw()
    {
        // draw our circle at it's position
    }
}

This works great. All the balls bounce around and around from wall to wall.

这很好用。所有的球都从墙到墙反弹。

However, I have decided that I want to be able to include the effects of gravity. I know that objects accelerate toward the earth at 9.8m/s but I don't directly know how this should translate into code. I realize that the yVector will be affected but my experimentation with this didn't have the desired effect I wanted.

但是,我已经决定,我希望能够包含引力的影响。我知道物体以9.8m / s的速度向地球加速,但我不知道这应该如何转化为代码。我意识到yVector会受到影响,但我对此的实验没有达到我想要的效果。

Ideally, I would like to be able to add some gravity effect to this program and also allow the balls to bounce a few times before settling to the "ground."

理想情况下,我希望能够为这个程序添加一些重力效果,并且允许球在沉降到“地面”之前反弹几次。

How can I create this bouncing-elastic, gravity effect? How must I manipulate the speed vectors of the ball on each step? What must be done when it hits the "ground" so that I can allow it to bounce up again, but somewhat shorter then the previous time?

如何创造这种弹跳弹性重力效果?我如何在每一步操纵球的速度矢量?它撞到“地面”时必须做什么才能让它再次反弹,但比前一次更短?

Any help is appreciated in pointing me in the right direction.

在指出我正确的方向时,任何帮助都是值得赞赏的。


Thanks you for the comments everyone! It already is working great!

谢谢大家的评论!它已经很好用了!

In my step() I am adding a gravity constant to my yVector like people suggested and this is my checkCollision():

在我的步骤()中,我向我的yVector添加了一个重力常量,就像人们建议的那样,这是我的checkCollision():

public void checkCollision()
{
    if (posX - radius < 0)              // Left Wall?
    {
        posX = radius;              // Place ball against edge
        xVector = -(xVector * friction);
    }
    else if (posX + radius > rightBound) // Right Wall?
    {
        posX = rightBound - radius;     // Place ball against edge
        xVector = -(xVector * friction);
    }

    // Same for posY and yVector here.
}

However, the balls will continue to slide around/roll on the floor. I assume this is because I am simply taking a percentage (90%) of their vectors each bounce and it is never truly zero. Should I add in a check that if the xVector becomes a certain absolute value I should just change it to zero?

然而,球将继续在地板上滑动/滚动。我认为这是因为我只是将每个弹跳的百分比(90%)反弹并且它永远不会真正为零。我应该加上一个检查,如果xVector变成某个绝对值,我应该把它改成零吗?

9 个解决方案

#1


15  

What you have to do is constantly subtract a small constant (something that represents your 9.8 m/s) from your yVector. When the ball is going down (yVector is already negative), this would make it go faster. When it's going up (yVector is positive) it would slow it down.

你要做的就是不断从你的yVector中减去一个小的常数(代表你的9.8 m / s)。当球落下时(yVector已经为负),这将使它更快。当它上升时(yVector为正)它会减慢速度。

This would not account for friction, so the things should bounce pretty much for ever.

这不会解释摩擦,所以事情应该永远反弹。

edit1: To account for friction, whenever it reverses (and you reverse the sign), lower the absolute number a little. Like if it hits at yVector=-500, when you reverse the sign, make it +480 instead of +500. You should probably do the same thing to xVector to stop it from bouncing side-to-side.

edit1:考虑到摩擦,只要它反转(并且你反转符号),稍微降低绝对数。就像它在yVector = -500时命中一样,当你反转符号时,将其设为+480而不是+500。您可能应该对xVector执行相同的操作,以防止它从一侧到另一侧弹跳。

edit2: Also, if you want it to react to "air friction", reduce both vectors by a very small amount every adjustment.

edit2:另外,如果你想让它对“空气摩擦”做出反应,每次调整都会减少两个向量。

edit3: About the thing rolling around on the bottom forever--Depending on how high your numbers are, it could be one of two things. Either your numbers are large and it just seems to take forever to finish, or you are rounding and your Vectors are always 5 or something. (90% of 5 is 4.5, so it may round up to 5).

编辑3:关于永远在底层滚动的东西 - 根据你的数字有多高,它可能是两件事之一。要么你的数字很大而且它似乎需要永远完成,或者你正在四舍五入,你的向量总是5或者什么。 (5%的90%是4.5,因此它可能会达到5)。

I'd print out a debug statement and see what the Vector numbers are like. If they go to somewhere around 5 and just stay there, then you can use a function that truncates your fraction to 4 instead of rounding back to 5. If it keeps on going down and eventually stops, then you might have to raise your friction coefficient.

我打印出一个调试语句,看看Vector数字是什么样的。如果它们到达5左右的某个地方并且只是呆在那里,那么你可以使用一个函数将你的分数截断到4而不是回到5。如果它继续下降并最终停止,那么你可能需要提高你的摩擦系数。

If you can't find an easy "rounding" function, you could use (0.9 * Vector) - 1, subtracting 1 from your existing equation should do the same thing.

如果你找不到一个简单的“舍入”函数,你可以使用(0.9 *向量) - 1,从你现有的等式中减1应该做同样的事情。

#2


13  

When the balls are all rolling around on the ground, yes, check to see if the velocity is below a certain minimum value and, if so, set it to zero. If you look at the physics behind this type of idealized motion and compare with what happens in the real world, you'll see that a single equation cannot be used to account for the fact that a real ball stops moving.

当球在地面上滚动时,是的,检查速度是否低于某个最小值,如果是,则将其设置为零。如果你看一下这种理想化运动背后的物理特性,并与现实世界中的情况进行比较,你会发现单个方程不能用来说明真实球停止运动的事实。

BTW, what you're doing is called the Euler method for numerical integration. It goes like this:

顺便说一句,你正在做的是称为数值积分的欧拉方法。它是这样的:

  • Start with the kinematic equations of motion:
    x(t) = x0 + vx*t + 0.5*axt^2
    y(t) = y0 + vy
    t + 0.5*ayt^2
    vx(t) = vx0 + ax
    t
    vy(t) = vy0 + ay*t
    Where x and y are position, vx and vy are velocity, ax and ay are acceleration, and t is time. x0, y0, vx0, and vy0 are the initial values. This describes the motion of an object in the absence of any outside force.

    从运动的运动方程开始:x(t)= x0 + vx * t + 0.5 * axt ^ 2 y(t)= y0 + vyt + 0.5 * ayt ^ 2 vx(t)= vx0 + axt vy(t) = vy0 + ay * t其中x和y是位置,vx和vy是速度,ax和ay是加速度,t是时间。 x0,y0,vx0和vy0是初始值。这描述了在没有任何外力的情况下物体的运动。

  • Now apply gravity:
    ay = -9.8 m/s^2
    To this point, there's no need to do anything tricky. We can solve for the position of each ball using this equation for any time.

    现在应用重力:ay = -9.8 m / s ^ 2到目前为止,没有必要做任何棘手的事情。我们可以随时使用这个等式求解每个球的位置。

  • Now add air friction: Since it's a spherical ball, we can assume it has a coefficient of friction c. There are typically two choices for how to model the air friction. It can be proportional to the velocity or to the square of velocity. Let's use the square:
    ax = -cvx^2
    ay = -c
    vy^2 - 9.8
    Because the acceleration is now dependent on the velocity, which is not constant, we must integrate. This is bad, because there's no way to solve this by hand. We'll have to integrate numerically.

    现在添加空气摩擦:因为它是一个球形球,我们可以假设它有一个摩擦系数c。如何模拟空气摩擦通常有两种选择。它可以与速度或速度的平方成比例。让我们使用square:ax = -cvx ^ 2 ay = -cvy ^ 2 - 9.8因为加速度现在取决于速度,这不是常数,我们必须整合。这很糟糕,因为没有办法手工解决这个问题。我们必须在数字上进行整合。

  • We take discrete time steps, dt. For Euler's method, we simply replace all occurances of t in the above equations with dt, and use the value from the previous timestep in place of the initial values, x0, y0, etc. So now our equations look like this (in pseudocode):

    // Save previous values
    xold = x;
    yold = y;
    vxold = vx;
    vyold = vy;

    // Update acceleration
    ax = -cvxold^2;
    ay = -c
    vyold^2 - 9.8;

    // Update velocity
    vx = vxold + axdt;
    vy = vyold + ay
    dt;

    // Update position
    x = xold + vxold*dt + 0.5*axdt^2;
    y = yold + vyold
    dt + 0.5*ay*dt^2;
  • 我们采取离散的时间步骤,dt。对于Euler方法,我们简单地用dt替换上述方程中t的所有出现,并使用前一个时间步长的值代替初始值x0,y0等。所以现在我们的方程看起来像这样(在伪代码中) ://保存以前的值xold = x; yold = y; vxold = vx; vyold = vy; //更新加速度ax = -cvxold ^ 2; ay = -cvyold ^ 2 - 9.8; //更新速度vx = vxold + axdt; vy = vyold + aydt; //更新位置x = xold + vxold * dt + 0.5 * axdt ^ 2; y = yold + vyolddt + 0.5 * ay * dt ^ 2;

This is an approximation, so it won't be exactly correct, but it'll look OK. The problem is that for bigger timesteps, the error increases, so if we want to accurately model how a real ball would move, we'd have to use very tiny values for dt, which would cause problems with accuracy on a computer. To solve that, there are more complicated techniques. But if you just want to see behavior that looks like gravity and friction at the same time, then Euler's method is ok.

这是一个近似值,所以它不完全正确,但它看起来还不错。问题是,对于更大的时间步长,误差会增加,因此如果我们想要准确地模拟真实球的移动方式,我们必须使用非常小的dt值,这会导致计算机的准确性问题。要解决这个问题,有更复杂的技术。但如果你只是想看到同时看起来像重力和摩擦的行为,那么欧拉的方法就可以了。

#3


1  

Every time slice you have to apply the effects of gravity by accelerating the ball in teh y downwards direction. As Bill K suggested, that's as simple as making a subtraction from your "yVector". When the ball hits the bottom, yVector = -yVector, so now it's moving upwards but still accelarating downwards. If you want to make the balls eventually stop bouncing, you need to make the collisions slightly inelastic, basically by removing some speed in the y-up direction, possibly by instead of "yVector = -yVector", make it "yVector = -0.9 * yVector".

每次切片都需要通过向下加速球来施加重力效果。比尔K建议,这就像从你的“yVector”中减去一样简单。当球击中底部时,yVector = -yVector,所以现在它向上移动但仍然向下加速。如果你想让球最终停止弹跳,你需要使碰撞略微无弹性,基本上是通过在y-up方向上移除一些速度,可能是通过代替“yVector = -yVector”,使其成为“yVector = -0.9” * yVector“。

#4


1  

public void step()
{
    posX += xVector;
    posY += yVector;

    yVector += g //some constant representing 9.8

    checkCollisions();
}

in checkCollisions(), you should invert and multiply yVector by a number between 0 and 1 when it bounces on the ground. This should give you the desired effect

在checkCollisions()中,当它在地面上反弹时,你应该将yVector反转并乘以0到1之间的数字。这应该会给你想要的效果

#5


1  

It's a ballistic movement. So you got a linear movement on x-axis and an uniform accelerated movement on y-axis.

这是一场弹道运动。因此,您在x轴上进行了线性运动,在y轴上进行了均匀的加速运动。

The basic idea is that the y-axis will follow the equation:

基本思想是y轴将遵循以下等式:

y = y0 + v0 * t + (0.5)*a*t^2

Or, in C code, for example:

或者,在C代码中,例如:

float speed = 10.0f, acceleration = -9.8f, y = [whatever position];

y += speed*t + 0.5f*acceleration*t^2;

Where here I use tiem parametrization. But you could use Torricelli:

在这里我使用tiem参数化。但你可以使用Torricelli:

v = sqrt(v0^2 + 2*acceleration*(y-y0));

And, on this model, you must maintain the last values of v and y.

并且,在此模型上,您必须保持v和y的最后值。

Finally, I've done something similar using the first model with dt (time's differential) being fixed at 1/60 second (60 FPS).

最后,我使用第一个模型做了类似的事情,dt(时间差分)固定在1/60秒(60 FPS)。

Well, both models give good real-like results, but sqrt(), for example, is expensive.

嗯,两个模型都给出了很好的真实结果,但是例如sqrt()价格昂贵。

#6


0  

You really want to simulate what gravity does - all it does is create force that acts over time to change the velocity of an object. Every time you take a step, you change the velocity of your ball a little bit in order to "pull" it towards the bottom of the widget.

你真的想模拟重力的作用 - 它所做的就是创造一种力,随着时间的推移,它会改变一个物体的速度。每次你迈出一步,你都会稍微改变一下球的速度,以便将它“拉”到小部件的底部。

In order to deal with the no-friction / bouncing ball settles issue, you need to make the "ground" collision exert a different effect than just strict reflection - it should remove some amount of energy from the ball, making it bounce back at a smaller velocity after it hits the ground than it would otherwise.

为了解决无摩擦/弹跳球问题,你需要让“地面”碰撞产生不同于严格反射的不同效果 - 它应该从球中移除一些能量,使其在撞击地面后的速度比否则要小。

Another thing that you generally want to do in these types of bouncy visualizations is give the ground some sideways friction as well, so that when it's hitting the ground all the time, it will eventually roll to a stop.

你通常想要在这些类型的弹性可视化中做的另一件事是给地面一些侧向摩擦,这样当它一直撞到地面时,它最终会停止。

#7


0  

I agree with what "Bill K" said, and would add that if you want them to "settle" you will need to reduce the x and y vectors over time (apply resistance). This will have to be a very small amount at a time, so you may have to change your vectors from int to a floating point type, or only reduce them by 1 every few seconds.

我同意“Bill K”的说法,并补充一点,如果你想让它们“稳定”,你需要随着时间的推移减少x和y向量(应用阻力)。这一次必须是非常小的数量,因此您可能必须将矢量从int更改为浮点类型,或者每隔几秒将它们减少1。

#8


0  

What you want to do is change the values of xVector and yVector to simulate gravity and friction. This is really pretty simple to do. (Need to change all of your variables to floats. When it comes time to draw, just round the floats.)

你想要做的是改变xVector和yVector的值来模拟重力和摩擦力。这真的很简单。 (需要将所有变量更改为浮点数。当需要绘制时,只需将浮点数四舍五入。)

In your step function, after updating the ball's position, you should do something like this:

在你的步进功能中,在更新球的位置后,你应该做这样的事情:

yVector *= 0.95;
xVector *= 0.95;
yVector -= 2.0;

This scales the X and Y speed down slightly, allowing your balls to eventually stop moving, and then applies a constant downward "acceleration" to the Y value, which will accumulate faster than the "slowdown" and cause the balls to fall.

这会略微缩小X和Y的速度,让你的球最终停止移动,然后向Y值施加恒定的向下“加速度”,这将比“减速”累积得更快并导致球落下。

This is an approximation of what you really want to do. What you really want is to keep a vector representing the acceleration of your balls. Every step you would then dot product that vector with a constant gravity vector to slightly change the ball's acceleration. But I think that my be more complex than you want to get, unless you're looking for a more realistic physics simulation.

这是你真正想做的事情的近似。你真正想要的是保持一个代表你的球加速度的矢量。然后,每一步,您都会使用恒定的重力矢量对该矢量进行点测,以略微改变球的加速度。但我认为除非你正在寻找更逼真的物理模拟,否则我会比你想要的更复杂。

#9


0  

What must be done when it hits the "ground" so that I can allow it to bounce up again

当它撞到“地面”时必须做什么才能让它再次反弹

If you assume a perfect collision (ie all the energy is conserved) all you have to do reverse the sign of one of the velocity scalar depending on which wall was hit.

如果你假设一个完美的碰撞(即所有的能量都是守恒的),你必须做的就是根据撞击的墙壁反转其中一个速度标量的符号。

For example if the ball hits the right or left walls revese the x scalar component and leave the the y scalar component the same:

例如,如果球击中右侧或左侧墙壁,则会显示x标量组件,并使y标量组件保持相同:

 this.xVector = -this.xVector;

If the ball hits the top or bottom walls reverse the y scalar component and leave the x scalar component the same:

如果球撞击顶部或底部墙壁,则反转y标量分量并使x标量分量保持不变:

 this.yVector = -this.yVector;

but somewhat shorter then the previous time?

但比前一次短一些?

In this scenario some of the energy will be lost in the collision with the wall so just add in a loss factor to take of some of the velocity each time the wall is hit:

在这种情况下,一些能量将在与墙壁的碰撞中丢失,因此每次撞击墙壁时,只需增加一些损耗因子即可获得一些速度:

 double loss_factor = 0.99;
 this.xVector = -(loss_factor * this.xVector);
 this.yVector = -(loss_factor * this.yVector;

#1


15  

What you have to do is constantly subtract a small constant (something that represents your 9.8 m/s) from your yVector. When the ball is going down (yVector is already negative), this would make it go faster. When it's going up (yVector is positive) it would slow it down.

你要做的就是不断从你的yVector中减去一个小的常数(代表你的9.8 m / s)。当球落下时(yVector已经为负),这将使它更快。当它上升时(yVector为正)它会减慢速度。

This would not account for friction, so the things should bounce pretty much for ever.

这不会解释摩擦,所以事情应该永远反弹。

edit1: To account for friction, whenever it reverses (and you reverse the sign), lower the absolute number a little. Like if it hits at yVector=-500, when you reverse the sign, make it +480 instead of +500. You should probably do the same thing to xVector to stop it from bouncing side-to-side.

edit1:考虑到摩擦,只要它反转(并且你反转符号),稍微降低绝对数。就像它在yVector = -500时命中一样,当你反转符号时,将其设为+480而不是+500。您可能应该对xVector执行相同的操作,以防止它从一侧到另一侧弹跳。

edit2: Also, if you want it to react to "air friction", reduce both vectors by a very small amount every adjustment.

edit2:另外,如果你想让它对“空气摩擦”做出反应,每次调整都会减少两个向量。

edit3: About the thing rolling around on the bottom forever--Depending on how high your numbers are, it could be one of two things. Either your numbers are large and it just seems to take forever to finish, or you are rounding and your Vectors are always 5 or something. (90% of 5 is 4.5, so it may round up to 5).

编辑3:关于永远在底层滚动的东西 - 根据你的数字有多高,它可能是两件事之一。要么你的数字很大而且它似乎需要永远完成,或者你正在四舍五入,你的向量总是5或者什么。 (5%的90%是4.5,因此它可能会达到5)。

I'd print out a debug statement and see what the Vector numbers are like. If they go to somewhere around 5 and just stay there, then you can use a function that truncates your fraction to 4 instead of rounding back to 5. If it keeps on going down and eventually stops, then you might have to raise your friction coefficient.

我打印出一个调试语句,看看Vector数字是什么样的。如果它们到达5左右的某个地方并且只是呆在那里,那么你可以使用一个函数将你的分数截断到4而不是回到5。如果它继续下降并最终停止,那么你可能需要提高你的摩擦系数。

If you can't find an easy "rounding" function, you could use (0.9 * Vector) - 1, subtracting 1 from your existing equation should do the same thing.

如果你找不到一个简单的“舍入”函数,你可以使用(0.9 *向量) - 1,从你现有的等式中减1应该做同样的事情。

#2


13  

When the balls are all rolling around on the ground, yes, check to see if the velocity is below a certain minimum value and, if so, set it to zero. If you look at the physics behind this type of idealized motion and compare with what happens in the real world, you'll see that a single equation cannot be used to account for the fact that a real ball stops moving.

当球在地面上滚动时,是的,检查速度是否低于某个最小值,如果是,则将其设置为零。如果你看一下这种理想化运动背后的物理特性,并与现实世界中的情况进行比较,你会发现单个方程不能用来说明真实球停止运动的事实。

BTW, what you're doing is called the Euler method for numerical integration. It goes like this:

顺便说一句,你正在做的是称为数值积分的欧拉方法。它是这样的:

  • Start with the kinematic equations of motion:
    x(t) = x0 + vx*t + 0.5*axt^2
    y(t) = y0 + vy
    t + 0.5*ayt^2
    vx(t) = vx0 + ax
    t
    vy(t) = vy0 + ay*t
    Where x and y are position, vx and vy are velocity, ax and ay are acceleration, and t is time. x0, y0, vx0, and vy0 are the initial values. This describes the motion of an object in the absence of any outside force.

    从运动的运动方程开始:x(t)= x0 + vx * t + 0.5 * axt ^ 2 y(t)= y0 + vyt + 0.5 * ayt ^ 2 vx(t)= vx0 + axt vy(t) = vy0 + ay * t其中x和y是位置,vx和vy是速度,ax和ay是加速度,t是时间。 x0,y0,vx0和vy0是初始值。这描述了在没有任何外力的情况下物体的运动。

  • Now apply gravity:
    ay = -9.8 m/s^2
    To this point, there's no need to do anything tricky. We can solve for the position of each ball using this equation for any time.

    现在应用重力:ay = -9.8 m / s ^ 2到目前为止,没有必要做任何棘手的事情。我们可以随时使用这个等式求解每个球的位置。

  • Now add air friction: Since it's a spherical ball, we can assume it has a coefficient of friction c. There are typically two choices for how to model the air friction. It can be proportional to the velocity or to the square of velocity. Let's use the square:
    ax = -cvx^2
    ay = -c
    vy^2 - 9.8
    Because the acceleration is now dependent on the velocity, which is not constant, we must integrate. This is bad, because there's no way to solve this by hand. We'll have to integrate numerically.

    现在添加空气摩擦:因为它是一个球形球,我们可以假设它有一个摩擦系数c。如何模拟空气摩擦通常有两种选择。它可以与速度或速度的平方成比例。让我们使用square:ax = -cvx ^ 2 ay = -cvy ^ 2 - 9.8因为加速度现在取决于速度,这不是常数,我们必须整合。这很糟糕,因为没有办法手工解决这个问题。我们必须在数字上进行整合。

  • We take discrete time steps, dt. For Euler's method, we simply replace all occurances of t in the above equations with dt, and use the value from the previous timestep in place of the initial values, x0, y0, etc. So now our equations look like this (in pseudocode):

    // Save previous values
    xold = x;
    yold = y;
    vxold = vx;
    vyold = vy;

    // Update acceleration
    ax = -cvxold^2;
    ay = -c
    vyold^2 - 9.8;

    // Update velocity
    vx = vxold + axdt;
    vy = vyold + ay
    dt;

    // Update position
    x = xold + vxold*dt + 0.5*axdt^2;
    y = yold + vyold
    dt + 0.5*ay*dt^2;
  • 我们采取离散的时间步骤,dt。对于Euler方法,我们简单地用dt替换上述方程中t的所有出现,并使用前一个时间步长的值代替初始值x0,y0等。所以现在我们的方程看起来像这样(在伪代码中) ://保存以前的值xold = x; yold = y; vxold = vx; vyold = vy; //更新加速度ax = -cvxold ^ 2; ay = -cvyold ^ 2 - 9.8; //更新速度vx = vxold + axdt; vy = vyold + aydt; //更新位置x = xold + vxold * dt + 0.5 * axdt ^ 2; y = yold + vyolddt + 0.5 * ay * dt ^ 2;

This is an approximation, so it won't be exactly correct, but it'll look OK. The problem is that for bigger timesteps, the error increases, so if we want to accurately model how a real ball would move, we'd have to use very tiny values for dt, which would cause problems with accuracy on a computer. To solve that, there are more complicated techniques. But if you just want to see behavior that looks like gravity and friction at the same time, then Euler's method is ok.

这是一个近似值,所以它不完全正确,但它看起来还不错。问题是,对于更大的时间步长,误差会增加,因此如果我们想要准确地模拟真实球的移动方式,我们必须使用非常小的dt值,这会导致计算机的准确性问题。要解决这个问题,有更复杂的技术。但如果你只是想看到同时看起来像重力和摩擦的行为,那么欧拉的方法就可以了。

#3


1  

Every time slice you have to apply the effects of gravity by accelerating the ball in teh y downwards direction. As Bill K suggested, that's as simple as making a subtraction from your "yVector". When the ball hits the bottom, yVector = -yVector, so now it's moving upwards but still accelarating downwards. If you want to make the balls eventually stop bouncing, you need to make the collisions slightly inelastic, basically by removing some speed in the y-up direction, possibly by instead of "yVector = -yVector", make it "yVector = -0.9 * yVector".

每次切片都需要通过向下加速球来施加重力效果。比尔K建议,这就像从你的“yVector”中减去一样简单。当球击中底部时,yVector = -yVector,所以现在它向上移动但仍然向下加速。如果你想让球最终停止弹跳,你需要使碰撞略微无弹性,基本上是通过在y-up方向上移除一些速度,可能是通过代替“yVector = -yVector”,使其成为“yVector = -0.9” * yVector“。

#4


1  

public void step()
{
    posX += xVector;
    posY += yVector;

    yVector += g //some constant representing 9.8

    checkCollisions();
}

in checkCollisions(), you should invert and multiply yVector by a number between 0 and 1 when it bounces on the ground. This should give you the desired effect

在checkCollisions()中,当它在地面上反弹时,你应该将yVector反转并乘以0到1之间的数字。这应该会给你想要的效果

#5


1  

It's a ballistic movement. So you got a linear movement on x-axis and an uniform accelerated movement on y-axis.

这是一场弹道运动。因此,您在x轴上进行了线性运动,在y轴上进行了均匀的加速运动。

The basic idea is that the y-axis will follow the equation:

基本思想是y轴将遵循以下等式:

y = y0 + v0 * t + (0.5)*a*t^2

Or, in C code, for example:

或者,在C代码中,例如:

float speed = 10.0f, acceleration = -9.8f, y = [whatever position];

y += speed*t + 0.5f*acceleration*t^2;

Where here I use tiem parametrization. But you could use Torricelli:

在这里我使用tiem参数化。但你可以使用Torricelli:

v = sqrt(v0^2 + 2*acceleration*(y-y0));

And, on this model, you must maintain the last values of v and y.

并且,在此模型上,您必须保持v和y的最后值。

Finally, I've done something similar using the first model with dt (time's differential) being fixed at 1/60 second (60 FPS).

最后,我使用第一个模型做了类似的事情,dt(时间差分)固定在1/60秒(60 FPS)。

Well, both models give good real-like results, but sqrt(), for example, is expensive.

嗯,两个模型都给出了很好的真实结果,但是例如sqrt()价格昂贵。

#6


0  

You really want to simulate what gravity does - all it does is create force that acts over time to change the velocity of an object. Every time you take a step, you change the velocity of your ball a little bit in order to "pull" it towards the bottom of the widget.

你真的想模拟重力的作用 - 它所做的就是创造一种力,随着时间的推移,它会改变一个物体的速度。每次你迈出一步,你都会稍微改变一下球的速度,以便将它“拉”到小部件的底部。

In order to deal with the no-friction / bouncing ball settles issue, you need to make the "ground" collision exert a different effect than just strict reflection - it should remove some amount of energy from the ball, making it bounce back at a smaller velocity after it hits the ground than it would otherwise.

为了解决无摩擦/弹跳球问题,你需要让“地面”碰撞产生不同于严格反射的不同效果 - 它应该从球中移除一些能量,使其在撞击地面后的速度比否则要小。

Another thing that you generally want to do in these types of bouncy visualizations is give the ground some sideways friction as well, so that when it's hitting the ground all the time, it will eventually roll to a stop.

你通常想要在这些类型的弹性可视化中做的另一件事是给地面一些侧向摩擦,这样当它一直撞到地面时,它最终会停止。

#7


0  

I agree with what "Bill K" said, and would add that if you want them to "settle" you will need to reduce the x and y vectors over time (apply resistance). This will have to be a very small amount at a time, so you may have to change your vectors from int to a floating point type, or only reduce them by 1 every few seconds.

我同意“Bill K”的说法,并补充一点,如果你想让它们“稳定”,你需要随着时间的推移减少x和y向量(应用阻力)。这一次必须是非常小的数量,因此您可能必须将矢量从int更改为浮点类型,或者每隔几秒将它们减少1。

#8


0  

What you want to do is change the values of xVector and yVector to simulate gravity and friction. This is really pretty simple to do. (Need to change all of your variables to floats. When it comes time to draw, just round the floats.)

你想要做的是改变xVector和yVector的值来模拟重力和摩擦力。这真的很简单。 (需要将所有变量更改为浮点数。当需要绘制时,只需将浮点数四舍五入。)

In your step function, after updating the ball's position, you should do something like this:

在你的步进功能中,在更新球的位置后,你应该做这样的事情:

yVector *= 0.95;
xVector *= 0.95;
yVector -= 2.0;

This scales the X and Y speed down slightly, allowing your balls to eventually stop moving, and then applies a constant downward "acceleration" to the Y value, which will accumulate faster than the "slowdown" and cause the balls to fall.

这会略微缩小X和Y的速度,让你的球最终停止移动,然后向Y值施加恒定的向下“加速度”,这将比“减速”累积得更快并导致球落下。

This is an approximation of what you really want to do. What you really want is to keep a vector representing the acceleration of your balls. Every step you would then dot product that vector with a constant gravity vector to slightly change the ball's acceleration. But I think that my be more complex than you want to get, unless you're looking for a more realistic physics simulation.

这是你真正想做的事情的近似。你真正想要的是保持一个代表你的球加速度的矢量。然后,每一步,您都会使用恒定的重力矢量对该矢量进行点测,以略微改变球的加速度。但我认为除非你正在寻找更逼真的物理模拟,否则我会比你想要的更复杂。

#9


0  

What must be done when it hits the "ground" so that I can allow it to bounce up again

当它撞到“地面”时必须做什么才能让它再次反弹

If you assume a perfect collision (ie all the energy is conserved) all you have to do reverse the sign of one of the velocity scalar depending on which wall was hit.

如果你假设一个完美的碰撞(即所有的能量都是守恒的),你必须做的就是根据撞击的墙壁反转其中一个速度标量的符号。

For example if the ball hits the right or left walls revese the x scalar component and leave the the y scalar component the same:

例如,如果球击中右侧或左侧墙壁,则会显示x标量组件,并使y标量组件保持相同:

 this.xVector = -this.xVector;

If the ball hits the top or bottom walls reverse the y scalar component and leave the x scalar component the same:

如果球撞击顶部或底部墙壁,则反转y标量分量并使x标量分量保持不变:

 this.yVector = -this.yVector;

but somewhat shorter then the previous time?

但比前一次短一些?

In this scenario some of the energy will be lost in the collision with the wall so just add in a loss factor to take of some of the velocity each time the wall is hit:

在这种情况下,一些能量将在与墙壁的碰撞中丢失,因此每次撞击墙壁时,只需增加一些损耗因子即可获得一些速度:

 double loss_factor = 0.99;
 this.xVector = -(loss_factor * this.xVector);
 this.yVector = -(loss_factor * this.yVector;