Pygame碰撞检测
Posted GraceSkyer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pygame碰撞检测相关的知识,希望对你有一定的参考价值。
学习自小甲鱼视频教学(笔记)
功能实现:
在随机位置生成若干个小球以随机速度运动;
若小球运动出左边界则从右边界进入,上下边界同理;
若两小球相碰撞则都以相反速度运动分开。
代码如下:
1.尝试自己写碰撞检测函数(对比两球之间的圆心距离和半径即可)。
1 import pygame 2 import sys 3 import math 4 from pygame.locals import * 5 from random import * 6 7 8 # 面向对象的编程方法,定义一个球的类型 9 class Ball(pygame.sprite.Sprite): 10 def __init__(self, image, position, speed, bg_size): 11 # 初始化动画精灵 12 pygame.sprite.Sprite.__init__(self) 13 14 self.image = pygame.image.load(image).convert_alpha() 15 self.rect = self.image.get_rect() 16 # 将小球放在指定位置 17 self.rect.left, self.rect.top = position 18 self.speed = speed 19 self.width, self.height = bg_size[0], bg_size[1] 20 21 # 定义一个移动的方法 22 def move(self): 23 self.rect = self.rect.move(self.speed) 24 # 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界 25 # 这样便实现了从左边进入,右边出来的效果 26 if self.rect.right < 0: 27 self.rect.left = self.width 28 if self.rect.left > self.width: 29 self.rect.right = 0 30 if self.rect.bottom < 0: 31 self.rect.top = self.height 32 if self.rect.top > self.height: 33 self.rect.bottom = 0 34 35 36 def collide_check(item, target): 37 col_balls = [] 38 for each in target: 39 distance = math.sqrt( 40 math.pow((item.rect.center[0] - each.rect.center[0]), 2) + 41 math.pow((item.rect.center[1] - each.rect.center[1]), 2)) 42 if distance <= (item.rect.width + each.rect.width) / 2: 43 col_balls.append(each) 44 45 return col_balls 46 47 48 def main(): 49 pygame.init() 50 51 ball_image = \'ball.png\' 52 bg_image = \'background.png\' 53 running = True 54 55 # 根据背景图片指定游戏界面尺寸 56 bg_size = width, height = 1024, 500 57 screen = pygame.display.set_mode(bg_size) 58 pygame.display.set_caption(\'Collision Spheres\') 59 60 background = pygame.image.load(bg_image).convert_alpha() 61 62 # 用来存放小球对象的列表 63 balls = [] 64 65 # 创建6个位置随机,速度随机的小球 66 BALL_NUM = 6 67 for i in range(BALL_NUM): 68 position = randint(0, width - 70), randint(0, height - 70) 69 speed = [randint(1, 6), randint(1, 6)] 70 ball = Ball(ball_image, position, speed, bg_size) 71 while collide_check(ball, balls): 72 ball.rect.left, ball.rect.top = randint(0, width - 70), randint(0, height - 70) 73 74 balls.append(ball) 75 76 clock = pygame.time.Clock() 77 78 while running: 79 for event in pygame.event.get(): 80 if event.type == QUIT: 81 sys.exit() 82 83 screen.blit(background, (0, 0)) 84 85 for each in balls: 86 each.move() 87 screen.blit(each.image, each.rect) 88 89 for i in range(BALL_NUM): 90 item = balls.pop(i) 91 92 if collide_check(item, balls): 93 item.speed[0] = -item.speed[0] 94 item.speed[1] = -item.speed[1] 95 96 balls.insert(i, item) 97 98 pygame.display.flip() 99 clock.tick(60) 100 101 102 if __name__ == \'__main__\': 103 main()
2.使用sprite模块提供的碰撞检测函数。
sprite 模块提供了一个 spritecollide() 函数,用于检测某个精灵是否与指定组中的其他精灵发生碰撞。
spritecollide(sprite, group, dokill, collided = None)
第一个参数指定被检测的精灵
第二个参数指定一个组,由 sprite.Group() 生成
第三个参数设置是否从组中删除检测到碰撞的精灵
第四个参数设置一个回调函数,用于定制特殊的检测方法。如果该参数忽略,那么默认是检测精灵之间的 rect 是否产生重叠。
注意:
实现圆形的碰撞检测,我们还需要指定 spritecollide() 函数的最后一个参数。
sprite 模块中正好有一个 collide_circle() 函数用于检测两个圆之间是否发生碰撞...
这个函数需要你的精灵对象中必须有一个 radius(半径)属性才行。
1 import pygame 2 import sys 3 from pygame.locals import * 4 from random import * 5 6 # 面向对象的编程方法,定义一个球的类型 7 class Ball(pygame.sprite.Sprite): 8 def __init__(self, image, position, speed, bg_size): 9 # 初始化动画精灵 10 pygame.sprite.Sprite.__init__(self) 11 12 self.image = pygame.image.load(image).convert_alpha() 13 self.rect = self.image.get_rect() 14 # 将小球放在指定位置 15 self.rect.left, self.rect.top = position 16 self.speed = speed 17 self.width, self.height = bg_size[0], bg_size[1] 18 self.radius = self.rect.width / 2 19 20 # 定义一个移动的方法 21 def move(self): 22 self.rect = self.rect.move(self.speed) 23 # 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界 24 # 这样便实现了从左边进入,右边出来的效果 25 if self.rect.right < 0: 26 self.rect.left = self.width 27 if self.rect.left > self.width: 28 self.rect.right = 0 29 if self.rect.bottom < 0: 30 self.rect.top = self.height 31 if self.rect.top > self.height: 32 self.rect.bottom = 0 33 34 35 def main(): 36 pygame.init() 37 38 ball_image = \'ball.png\' 39 bg_image = \'background.png\' 40 running = True 41 42 # 根据背景图片指定游戏界面尺寸 43 bg_size = width, height = 1024, 500 44 screen = pygame.display.set_mode(bg_size) 45 pygame.display.set_caption(\'Collision Spheres\') 46 47 background = pygame.image.load(bg_image).convert_alpha() 48 49 # 用来存放小球对象的列表 50 balls = [] 51 group = pygame.sprite.Group() 52 53 # 创建6个位置随机,速度随机的小球 54 BALL_NUM = 6 55 for i in range(BALL_NUM): 56 position = randint(0, width - 70), randint(0, height - 70) 57 speed = [randint(1, 6), randint(1, 6)] 58 ball = Ball(ball_image, position, speed, bg_size) 59 while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle): 60 ball.rect.left, ball.rect.top = randint(0, width - 70), randint(0, height - 70) 61 balls.append(ball) 62 group.add(ball) 63 64 clock = pygame.time.Clock() 65 66 while running: 67 for event in pygame.event.get(): 68 if event.type == QUIT: 69 sys.exit() 70 71 screen.blit(background, (0, 0)) 72 73 for each in balls: 74 each.move() 75 screen.blit(each.image, each.rect) 76 77 for each in group: 78 group.remove(each) 79 80 if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle): 81 each.speed[0] = -each.speed[0] 82 each.speed[1] = -each.speed[1] 83 84 group.add(each) 85 86 pygame.display.flip() 87 clock.tick(60) 88 89 90 if __name__ == \'__main__\': 91 main()
本演示图片素材下载:https://files.cnblogs.com/files/GraceSkyer/20180203.zip
以上是关于Pygame碰撞检测的主要内容,如果未能解决你的问题,请参考以下文章
pygame.mask原理及使用pygame.mask实现精准碰撞检测