【问题标题】:Implement bouncing balls collision detection实现弹跳球碰撞检测
【发布时间】:2013-01-14 05:15:16
【问题描述】:

我有一个弹跳球应用程序,我必须扩展它以防止球重叠。

当球与另一个球重叠时,它们应该像在现实生活中一样移开。

我必须扩展给定的MoveBall 方法:

        private void MoveBall()
    {
        prevX = x;
        prevY = y;
        x += xVelocity;
        y += yVelocity;

        // Is there too closed ball?

        foreach (Ball ball in parentForm.balls)
        {
            distance = Math.Sqrt(Math.Pow((double)(ball.prevX - prevX), 2) + 
                                 Math.Pow((double)(ball.prevY- prevY), 2));
            overlap = ((radius + ball.radius) - distance);// +ball.radius;

            if (ball.id != this.id && 
                ball.id != lastID &&
                overlap > 0)
            {
                lastID = this.id;
                if (xVelocity > 0) // roading right 
                {
                    xVelocity = -xVelocity;
                    x -= xVelocity - ball.xVelocity;
                }
                else if (xVelocity <= 0) // roading left 
                {
                    xVelocity = -xVelocity;
                    x += xVelocity + ball.xVelocity;
                }
                if (yVelocity > 0)
                { // going up
                    yVelocity = -yVelocity;
                    y -= yVelocity - ball.yVelocity;
                }
                else if (yVelocity <= 0) // down
                {
                    yVelocity = -yVelocity;
                    y += yVelocity + ball.yVelocity;
                }

            }
        }

        // ***********************************************
        // ***************** END MY CODE *****************
        if (x > parentForm.Width - 10 - (radius) || x < 0)
        {
            if (x < 0) x = 0;
            if (x > parentForm.Width - 10) x = parentForm.Width - 10 - radius;
            xVelocity = -xVelocity;
        }
        if (y > parentForm.Height - 40 - (radius) || y < 0)
        {
            if (y < 0) y = 0;
            if (y > parentForm.Height - 40) y = parentForm.Height - 40 - (radius);
            yVelocity = -yVelocity;
        }

    }

x,y, xVelocity, yVelocity, radius, prevX, prevY 声明为 int。

重叠,距离加倍。

当 2 个重叠时,它们会卡住。为什么?

很遗憾,由于模块太多,我无法上传所有源代码。 我正在使用 Visual C# Express 2010。

【问题讨论】:

  • 很遗憾,您在此处编写的内容不适合 Stack Overflow。您需要首先减少问题;找出出错的代码,然后构造一个minimal test-case 来演示它。一个测试用例包括输入和输出。
  • 您的问题是什么?我已经阅读了您的代码和课程,但我无法区分您要解决的确切问题。您是否要求某人提供完整的解决方案 - 如果没有,请提供该问题的更具体细节,因为它看起来有点像您。从描述对象模型和接口开始,这样人们就可以理解如何引用和调用方法来询问(并可能改变状态)每个Ball
  • @JustinJDavies 当球重叠而不是移开时,它们有点卡住了。这就是问题所在。

标签: c# collision-detection


【解决方案1】:

由于没有明确提出问题,我将假设问题“为什么球会粘在一起?”

您只在源代码中显示了一个循环,这还不够;-) 要检查所有可能的冲突,您需要检查 n*(n-1)/2 个可能的冲突。这通常通过两个循环来完成。您必须采取谨慎措施以避免两次处理相同的碰撞。

您的球卡住的原因是您多次处理相同的碰撞。例如两个完全水平碰撞的球:左边的一个球的速度为 5,x 位置为 100。另一个球的位置为 110,速度为 -6。碰撞发生时:

  1. x 设置为 105。
  2. 检测到碰撞:x 设置为 104,速度设置为 -5。
  3. 另一个 Ball 处理相同的碰撞:
  4. 他根据自己的速度移动到位置 104。
  5. 碰撞处理:他的速度变为 6,位置变为 105。

球分别为 100 和 110。并已移至 104 和 105。虽然速度现在指向彼此背离,但下一步中的碰撞处理将再次反转它们。所以位置很接近,速度每帧都在改变符号。这些球似乎“粘在一起”。

我希望答案能帮助您理解您的问题。为了更好地实现弹性碰撞(每次碰撞只处理一次),请看这里:Ball to Ball Collision - Detection and Handling

【讨论】:

  • 非常感谢。 collision = collision / distance; 在做什么?
  • 碰撞是一个二维向量,距离定义为碰撞的长度。代码将向量标准化为长度正好为 1。
【解决方案2】:

在我第一次尝试碰撞检测算法时偶然发现了类似的问题,我将尝试在这里描述我认为的问题。

也许球移动得足够快,以至于在您的代码甚至检测到碰撞之前,它们已经部分地“在”彼此“内部”。当碰撞检测出现并注意到这一点时,它会做它应该做的事情:根据刚刚发生的碰撞的细节改变物体的计划轨迹。问题是,因为这些对象在碰撞检测捕获它们之前已经“合并”了,所以它们无法解开,因为再次触发碰撞检测,将它们相互困住。

如果这是问题的根源,那么也许上面的代码可以使用足够小的速度向量。当然,这不是一个真正的解决方案,但如果它确实适用于非常小的速度,它可能会证实我的假设,并且您对如何进行有一些想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 2010-10-21
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    相关资源
    最近更新 更多