当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何将重力应用于弹跳球应用?》经验,为你挑选了2个好方法。

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

这是一个快速截图:
替代文字http://img222.imageshack.us/img222/3179/ballbouncemf9.png

屏幕上的每个圆圈都是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
    }
}

这非常有效.所有的球都从墙到墙反弹.

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

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

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

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


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

在我的步骤()中,我向我的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.
}

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



1> Bill K..:

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

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

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

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

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

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

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



2> Scottie T..:

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

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

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

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

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

我们采取离散的时间步骤,dt.对于Euler方法,我们简单地用dt替换上述方程中t的所有出现,并使用前一个时间步长的值代替初始值x0,y0等.所以现在我们的方程看起来像这样(在伪代码中) :

//保存以前的值
xold = x;
yold = y;
vxold = vx;
vyold = vy;

//更新加速度
ax = -c vxold ^ 2;
ay = -c
vyold ^ 2 - 9.8;

//更新速度
vx = vxold + ax dt;
vy = vyold + ay
dt;

//更新位置
x = xold + vxold*dt + 0.5*ax dt ^ 2;
y = yold + vyold
dt + 0.5*ay*dt ^ 2;

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

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有