我们首先来讲一下动画精灵是个什么东西?
我们在之前显示图片时候,都是先把背景色填充,然后再把飞机绘制在屏幕上,最后刷新窗体,这中间就有一个擦除和绘制的过程;我们现在来想象一下,在游戏的时候会有很多的飞机,随着我们现在的机器配置越来越高当然没什么问题,可以很快速的处理很多图片的显示和消失,但是以前的硬件基础并不是很好,这些游戏机就有一些特殊的硬件,专门用来处理需要快速移动的游戏对象,这些对象就称为“动画精灵”。简单的来说,动画精灵就是一次性显示的一组像素,它返回的是一种图形对象,将多个图形作为一个整体显示。
那么,我们需要怎么实现呢?
pygame的sprite模块提供了一个动画精灵的基类——Sprite,一般来讲我们不会直接使用基类,而是基于基类来创建自己的子类使用,接下来我们看一下他是怎么使用的;先来创建一个自己的子类吧:
class PlaneClass(pygame.sprite.Sprite): # 我们基于动画精灵的基类来创建子类
def __init__(self,img,position,speed): # 初始化,一般来讲将需要用到的属性在这里进行初始化操作
pygame.sprite.Sprite.__init__(self) # 初始化动画精灵
self.image = pygame.image.load(img) # 加载飞机图片
self.rect = self.image.get_rect() # 获取图片的rect
self.rect.left,self.rect.top = position # 设置图片的初始位置
self.speed = speed # 设置飞机的速度
def move(self): # 定义飞机移动的方法
self.rect = self.rect.move(self.speed) # 获取飞机移动之后的位置
if self.rect.left < 0 or self.rect.right > width: # 下面就是跟之前一样了,判断是否超出了边界
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
这里来讲一下什么是基类,什么是子类?
基类就是父类,这就好比一个父亲一个儿子,儿子肯定继承了父亲的一部分基因,所以外貌、性格等会与父亲相似,但是儿子毕竟是一个单独的个体,首先属性参数会不一样,其次可能会有其他的属性是父亲所没有的;基类和子类也是一样的道理,我们创建一个类,相当于创建了一个模型,继承了父类的所有属性,但是子类也可以添加自己的属性和方法,当我们这个类创建完毕之后,就可以用这个类创建对象了,这个对象就具有了这个类的所有属性和方法了。
以上面的代码来说,创建了一个PlaneClass类,继承了pygame.sprire.Sprite的属性,我们在初始话的时候,self就代表它本身所具有的属性,然后将参数设置上去;在下面move就是我们自己定义的方法,这个就是基类所不具备的,就像父亲不会英语,儿子会一样;
airplanes = [] # 创建列表,用来存放创建的飞机
for i in range(4):
img_position = [i*100,10] # 设置飞机的初始位置
speed = [choice([-2,2]),choice([-2,2])] # 让他们的速度都随机
airplane = PlaneClass('./images/me1.png',img_position,speed) # 基于类创建飞机
airplanes.append(airplane) # 将飞机放到列表中
clock = pygame.time.Clock() # 创建一个clock对象,用来控制游戏每秒的帧数
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill(bg)
for each in airplanes: # 遍历类,将每个飞机都显示出来
each.move() # 移动并检测边界
screen.blit(each.image,each.rect) # 将飞机绘制到界面上
pygame.display.flip() # 刷新游戏界面
clock.tick(60) # 设置游戏每秒60帧

好了,我们现在已经知道怎么用动画精灵创建一组飞机了,我们会发现飞机在移动的时候会产生重叠,当然友方飞机问题不大,但是是敌方飞机,或者我们想要他们产生一个碰撞效果,该怎么处理呢?
imgs = ['./images/me1.png','./images/enemy1.png','./images/enemy2.png']
group = pygame.sprite.Group() # 创建一个组,之前我们是创建一个列表,然后把生成的飞机添加到列表里面的 ,现在我们存放在这个组里面
for i in range(3):
img_position = [i*200,10]
speed = [choice([-2,2]),choice([-2,2])]
airplane = PlaneClass(imgs[i],img_position,speed)
group.add(airplane) # 其余的,没有太大的变化,就是添加到组
def collide_check(group): # 定义一个方法,检查同组的飞机有没有发生碰撞
for plane in group: # 我们先遍历将每个飞机的位置发生改变
plane.move()
for plane in group:
group.remove(plane) # 首先先将这个飞机移除出组
if pygame.sprite.spritecollide(plane,group,False,pygame.sprite.collide_mask): # 然后检测是否发生碰撞
plane.speed[0] = -plane.speed[0]
plane.speed[1] = -plane.speed[1]
group.add(plane) # 然后再把飞机添加回来
screen.blit(plane.image,plane.rect) # 最后绘制飞机到界面上
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill(bg)
collide_check(group) # 调用方法,将组内的飞机移动、检测并显示
pygame.display.flip()
clock.tick(60)
这里需要说的是几个方法的使用:
- pygame.sprite.Group.add()方法添加动画精灵到组当中;
- pygame.sprite.Group.remove()方法从组当中移除某一个动画精灵;
- pygame.sprite.spritecollide()方法用来检测某个动画精灵组中的动画精灵是否发生碰撞;

- pygame.sprite.collide_mask是pygame提供的一个图像蒙版模块,用来返回图像的轮廓,为什么需要这个呢?我们可以将上面代码中pygame.sprite.spritecollide()的第四个参数删掉,会发现飞机并没有发生完全重叠就发生碰撞了,这是因为默认碰撞检测的是图像的矩形部分,矩形部分产生重叠,就认为发生了碰撞,这样显然是有问题的,所以我们需要将其轮廓显示出来,然后再进行判断;

完整代码如下:
import pygame
import sys
from random import *
from pygame.locals import *
class PlaneClass(pygame.sprite.Sprite):
def __init__(self,img,position,speed):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(img)
self.rect = self.image.get_rect()
self.rect.left,self.rect.top = position
self.speed = speed
def move(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > height:
self.speed[1] = -self.speed[1]
def collide_check(group):
for plane in group:
plane.move()
for plane in group:
group.remove(plane)
if pygame.sprite.spritecollide(plane,group,False,pygame.sprite.collide_mask):
plane.speed[0] = -plane.speed[0]
plane.speed[1] = -plane.speed[1]
group.add(plane)
screen.blit(plane.image,plane.rect)
pygame.init()
screen_size = width,height = 480,700
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption('飞机大战')
bg = (0,255,0)
imgs = ['./images/me1.png','./images/enemy1.png','./images/enemy2.png']
group = pygame.sprite.Group()
for i in range(3):
img_position = [i*200,10]
speed = [choice([-2,2]),choice([-2,2])]
airplane = PlaneClass(imgs[i],img_position,speed)
group.add(airplane)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill(bg)
collide_check(group)
pygame.display.flip()
clock.tick(60)
本文详细讲解了在游戏开发中如何使用Pygame的动画精灵(Sprite)模块创建动态对象,包括创建自定义动画精灵类、实现移动与边界检测,并通过组(Group)管理多个动画精灵,以及如何实现碰撞检测,确保游戏中的飞机不会重叠。
——用动画精灵创建一组飞机,并检测碰撞&spm=1001.2101.3001.5002&articleId=103435649&d=1&t=3&u=8225372aa3c24072a56a52029ceaa39f)
924

被折叠的 条评论
为什么被折叠?



