当子弹和敌机碰撞,我们并不想仅将飞机和子弹消失,应该在其发生碰撞的位置播放一组爆炸动画,播放爆炸音效,游戏效果更为逼真一些。
1. Bomb 类
爆炸动画实现思路很简单,我们将一组图片按照一定的时间间隔,将其按顺序绘制到屏幕上,即可显示为动画效果。

class Bomb:
def __init__(self, scene):
# 加载爆炸素材
self.images = [ pygame.image.load(f'source/bomb/bomb-{index + 1}.png') for index in range(7)]
# 爆炸位置
self.position = [0, 0]
# 帧播放间隔
self.interval = 5
self.interval_index = 0
# 当前绘制的图像
self.draw_index = 0
# 爆炸是否可见
self.visible = False
# 持有场景对象
self.scene = scene
def set_used(self, start_x, start_y):
self.visible = True
self.draw_index = 0
self.position[0] = start_x
self.position[1] = start_y
def set_unused(self):
self.visible = False
self.draw_index = 0
self.position[0] = -1000
self.position[1] = -1000
def switch_frame(self):
if not self.visible:
return
self.interval_index += 1
if self.interval_index < self.interval:
return
self.interval_index = 0
self.draw_index += 1
if self.draw_index >= len(self.images):
self.set_unused()
def draw_element(self):
if not self.visible:
return
self.scene.blit(self.images[self.draw_index], self.position)
测试 Bomb 类:
if __name__ == '__main__':
pygame.init()
window = pygame.display.set_mode([512, 768])
clock = pygame.time.Clock()
# 初始化爆炸对象
bomb = Bomb(window)
bomb.set_used(200, 450)
while True:
window.fill((0, 0, 0))
# 切换爆炸图片
bomb.switch_frame()
# 绘制爆炸图片
bomb.draw_element()
if not bomb.visible:
bomb.set_used(200, 450)
pygame.event.get()
pygame.display.update()
clock.tick(60)
2. 敌机爆炸动画
当敌机被击中时,我们会调用敌机的 set_unused 函数,此时我们就启动爆炸动画的播放。
class EnemyPlane:
def __init__(self, scene, speed=10):
# 游戏主场景
self.scene = scene
# 敌机资源
self.image = pygame.image.load(f'source/plane/enemy-{random.randint(1, 7)}.png')
# 敌机边框
self.bbox = self.image.get_rect()
# 移动速度
self.speed = speed
# 是否可见
self.visible = False
# 初始化子弹
self.bullet = Bullet(scene, is_enemy=True)
# -----------爆炸效果----------
# 初始化爆炸
self.bomb = Bomb(self.scene)
# ----------------------------
def set_used(self, start_x, start_y):
self.bbox[0] = start_x
self.bbox[1] = start_y
self.speed = random.randint(4, 8)
self.visible = True
def calc_position(self):
# 计算飞机位置
if self.visible:
self.bbox.move_ip(0, self.speed)
if self.bbox[1] > SCENE_H:
self.set_unused()
# 计算子弹位置
if self.bullet.visible:
self.bullet.move(0, self.speed + 5)
# -----------爆炸效果----------
# 切换爆炸帧
self.bomb.switch_frame()
# ----------------------------
def draw_element(self):
# 绘制飞机
if self.visible:
self.scene.blit(self.image, self.bbox)
# 绘制子弹
if self.bullet.visible:
self.bullet.draw_element()
# -----------爆炸效果----------
# 绘制爆炸图片
self.bomb.draw_element()
# ----------------------------
def set_unused(self):
self.visible = False
self.bbox[0] = -1000
self.bbox[1] = -1000
def shoot(self):
if self.bullet.visible:
return
start_x = self.bbox[0] + self.bbox[2]/2 - self.bullet.bbox[2]/2
start_y = self.bbox[1] + self.bbox[3] - 10
self.bullet.set_used(start_x, start_y)
接下来,在碰撞检测适当的位置调用 Bomb 对象的 set_used 方法即可实现。
3. 爆炸音效和背景音乐
首先,在 Bomb 类的 init 方法中初始化爆炸音效:
class Bomb:
def __init__(self, scene):
...
# 加载爆炸音效
self.sound = pygame.mixer.Sound('source/music/bomb.wav')
self.sound.set_volume(0.1)
在 Bomb 类的 set_used 函数中播放爆炸音效,如下代码:
def set_used(self, start_x, start_y):
...
# 播放爆炸音效
self.sound.play()
接下来,添加游戏背景音乐。在 MainScene 的 init 方法中加载背景音乐并设置循环播放,如下:
class MainScene:
# 初始化主场景
def __init__(self):
...
# 游戏背景音乐
pygame.mixer.music.load('source/music/bg.wav')
pygame.mixer.music.set_volume(0.05)
pygame.mixer.music.play(-1)
至此,我们 v1.0 版本的飞机大战开发完毕,希望同学们通过这个案例能有所收获。


冀公网安备13050302001966号