英雄飞机的移动是通过鼠标或者键盘事件,即:
- 鼠标拖动英雄飞机,自动发射子弹
- 通过键盘控制飞机移动,按键发射子弹
我们这里实现第二种方式。这里需要注意:英雄飞机的移动是由按键事件驱动。
1. HeroPlane 类实现
英雄飞机是我们的主角,其基本实现的功能如下:
- top、bottom、left、right 4 个函数是飞机在不同方向上的移动函数
- shoot 用于发射子弹
- draw_element 绘制英雄飞机、以及英雄飞机发射出的子弹
- calc_position 计算英雄飞机、以及英雄飞机发射子弹的坐标
import pygame from BulletForHero import BulletForHero from Config import * class HeroPlane: def __init__(self, scene): # 游戏主场景 self.scene = scene # 英雄飞机资源 self.image = pygame.image.load(f'source/plane/hero.png') # 英雄飞机边框 self.bbox = self.image.get_rect() # 初始化飞机位置 self.bbox[0] = SCENE_W / 2 - self.bbox[2] / 2 self.bbox[1] = SCENE_H - self.bbox[3] - 10 # 初始化弹夹 self.bullets = BulletForHero(scene) # 移动速度 self.speed = 4 def top(self): if self.bbox[1] <= 0: return self.bbox.move_ip(0, -self.speed) def bottom(self): if self.bbox[1] >= SCENE_H - self.bbox[3]: return self.bbox.move_ip(0, self.speed) def left(self): if self.bbox[0] <= 0: return self.bbox.move_ip(-self.speed, 0) def right(self): if self.bbox[0] >= (SCENE_W - self.bbox[2]): return self.bbox.move_ip(self.speed, 0) def shoot(self, num): shoot_x = self.bbox[0] + self.bbox[2] / 2 shoot_y = self.bbox[1] self.bullets.shoot(shoot_x, shoot_y, num) def draw_element(self): self.scene.blit(self.image, self.bbox) self.bullets.draw_element() def calc_position(self): self.bullets.calc_position()
测试 HeroPlane 类:
if __name__ == '__main__': pygame.init() window = pygame.display.set_mode([512, 768]) clock = pygame.time.Clock() # 初始化英雄飞机 hero = HeroPlane(window) actions = [hero.left, hero.right, hero.top, hero.bottom] index = 0 action_index = 0 while True: # 清空窗口 window.fill((0, 0, 0)) # 计算坐标 hero.calc_position() # 绘制图像 hero.draw_element() # 发射子弹 hero.shoot(3) # 随机选择方向 actions[action_index]() index += 1 if index > 50: action_index = random.randint(0, 3) index = 0 pygame.event.get() pygame.display.update() clock.tick(60)
2. 键盘事件处理
这一步我们需要创建飞机对象并将其添加到 MainScene 中,并编写相应的键盘事件还控制飞机移动和发射子弹。
- W 向上
- S 乡下
- A 向左
- D 向右
- 按键 J 单列子弹发射
- 按键 K 三列子弹发射
- 按键 L 五列子弹发射
import random import pygame from Config import * from GameMap import GameMap from HeroPlane import HeroPlane from EnemyTroops import EnemyTroops # 主场景 class MainScene(object): # 初始化主场景 def __init__(self): # 初始化组件 pygame.init() # 初始化时钟 self.clock = pygame.time.Clock() # 初始化游戏窗口 self.scene = pygame.display.set_mode((SCENE_W, SCENE_H)) # 设置窗口标题 pygame.display.set_caption("飞机大战-v1.0 作者: 孟宝亮") # 初始化游戏元素 self.init_elements() # 初始化游戏元素 def init_elements(self): # 初始化游戏地图 self.map = GameMap(self.scene) # 初始化英雄飞机 self.hero = HeroPlane(self.scene) # 计算坐标 def calc_position(self): # 计算地图坐标 self.map.calc_position() # 计算英雄弹夹坐标 self.hero.calc_position() # 绘制元素 def draw_elements(self): # 绘制滚动地图 self.map.draw_element() # 绘制英雄飞机 self.hero.draw_element() # 处理事件 def handle_events(self): # 点击窗口关闭按钮 events = pygame.event.get() for event in events: if event.type == pygame.QUIT: pygame.quit() sys.exit() # 获得当前按下的键 keys = pygame.key.get_pressed() # 射击 if keys[pygame.K_j]: self.hero.shoot(1) if keys[pygame.K_k]: self.hero.shoot(3) if keys[pygame.K_l]: self.hero.shoot(5) # 上 if keys[pygame.K_w]: self.hero.top() # 下 if keys[pygame.K_s]: self.hero.bottom() # 左 if keys[pygame.K_a]: self.hero.left() # 右 if keys[pygame.K_d]: self.hero.right() # 碰撞检测 def detect_conlision(self): pass # 主循环 def run(self): while True: # 碰撞检测 self.detect_conlision() # 计算元素坐标 self.calc_position() # 绘制元素图片 self.draw_elements() # 处理事件 self.handle_events() # 刷新显示 pygame.display.update() # 控制帧率 self.clock.tick(60)