我用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()
检测碰撞只是第一步。让我们把它分解。
最快的方法是计算它们的方形边界框,看看它们是否碰撞。两个边需要交叉(1的顶部和底部或2,1的左侧和2的右侧,或反之亦然),以便边界框重叠。没有重叠,没有碰撞。
现在,当它们重叠时,你需要计算它们之间的距离。如果这个距离大于球半径的和,那么就没有碰撞。
好吧!我们有两个球相撞。现在什么?好吧,他们必须互相击退。它们反弹的方式取决于几个因素。
首先是它们的弹性。两个橡胶球互相弹跳的反弹方式不同于两个玻璃球。
第二个是它们的初始速度。惯性是指他们希望继续沿着他们开始的方向前进。
第三个是球的质量。质量较小的球会以较高的速度从质量大得多的球上反弹。
我们先来处理第二和第三个因素,因为它们是相互交织的。
两个球很少会完全击中。斜视打击的可能性要大得多。在任何情况下,碰撞都会沿着球碰撞的切线的法线发生。考虑到它们的初始速度,你需要计算它们沿这个法线的矢量分量。这将产生一对法向速度,这两个球将导致碰撞。把总数加起来,放在方便的地方。
现在我们得弄清楚每一个球会从中拿走什么。得到的每个球的法向速度与给定球的质量成反比。也就是说,取每个球质量的倒数,把两个质量加在一起,然后根据球质量与两个球质量倒数之和的比率,将碰撞产生的法向速度包裹起来。然后加上切向速度,得到球的合成速度。
弹性基本上是一样的,只是它需要一些基本的微积分,因为球在压缩时仍然在运动。我把它留给你去查相关的数学。
探测碰撞被Pax's answer很好地覆盖了。关于让对象相互跳转,我建议查看以下关于elastic collisions、inelastic collisions和coefficients of restitution的链接。
编辑:我刚刚注意到这在another SO question中有涉及,尽管不是专门针对Python的。你也应该检查那里的一些好的链接。
任意形状的碰撞检测通常非常棘手,因为您必须找出是否有任何像素发生碰撞。
用圆圈其实更容易。如果有半径为r1和r2的两个圆,则如果中心之间的距离小于r1+r2,则会发生碰撞。
两个中心(x1,y1)和(x2,y2)之间的距离可以计算并比较为:
或者,正如jfclavette所指出的,平方根是昂贵的,所以最好使用简单的运算来计算:
计算新的运动矢量(给定对象的(x,y)随时间变化的速率)时会遇到棘手的问题,因为需要考虑当前的运动矢量和接触点。
我认为,作为第一个切入点,您应该反转运动向量,以测试碰撞检测是否首先起作用。
然后再问另一个问题——最好把个别问题具体化,这样答案才有针对性。
相关问题 更多 >
编程相关推荐