如何为弹跳球创建碰撞检测?

时间:2009-04-23 03:13:56

标签: python collision-detection

我编写了一个动画(在python中),用于三个沙滩球在屏幕上反弹。我现在希望让它们全部碰撞,并能够互相反弹。我真的很感激可以提供任何帮助。

import pygame
import random
import sys
class Ball:


    def __init__(self,X,Y):

        self.velocity = [1,1]
        self.ball_image = pygame.image.load ('Beachball.jpg'). convert()
        self.ball_boundary = self.ball_image.get_rect (center=(X,Y))
        self.sound = pygame.mixer.Sound ('Thump.wav')
        self.rect = self.ball_image.get_rect (center=(X,Y))

if __name__ =='__main__':

    width = 800
    height = 600
    background_colour = 0,0,0
    pygame.init()
    window = pygame.display.set_mode((width, height))
    pygame.display.set_caption("Bouncing Ball animation")
    num_balls = 3
    ball_list = []
    for number in range(num_balls):
        ball_list.append( Ball(random.randint(10, (width - 10)),random.randint(10, (height - 10))) )
    while True:
        for event in pygame.event.get():
                print event 
                if event.type == pygame.QUIT:
                        sys.exit(0)
        window.fill (background_colour)

        for ball in ball_list:
                if ball.ball_boundary.left < 0 or ball.ball_boundary.right > width:
                        ball.sound.play()
                        ball.velocity[0] = -1 * ball.velocity[0]
                if ball.ball_boundary.top < 0 or ball.ball_boundary.bottom > height:
                        ball.sound.play()
                        ball.velocity[1] = -1 * ball.velocity[1]

                ball.ball_boundary = ball.ball_boundary.move (ball.velocity)
                window.blit (ball.ball_image, ball.ball_boundary)
        pygame.display.flip()

7 个答案:

答案 0 :(得分:10)

任意形状的碰撞检测通常非常棘手,因为你必须弄清楚是否有任何像素碰撞。

圈子实际上更容易。如果您有两个半径为r1和r2的圆,则如果中心之间的距离小于r1 + r2,则会发生碰撞。

可以计算两个中心(x1,y1)和(x2,y2)之间的距离,并将其比较为:

d = sqrt((y2-y1) * (y2-y1) + (x2-x1) * (x2-x1));
if (d < r1 + r2) { ... bang ... }

或者,正如jfclavette指出的那样,平方根价格昂贵,所以用简单的操作计算可能更好:

dsqrd = (y2-y1) * (y2-y1) + (x2-x1) * (x2-x1);
if (dsqrd < (r1+r2)*(r1+r2)) { ... bang ... }

计算新的运动矢量(给定物体的(x,y)随时间变化的速率),因为你需要考虑当前的运动矢量和接触点,这一点非常棘手。

我认为作为第一次切割,您应该反转运动矢量以测试碰撞检测是否先工作。

然后提出另一个问题 - 最好将个别问题保持特定,以便能够找到答案。

答案 1 :(得分:3)

检测碰撞只是第一步。让我们打破它。

最快的事情是计算它们的方形边界框,看看它们是否发生碰撞。两个侧面需要交叉(1的顶部和底部或2,左边的1和2的右边,或反之亦然),以便边界框重叠。没有重叠,没有碰撞。

现在,当他们重叠时,您需要计算它们之间的距离。如果此距离大于球的半径之和,则不会发生碰撞。

好!我们有两个球相撞。 现在什么?好吧,他们必须互相反弹。他们反弹的方式取决于几个因素。

首先是他们的弹性。两个相互反弹的橡胶球比两个玻璃球反弹不同。

第二个是他们的初始速度。惯性表明,他们希望继续保持与他们开始时大致相同的方向。

第三是球的质量。质量较小的球会以更高的速度从更大的质量上反弹。

让我们首先处理第二和第三因素,因为它们是交织在一起的。

两个球很少会完全死亡。掠夺打击的可能性更大。在任何情况下,撞击都会发生在球碰撞的切线的法线上。在初始速度给定时,您需要计算两者的矢量分量。这将导致两个球将导致碰撞的一对正常速度。将总和相加并存放在方便的地方。

现在我们必须弄清楚每个球会从中拿走什么。每个球的最终正常速度与给定球的质量成反比。也就是说,取每个球的质量的倒数,将两个质量加在一起,然后根据球的质量与两个球质量的倒数之和的比率,将所得的法向速度远离碰撞。然后将切向速度加到此处,然后得到球的合成速度。

弹性大致相同,除了它需要一些基本的微积分,因为球在压缩时仍然在移动。我会留给你找相关的数学。

答案 2 :(得分:1)

Pax's answer完全涵盖了检测碰撞的问题。关于让对象互相反弹,我建议您查看以下有关elastic collisionsinelastic collisionscoefficients of restitution的链接。

编辑:我刚注意到another SO question中有这个内容,虽然不是专门针对Python的。您还应该在那里查看一些良好的链接。

答案 3 :(得分:1)

我认为有些事情比较简单,因为他们正在使用pygame,你们很遗憾。

调用get_rect函数可以设置图像的可能边界,并创建Rect,用于计算图像的位置,如果动画中有多个对象,则可用于检测碰撞。

colliderect&amp;可以使用rect,问题是我不知道你将如何实现它,尤其是对于未知数量的球。

记住这是蟒蛇。

答案 4 :(得分:0)

回到过去很久以前,CPU周期是高级编码器使用一个简单的技巧来检测碰撞:他们使用了这些颜色,如果它是背景或物体,他们可以从像素颜色中辨别出来。这至少在一些C64游戏中完成。

不知道你是否愿意走这条路线。

答案 5 :(得分:0)

首先,您需要检查与rect.colliderect(other_rect)

的碰撞

之后如果它们发生碰撞,你可以检查像素完美碰撞。所以你不要弄乱对象的半径或形状。

对于像素完美碰撞检查,我使用Masks: 使用mask.from_surface创建两个蒙版对象,然后将它们放到Mask.overlap函数中。

答案 6 :(得分:0)

我做了一个python碰撞检测if语句,这里是:

genderize.io

在你的情况下,使用3个弹跳球,你必须为每个球制作2个if格式的声明,以确保碰撞检测完美无瑕。我希望这会有所帮助。