飞机大战
------------------------------------------------------------------------------------------------
手工整理黑马程序员版飞机大战
部分代码展示,其余代码资源获取地址:https://download.csdn.net/download/weixin_56410185/85446705
-----------------------------------------------------------------------------------------
在game里导入游戏核心模块
game存放游戏核心
game_items存放游戏元素模块
game_hud存放游戏控制面板/提示信息模块
game_music存放游戏音乐控制模块
-----------------------------------------------------------------------------------------
"""游戏核心模块"""
import pygame
from game_items import *
from game_hud import *
from game_music import *
import random
class Game(object):
"""游戏核心类"""
def __init__(self):
# 1.游戏主窗口
self.main_window = pygame.display.set_mode(SCREEN_RECT.size)
pygame.display.set_caption("飞机大战") # 设置窗口的标题
# 2.游戏状态属性
self.is_game_over = False # 游戏结束标记
self.is_game_pause = False # 游戏暂停标记
# 3.游戏精灵组
self.all_group = pygame.sprite.Group() # 存放所有界面上的精灵
self.enemies_group = pygame.sprite.Group() # 敌机精灵组
self.supplies_group = pygame.sprite.Group() # 道具精灵组
# 4.创建精灵
# 创建背景精灵,向下方移动
self.all_group.add(Background(False), Background(True)) # 星空背景精灵
# 创建游戏控制面板
self.hud_panel = HUDPanel(self.all_group)
# 创建英雄飞机精灵
self.hero_sprite = Hero(self.all_group)
self.hud_panel.show_bomb(self.hero_sprite.bomb_count)
# 初始化敌机
self.create_enemies()
# 初始化道具
self.create_supply()
# 音乐播放器
self.player = MusicPlayer('game_music.ogg')
self.player.play_music()
def reset_game(self):
"""重置游戏数据"""
self.is_game_over = False
self.is_game_pause = False
# 重置面板
self.hud_panel.reset_panel()
# 重置英雄飞机位置
self.hero_sprite.rect.midbottom = HERO_DEFAULT_MID_BOTTOM
# 销毁所有的敌人飞机
for enemy in self.enemies_group:
enemy.kill()
# 销毁所有的子弹
for bullet in self.hero_sprite.bullets_group:
bullet.kill()
# 重新创建飞机
self.create_enemies()
def start(self):
"""开启游戏主逻辑"""
# 创建时钟
clock = pygame.time.Clock()
# 动画帧数计数器
frame_count = 0
while True:
# 判断英雄是否已经死亡
self.is_game_over = self.hud_panel.lives_count == 0
# 处理事件监听
if self.event_handler():
# event_handler返回True 则说明发生了退出事件
# 退出游戏之前要保存最好成绩
self.hud_panel.save_best_score()
return
# 根据游戏状态切换游戏显示的内容
if self.is_game_over:
# print("游戏已经结束,按空格键重新开始...")
self.hud_panel.panel_paused(True, self.all_group)
elif self.is_game_pause:
# print("游戏已经暂停,按空格键继续...")
self.hud_panel.panel_paused(False, self.all_group)
else:
self.hud_panel.panel_resume(self.all_group)
# 处理长按事件
keys = pygame.key.get_pressed() # get_pressed() 得到一个元组每一个按键在元组里都有一个下标,对应下标2值为1 则说明按键被按下
move_hor = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT] # 水平的移动基数
move_ver = keys[pygame.K_DOWN] - keys[pygame.K_UP] # 垂直的移动基数
# 检测碰撞
self.check_collide()
frame_count = (frame_count + 1) % FRAME_INTERVAL
self.all_group.update(frame_count == 0, move_hor, move_ver) # 刷新精灵位置
# 绘制内容
self.all_group.draw(self.main_window)
# 刷新界面
pygame.display.update()
# 设置刷新率
clock.tick(60)
def event_handler(self):
"""获取并处理事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 退出按钮被点击
return True
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
# 用户按下了键盘上的 ESC 键
return True
elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# 用户按下了键盘上的 空格 键
if self.is_game_over:
self.reset_game()
else:
# 游戏还没结束,切换暂停状态
self.is_game_pause = not self.is_game_pause
self.player.pause_music(self.is_game_pause) # 切换背景音乐状态
# 必须在游戏结束也没暂停才能执行的操作
if not self.is_game_over and not self.is_game_pause:
if event.type == pygame.KEYDOWN and event.key == pygame.K_b:
# 释放一颗炸弹, 并修改炸弹数量
if self.hero_sprite.hp > 0 and self.hero_sprite.bomb_count > 0:
self.player.play_sound('use_bomb.wav')
score = self.hero_sprite.blowup(self.enemies_group)
self.hud_panel.show_bomb(self.hero_sprite.bomb_count)
if self.hud_panel.increase_score(score):
self.create_enemies()
elif event.type == HERO_DEAD_EVENT:
# 玩家飞机死亡
self.hud_panel.lives_count -= 1
self.hud_panel.show_lives()
self.hud_panel.show_bomb(self.hero_sprite.bomb_count)
elif event.type == HERO_POWER_OFF_EVENT:
# 无敌时间结束
self.hero_sprite.is_power = False
pygame.time.set_timer(HERO_POWER_OFF_EVENT, 0) # 设置定时器延时为0,可用取消定时器
elif event.type == HERO_FIRE_EVENT:
# 英雄飞机发射子弹定时事件
self.player.play_sound('bullet.wav')
self.hero_sprite.fire(self.all_group)
elif event.type == THROW_SUPPLY_EVENT:
# 随机抛出一个道具
self.player.play_sound('supply.wav')
supply = random.choice(self.supplies_group.sprites())
supply.throw_supply()
elif event.type == BULLET_ENHANCED_OFF_EVENT:
# 玩家使用双排子弹的时间已经结束,需要恢复为单排的子弹
self.hero_sprite.bullets_kind = 0 # 恢复为单排的子弹
pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 0) # 取消定时
return False
def create_enemies(self):
"""创建敌机"""
count = len(self.enemies_group.sprites())
groups = (self.all_group, self.enemies_group)
# 根据不同的关卡创建不同数量的敌机
if self.hud_panel.level == 1 and count == 0:
# 关卡1
for i in range(16):
Enemy(0, 3, *groups)
elif self.hud_panel.level == 2 and count == 16:
# 关卡2
for enemy in self.enemies_group.sprites():
enemy.max_speed = 5
for i in range(8):
Enemy(0, 5, *groups)
for i in range(2):
Enemy(1, 1, *groups)
elif self.hud_panel.level == 3 and count == 26:
# 关卡3
for enemy in self.enemies_group.sprites():
enemy.max_speed = 7 if enemy.kind == 0 else 3
for i in range(8):
Enemy(0, 7, *groups)
for i in range(2):
Enemy(1, 3, *groups)
for i in range(2):
Enemy(2, 1, *groups)
def create_image(self):
"""加载背景图片和英雄飞机"""
self.background_image = pygame.image.load('./res/images/background.png')
self.background_rect = self.background_image.get_rect()
# 加载英雄飞机
self.hero_image = pygame.image.load('./res/images/me1.png')
self.hero_rect = self.hero_image.get_rect()
# 把英雄飞机和背景图片的中心对齐
self.hero_rect.center = self.background_rect.center
def check_collide(self):
"""检查是否有碰撞"""
if not self.hero_sprite.is_power: # 没有无敌才需要检查碰撞
collide_enemies = pygame.sprite.spritecollide(self.hero_sprite, self.enemies_group,
False, pygame.sprite.collide_mask)
collide_enemies = list(filter(lambda x: x.hp > 0, collide_enemies))
# 撞毁玩家飞机
if collide_enemies:
self.player.play_sound(self.hero_sprite.wav_name)
self.hero_sprite.hp = 0
# 撞毁敌人飞机
for enemy in collide_enemies:
enemy.hp = 0
# 子弹和敌机的碰撞分析
hit_enemies = pygame.sprite.groupcollide(self.enemies_group, self.hero_sprite.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
# 检查英雄飞机和道具的碰撞
supplies = pygame.sprite.spritecollide(self.hero_sprite, self.supplies_group,
False, pygame.sprite.collide_mask)
if supplies:
supply = supplies[0]
self.player.play_sound(supply.wav_name) # 根据道具类型播放捡道具的音效
# 根据道具类型产生不同的行为
if supply.kind == 0:
self.hero_sprite.bomb_count += 1
self.hud_panel.show_bomb(self.hero_sprite.bomb_count)
else:
self.hero_sprite.bullets_kind = 1 # 修改英雄子弹为双排
pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 20000) # 20秒之后重新变为单排
# 移动道具到屏幕之下
supply.rect.y = SCREEN_RECT.h
def create_supply(self):
"""初始化两个道具, 并开启投放道具的定时器"""
Supply(0, self.all_group, self.supplies_group)
Supply(1, self.all_group, self.supplies_group)
pygame.time.set_timer(THROW_SUPPLY_EVENT, 30000)
if __name__ == '__main__':
# 初始化游戏
pygame.init()
# 开始游戏
Game().start()
# 释放游戏资源
pygame.quit()



