我编写了一个动画(在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()
答案 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 collisions,inelastic collisions和coefficients 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格式的声明,以确保碰撞检测完美无瑕。我希望这会有所帮助。