在之前完成了飞机大战整个项目以后就想提升一下,所以萌生出了做双人模式的想法。
那么在单人模式的基础上重写一个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)
运行游戏便可看到可以双人模式进行游戏了
?第一次写文章有问题还希望大家多多指出
谢谢大家伙的观看
?
|