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

2024-09-28 23:13:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我用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()

Tags: rectimageimportselfeventgetifrandom
3条回答

检测碰撞只是第一步。让我们把它分解。

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

现在,当它们重叠时,你需要计算它们之间的距离。如果这个距离大于球半径的和,那么就没有碰撞。

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

首先是它们的弹性。两个橡胶球互相弹跳的反弹方式不同于两个玻璃球。

第二个是它们的初始速度。惯性是指他们希望继续沿着他们开始的方向前进。

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

我们先来处理第二和第三个因素,因为它们是相互交织的。

两个球很少会完全击中。斜视打击的可能性要大得多。在任何情况下,碰撞都会沿着球碰撞的切线的法线发生。考虑到它们的初始速度,你需要计算它们沿这个法线的矢量分量。这将产生一对法向速度,这两个球将导致碰撞。把总数加起来,放在方便的地方。

现在我们得弄清楚每一个球会从中拿走什么。得到的每个球的法向速度与给定球的质量成反比。也就是说,取每个球质量的倒数,把两个质量加在一起,然后根据球质量与两个球质量倒数之和的比率,将碰撞产生的法向速度包裹起来。然后加上切向速度,得到球的合成速度。

弹性基本上是一样的,只是它需要一些基本的微积分,因为球在压缩时仍然在运动。我把它留给你去查相关的数学。

探测碰撞被Pax's answer很好地覆盖了。关于让对象相互跳转,我建议查看以下关于elastic collisionsinelastic collisionscoefficients of restitution的链接。

编辑:我刚刚注意到这在another SO question中有涉及,尽管不是专门针对Python的。你也应该检查那里的一些好的链接。

任意形状的碰撞检测通常非常棘手,因为您必须找出是否有任何像素发生碰撞。

用圆圈其实更容易。如果有半径为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)随时间变化的速率)时会遇到棘手的问题,因为需要考虑当前的运动矢量和接触点。

我认为,作为第一个切入点,您应该反转运动向量,以测试碰撞检测是否首先起作用。

然后再问另一个问题——最好把个别问题具体化,这样答案才有针对性。

相关问题 更多 >