Canvas圆形碰撞,如何计算出碰撞后圆形应该移动到哪里?

5

我正在尝试使用html canvas构建一款游戏。这是一款空气曲棍球游戏,我已经做得很不错了。游戏中有三个圆形:被击打的圆盘和两个控制器(用于撞击圆盘/圆形)。

我已经让圆盘从墙壁上反弹,并且有一个函数来检测圆盘何时与控制器相撞。我遇到的问题是当两个圆形相撞时,控制器应该保持静止,圆盘应该以正确的方向移动。我已经阅读了一堆文章,但仍然无法搞定。

以下是我的进展代码链接。您可以看到冰球从控制器上反弹,但方向不正确。您还会发现,如果冰球从控制器后面来,它会穿过控制器。 http://codepen.io/allanpope/pen/a01ddb29cbdecef58197c2e829993284?editors=001

我想要的是弹性碰撞,但不确定如何解决。我找到了这篇文章,但未能让它起作用。

http://gamedevelopment.tutsplus.com/tutorials/when-worlds-collide-simulating-circle-circle-collisions--gamedev-769

以下是我的碰撞检测函数。Self指圆盘,controller[i]是圆盘撞击的控制器。

this.discCollision = function() {

        for (var i = 0; i < controllers.length; i++) {
                // Minus the x pos of one disc from the x pos of the other disc
                var distanceX = self.x - controllers[i].x,
                        // Minus the y pos of one disc from the y pos of the other disc
                        distanceY = self.y - controllers[i].y,
                        // Multiply each of the distances by itself
                        // Squareroot that number, which gives you the distance between the two disc's
                        distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY),
                        // Added the two disc radius together
                        addedRadius = self.radius + controllers[i].radius;


                // Check to see if the distance between the two circles is smaller than the added radius
                // If it is then we know the circles are overlapping
                if (distance <= addedRadius) {

                    var newVelocityX = (self.velocityX * (self.mass - controllers[i].mass) + (2 * controllers[i].mass * controllers[i].velocityX)) / (self.mass + controllers[i].mass);
                    var newVelocityY = (self.velocityY * (self.mass - controllers[i].mass) + (2 * controllers[i].mass * controllers[i].velocityX)) / (self.mass + controllers[i].mass);

                    self.velocityX = newVelocityX;
                    self.velocityY = newVelocityY;

                    self.x = self.x + newVelocityX;
                    self.y = self.y + newVelocityY; 

                } 
            }   

    }

更新

拆解了一个圆形碰撞演示并尝试实现他们的碰撞公式。下面是代码,可以向前和向下撞击冰球/圆盘,但出现问题时无法向后或向上撞击。

this.discCollision = function() {

            for (var i = 0; i < controllers.length; i++) {
                    // Minus the x pos of one disc from the x pos of the other disc
                    var distanceX = self.x - controllers[i].x,
                            // Minus the y pos of one disc from the y pos of the other disc
                            distanceY = self.y - controllers[i].y,
                            // Multiply each of the distances by itself
                            // Squareroot that number, which gives you the distance between the two disc's
                            distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY),
                            // Added the two disc radius together
                            addedRadius = self.radius + controllers[i].radius;

                    // Check to see if the distance between the two circles is smaller than the added radius
                    // If it is then we know the circles are overlapping                                
                    if (distance < addedRadius) {

                            var normalX = distanceX / distance,
                                normalY = distanceY / distance,
                                midpointX = (controllers[i].x + self.x) / 2,
                                midpointY = (controllers[i].y + self.y) / 2,
                                delta = ((controllers[i].velocityX - self.velocityX) * normalX) + ((controllers[i].velocityY - self.velocityY) * normalY),
                                deltaX = delta*normalX,
                                deltaY = delta*normalY;

                            // Rebound puck
                            self.x = midpointX + normalX * self.radius;
                            self.y = midpointY + normalY * self.radius;
                            self.velocityX += deltaX;
                            self.velocityY += deltaY;

                            // Accelerate once hit
                            self.accelerationX = 3;
                            self.accelerationY = 3;

                    }
            }

    }

1
新的方向将是两个向量的和。v1 = 球的vx,vy。v2 = 与第二个球边缘垂直且大小等于v1的向量。 - Muhammad Umer
由于控制器是静止的,您可以假设它的质量很大,或者您可以使用不吸收或转移动量而仅重定向的不同公式。 - Muhammad Umer
尝试访问此网站以进行可视化操作:https://phet.colorado.edu/sims/vector-addition/vector-addition_en.html - Muhammad Umer
谢谢Muhammad,我还不完全明白如何计算公式。你提到的“或者你可以使用不考虑动量吸收或转移只是重定向的不同公式。”可能是一个更好的选择,你有任何想法这个公式会是什么样子吗? - Allanp
假设球是一堵墙,角度Q在球上接近墙壁。那么它离开的角度将是左侧墙壁的180-Q。 - Muhammad Umer
2个回答

0

0

我不擅长这类数学问题,但看起来您需要将向量围绕正弦和余弦角度旋转。我会为您指出一个可行的示例和驱动它的源代码。这个示例不是我推导出来的。

我最近解决了这个问题中仅关于圆形碰撞检测的部分,但我找到的一个解决方案包括建立新的向量方向的代码。Ira Greenburg 在 processing.org 上托管他的原始源代码,进一步引用 Keith Peter 的 解决方案在 Foundation Actionscript Animation: Making Things Move! 中。

我将 Ira 的代码复制到 Processing 的 Javascript 模式中,然后将其推送到 Github Pages,以便您在尝试之前可以查看它。


1
谢谢。我也不太擅长这些数学问题,这是我第一次尝试做这样的事情。我看了你的解决方案,但我宁愿避免使用外部库。 - Allanp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接