在之前完成了飞机大战整个项目以后就想提升一下,所以萌生出了做双人模式的想法。
那么在单人模式的基础上重写一个HeroB,我们将一号玩家称为HeroA
class HeroB(Plane): """英雄飞机类""" def __init__(self, *groups): """构造方法 :param groups: 要添加的精灵组 """ super().__init__(1000, 5, 0, "me_down.wav", ["me%d.png" % i for i in range(1, 3)], "me1.png", ["me_destroy_%d.png" % i for i in range(1, 5)], *groups) self.is_power = False # 无敌判断标记 self.bomb_count = HERO_BOMB_COUNT # 炸弹数量 self.bullets_kind = 0 # 子弹类型 self.bullets_group = pygame.sprite.Group() # 子弹精灵组 # 初始位置 self.rect.midbottom = HERO_DEFAULT_MID_BOTTOM # 设置发射子弹定时器事件 pygame.time.set_timer(HERO_FIRE_EVENT, 40) def update(self, *args): """更新英雄飞机的图像及矩形区域 :param args: 0 更新图像标记, 1 水平移动基数, 2 垂直移动基数 """ # 调用父类方法更新飞机图像 - 注意 args需要解包 super().update(*args) # 限定在游戏窗口内部移动 self.rect.x = 0 if self.rect.x < 0 else self.rect.x if self.rect.right > SCREEN_RECT.right: self.rect.right = SCREEN_RECT.right self.rect.y = 0 if self.rect.y < 0 else self.rect.y if self.rect.bottom > SCREEN_RECT.bottom: self.rect.bottom = SCREEN_RECT.bottom def blowup(self, enemies_group): """引爆炸弹 :param enemies_group: 敌机精灵组 :return: 累计得分 """ # 如果没有足够数量的炸弹或者英雄飞机被摧毁,直接返回 if self.bomb_count <= 0 or self.hp <= 0: return 0 self.bomb_count -= 1 # 炸弹数量-1 score = 0 # 本次得分 count = 0 # 炸毁数量 # 遍历敌机精灵组,将游戏窗口内的敌机引爆 for enemy in enemies_group.sprites(): # 判断敌机是否进入游戏窗口 if enemy.rect.bottom > 0: score += enemy.value # 计算得分 count += 1 # 累计数量 enemy.hp = 0 # 摧毁敌机 print("炸毁了 %d 架敌机,得分 %d" % (count, score)) return score def reset_plane(self): """重置英雄飞机""" # 调用父类方法重置图像相关属性 super().reset_plane() self.is_power = True # 无敌判断标记 # self.bomb_count = HERO_BOMB_COUNT # 炸弹数量 self.bullets_kind = 0 # 子弹类型 # 发布英雄牺牲事件 pygame.event.post(pygame.event.Event(HERO_DEAD_EVENT)) # 设置3s之后取消无敌定时器事件 pygame.time.set_timer(HERO_POWER_OFF_EVENT, 3000) def fire(self, display_group): """发射子弹 :param display_group: 要添加的显示精灵组 """ # 需要将子弹精灵添加到2个精灵组 groups = (self.bullets_group, display_group) # 测试子弹增强效果 # self.bullets_kind = 1 for i in range(3): # 创建子弹精灵 bullet1 = Bullet(self.bullets_kind, *groups) # 计算子弹的垂直位置 y = self.rect.y - i * 15 # 判断子弹类型 if self.bullets_kind == 0: bullet1.rect.midbottom = (self.rect.centerx, y) else: bullet1.rect.midbottom = (self.rect.centerx - 20, y) # 再创建一颗子弹 bullet2 = Bullet(self.bullets_kind, *groups) bullet2.rect.midbottom = (self.rect.centerx + 20, y)
HeroB与HeroA为一致的代码
之后再在game里在所有调用HeroA的位置调用HeroB
# 英雄精灵 self.hero = HeroA(self.all_group) self.herob = HeroB(self.all_group)
重新赋予玩家操作按键
# 获得当前时刻的按键元组 keys = pygame.key.get_pressed() if keys[pygame.K_d]: self.herob.rect.x += 6 elif keys[pygame.K_a]: self.herob.rect.x -= 6 elif keys[pygame.K_w]: self.herob.rect.y -= 6 elif keys[pygame.K_s]: self.herob.rect.y += 6 if keys[pygame.K_RIGHT]: self.hero.rect.x += 6 elif keys[pygame.K_LEFT]: self.hero.rect.x -= 6 elif keys[pygame.K_UP]: self.hero.rect.y -= 6 elif keys[pygame.K_DOWN]: self.hero.rect.y += 6
修改碰撞体积方法
def check_collide(self): """碰撞检测""" global enemies # 检测英雄飞机和敌机的碰撞,若英雄飞机处于无敌状态彼此不会碰撞 if not self.hero.is_power: enemies = pygame.sprite.spritecollide(self.hero, self.enemies_group, False, pygame.sprite.collide_mask) # 过滤掉已经被摧毁的敌机 enemies = list(filter(lambda x: x.hp > 0, enemies)) # 检测英雄飞机和敌机的碰撞,若英雄飞机处于无敌状态彼此不会碰撞 if not self.herob.is_power: enemiesb = pygame.sprite.spritecollide(self.herob, self.enemies_group, False, pygame.sprite.collide_mask) # 过滤掉已经被摧毁的敌机 enemies = list(filter(lambda x: x.hp > 0, enemiesb)) # 是否撞到敌机 if enemies: # 播放英雄飞机被撞毁音效 self.player.play_sound(self.hero.wav_name) self.hero.hp = 0 # 英雄被摧毁 self.herob.hp = 0 for enemy in enemies: enemy.hp = 0 # 摧毁敌机 # 检测敌机是否被子弹击中 hit_enemies = pygame.sprite.groupcollide(self.enemies_group, self.hero.bullets_group, False, False, pygame.sprite.collide_mask) hit_enemiesb = pygame.sprite.groupcollide(self.enemies_group, self.herob.bullets_group, False, False, pygame.sprite.collide_mask) # 遍历字典 for enemy in hit_enemies: # 已经被摧毁的敌机不再浪费子弹 if enemy.hp <= 0: continue # 遍历击中敌机的子弹列表 for bullet in hit_enemies[enemy]: # 将子弹从所有精灵组中删除 bullet.kill() # 修改敌机的生命值 enemy.hp -= bullet.damage # 如果没有敌机被摧毁,继续判定下一颗子弹 if enemy.hp > 0: continue # 修改游戏得分并判断是否升级 if self.hud_panel.increase_score(enemy.value): # 播放升级音效 self.player.play_sound("upgrade.wav") self.create_enemies() # 播放敌机爆炸音效 self.player.play_sound(enemy.wav_name) # 退出遍历子弹列表循环 break # 遍历字典 for enemy in hit_enemiesb: # 已经被摧毁的敌机不再浪费子弹 if enemy.hp <= 0: continue # 遍历击中敌机的子弹列表 for bullet in hit_enemiesb[enemy]: # 将子弹从所有精灵组中删除 bullet.kill() # 修改敌机的生命值 enemy.hp -= bullet.damage # 如果没有敌机被摧毁,继续判定下一颗子弹 if enemy.hp > 0: continue # 修改游戏得分并判断是否升级 if self.hud_panel.increase_score(enemy.value): # 播放升级音效 self.player.play_sound("upgrade.wav") self.create_enemies() # 播放敌机爆炸音效 self.player.play_sound(enemy.wav_name) # 退出遍历子弹列表循环 break # 英雄拾取道具 supplies = pygame.sprite.spritecollide(self.hero, self.supplies_group, False, pygame.sprite.collide_mask) suppliesb = pygame.sprite.spritecollide(self.herob, self.supplies_group, False, pygame.sprite.collide_mask) if supplies: supply = supplies[0] # 播放拾取道具音效 self.player.play_sound(supply.wav_name) # 蒋道具设置到游戏窗口下方 supply.rect.y = SCREEN_RECT.h # 判断道具类型 if supply.kind == 0: # 设置炸弹补给 self.hero.bomb_count += 1 self.hud_panel.show_bomb(self.hero.bomb_count) else: # 设置子弹增强 self.hero.bullets_kind += 1 # 设置子弹增强效果的定时器事件 pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 8000) if suppliesb: supply = suppliesb[0] # 播放拾取道具音效 self.player.play_sound(supply.wav_name) # 蒋道具设置到游戏窗口下方 supply.rect.y = SCREEN_RECT.h # 判断道具类型 if supply.kind == 0: # 设置炸弹补给 self.hero.bomb_count += 1 self.hud_panel.show_bomb(self.hero.bomb_count) else: # 设置子弹增强 self.herob.bullets_kind += 1 # 设置子弹增强效果的定时器事件 pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 8000)
运行游戏便可看到可以双人模式进行游戏了
第一次写文章有问题还希望大家多多指出
谢谢大家伙的观看