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()
View Code

 

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()
View Code

 

 

本演示图片素材下载:https://files.cnblogs.com/files/GraceSkyer/20180203.zip

 

以上是关于Pygame碰撞检测的主要内容,如果未能解决你的问题,请参考以下文章

Pygame碰撞检测

Pygame中图像和矩形之间的碰撞检测?

pygame碰撞检测函数python3中的语法错误[重复]

pygame.mask原理及使用pygame.mask实现精准碰撞检测

pygame.mask原理及使用pygame.mask实现精准碰撞检测

pygame.mask原理及使用pygame.mask实现精准碰撞检测