当子弹和敌机碰撞,我们并不想仅将飞机和子弹消失,应该在其发生碰撞的位置播放一组爆炸动画,播放爆炸音效,游戏效果更为逼真一些。
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 版本的飞机大战开发完毕,希望同学们通过这个案例能有所收获。