这里写目录标题
- 碰撞检测
- 使用spritecollide()碰撞检测
碰撞检测
碰撞之后会反方向移动,方向和速度都取反
import pygame
import sys # 退出游戏需要
import math # 数学公式需要
from pygame.locals import * # 把pygame的常量名导进去
from random import * # 随机生成数需要
class Ball(pygame.sprite.Sprite): # 定义一个球类,继承动画精灵基类
"""小球的属性"""
def __init__(self, image, position, speed, bg_size):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image).convert_alpha() # 加载图像
self.rect = self.image.get_rect() # 获取图像矩形
self.rect.left, self.rect.top = position # 获取图像位置
self.speed = speed # 速度
self.width, self.height = bg_size[0], bg_size[1] # 窗口宽高
"""小球的移动"""
def move(self):
self.rect = self.rect.move(self.speed) # 移动球所在矩形
"""实现小球从某侧出界,从对侧进来"""
if self.rect.right < 0: # 小球右边小于左边窗口边界,即从左边出去了
self.rect.left = self.width # 屏幕右边出来
elif self.rect.left > self.width: # 小球左边大于右边窗口边界,即从右边出去了
self.rect.right = 0 # 屏幕左边出来
elif self.rect.bottom < 0: # 小球底部坐标小于0,即从上边出去了
self.rect.top = self.height # 屏幕下边出来
elif self.rect.top > self.height: # 小球顶部坐标大于屏幕高,即从下边出去了
self.rect.bottom = 0 # 屏幕上边出来
def collide_check(item, target): # item是取出的一个小球,target是小球集合五个
"""碰撞检测"""
col_balls = [] # 建立一个收集碰撞的球的空列表
for each in target:
distance = math.sqrt(
math.pow((item.rect.center[0]-each.rect.center[0]), 2) +
math.pow((item.rect.center[0]-each.rect.center[0]), 2)
) # 求两点之间的距离
if distance <= (item.rect.width + each.rect.width) / 2:
# 距离小于两个球半径相加
col_balls.append(each)
return col_balls
def main(): # 主函数
pygame.init() # 初始化,游戏开始都需要的
ball_image = "gray_ball.png" # 灰球图像
bg_image = "background.png" # 背景图片,图片上有五个黑球
running = True # 初试running为True
bg_size = width, height = 1024, 681 # 窗口尺寸,也是背景的尺寸大小
screen = pygame.display.set_mode(bg_size) # 绘制窗口
pygame.display.set_caption("玩个球") # 窗口名
background = pygame.image.load(bg_image).convert_alpha() # 加载背景图片进去
balls = [] # 球列表,初始空列表
# 创建五个小球
BALL_NUM = 5
for i in range(BALL_NUM): # 遍历0到4即五个小球
# position = (left, top) 左边和上边的坐标
position = randint(0, width-100), randint(0, height-100) # 随机生成球的坐标,球大小是100×100
speed = [randint(-10, 10), randint(-10, 10)] # 球速度随机-10到10
ball = Ball(ball_image, position, speed, bg_size) # 实例化上面的Ball类,建立一个小球,循环五次就建立了五个
while collide_check(ball, balls): # 如果刚开始就碰撞了
ball.rect.left, ball.rect.top = randint(0, width-100), randint(0, height-100) # 重新初试位置
balls.append(ball) # 添加球到球列表,循环五次就添加了五个
clock = pygame.time.Clock() # 设置帧率需要用到
while running: # 主循环
for event in pygame.event.get(): # 遍历事件
if event.type == QUIT: # ×掉窗口
sys.exit() # 退出游戏
screen.blit(background, (0, 0)) # 更新图像和位置
for each in balls: # 遍历球类里面的各个球
each.move() # 各自移动
screen.blit(each.image, each.rect) # 更新每个球和球矩形位置
for i in range(BALL_NUM): # 检测碰撞
item = balls.pop(i) # 先取出来小球
if collide_check(item, balls): # 如果碰撞
item.speed[0] = -item.speed[0] # 速度取反
item.speed[1] = -item.speed[1]
balls.insert(i, item) # 取出来的放回去
pygame.display.flip() # 刷新界面,相当于游戏结束都需要的
clock.tick(30) # 这里设置帧率
if __name__ == "__main__":
main()
使用spritecollide()碰撞检测
spritecollide(sprite, group, dokill, collided = None)
第一个参数 sprite 是指定被检测的精灵;(就是我们写的里面的 item)
第二个参数 group 是指定一个组(就是我们写的里面的 target 列表),它是 sprite 的组,因此要使用 sprite.Group() 来生成;
第三个参数 dokill 是设置是否从组中删除检测到碰撞的精灵,设置为True,则删除;
第四个参数 collided 是指定一个回调函数,用于定制特殊的检测方法,如果第四个参数忽略的话,默认是检测精灵之间的 rect 属性。
import pygame
import sys # 退出需要
from pygame.locals import * # 把pygame的常量名导进去
from random import * # 随机生成数需要
# 球类继承自Spirte类
class Ball(pygame.sprite.Sprite):
def __init__(self, image, position, speed, bg_size):
# 初始化动画精灵
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image).convert_alpha()
self.rect = self.image.get_rect()
# 将小球放在指定位置
self.rect.left, self.rect.top = position # 小球的左边和上边
self.speed = speed
self.width, self.height = bg_size[0], bg_size[1] # 窗口的宽高
self.radius = self.rect.width / 2 # 增加半径属性
def move(self):
self.rect = self.rect.move(self.speed)
# 如果小球的左侧出了边界,那么将小球左侧的位置改为右侧的边界
# 这样便实现了从左边进入,右边出来的效果
if self.rect.right < 0:
self.rect.left = self.width
elif self.rect.left > self.width:
self.rect.right = 0
elif self.rect.bottom < 0:
self.rect.top = self.height
elif self.rect.top > self.height:
self.rect.bottom = 0
def main():
pygame.init()
ball_image = "gray_ball.png"
bg_image = "background.png"
running = True
# 根据背景图片指定游戏界面尺寸
bg_size = width, height = 1024, 681
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("小游戏")
background = pygame.image.load(bg_image).convert_alpha()
# 用来存放小球对象的列表
balls = []
group = pygame.sprite.Group()
# 创建五个小球
for i in range(5):
# 位置随机,速度随机
position = randint(0, width - 100), randint(0, height - 100) # 随机生成位置
speed = [randint(-10, 10), randint(-10, 10)] # 随机生成速度
ball = Ball(ball_image, position, speed, bg_size) # 实例化小球
while pygame.sprite.spritecollide(ball, group, False, pygame.sprite.collide_circle): # 在创建小球这里必须进行一下碰撞检测
ball.rect.left, ball.rect.top = randint(0, width - 100), randint(0, height - 100) # 随机生成的小球碰撞了就在随机生成位置
balls.append(ball) # 列表用append
group.add(ball) # 集合用add
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
screen.blit(background, (0, 0))
for each in balls:
each.move()
screen.blit(each.image, each.rect)
for each in group:
group.remove(each) # 把自身拿出来
if pygame.sprite.spritecollide(each, group, False, pygame.sprite.collide_circle): # 把自己和别的球进行碰撞检测
each.speed[0] = -each.speed[0]
each.speed[1] = -each.speed[1]
group.add(each) # 还要把自己放进去
pygame.display.flip()
clock.tick(30)
if __name__ == "__main__":
main()