绘制英雄类( 已方飞机 ), 同时有以下需求
- 英雄可以水平移动
- 英雄不能移出屏幕
- 可以发射子弹( 下一小节 )
添加英雄类
增加一个Hero类, 代码如下
class Hero(GameSprite):
"""英雄精灵"""
def __init__(self):
# 1.调用父类方法, 设置image
super().__init__("./images/me1.png", 0) # 设置速度为0, 不移动
# 设置初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom - 120
在创建精灵组方法中, 增加创建英雄精灵代码
# 创建英雄的精灵和精灵组
self.hero = Hero() # 保存到self中, 因为后续需要对它增加子弹
self.hero_group = pg.sprite.Group(self.hero)
在重绘精灵中, 增加代码重绘英雄 ( 绘制图片时, 有先后顺序)
# 更新英雄精灵
self.hero_group.update()
self.hero_group.draw(self.screen)
英雄移动事件
pygame中, 监听键盘按键有2种方式, 可以在监听event事件列表中查看按键事件, 或者直接监听键盘常量
前者代码实现如下:
elif event.type == pg.KEYDOWN and event.key == pg.K_RIGHT:
print("向右移动")
相对比前者的按一下动一下, 后者是在按住不松手的时间内持续有效, 两者监听方式不同, 前者是监听是否触发事件, 仅在按下, 或松手时能触发事件(一次), 而后者键盘常量能知道你是否持续按住某个键, 后者实现代码如下
keys_pressed = pg.key.get_pressed()
if keys_pressed[pg.K_RIGHT]:
print("持续向右移动")
在Hero类中, 覆盖update方法, 代码如下
def update(self):
self.rect.x += self.speed
在持续向右移动的监听中, 替换为如下代码
if keys_pressed[pg.K_RIGHT]:
self.hero.speed = 2
elif keys_pressed[pg.K_LEFT]:
self.hero.speed = -2
else:
self.hero.speed = 0
控制英雄边界
在Hero类的update方法中, 添加如下代码, 控制边界
# 控制边界
if self.rect.x < 0:
self.rect.x = 0
if self.rect.right > SCREEN_RECT.right: # right属性, 为x+width
self.rect.right = SCREEN_RECT.right
其中, rect.right, 表示矩形的x + 矩形的宽, 是pg.rect内置属性
代码小结
本节在plane_sprites中新增了Hero类, 完整代码如下
class Hero(GameSprite):
"""英雄精灵"""
def __init__(self):
# 1.调用父类方法, 设置image
super().__init__("./images/me1.png", 0) # 设置速度为0, 不移动
# 设置初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom - 120
def update(self):
self.rect.x += self.speed
# 控制边界
if self.rect.x < 0:
self.rect.x = 0
if self.rect.right > SCREEN_RECT.right: # right属性, 为x+width
self.rect.right = SCREEN_RECT.right
另外, main.py完整代码如下
import pygame as pg # 导入pygame模块
from plane_sprites import *
class PlaneGame(object):
"""飞机大战主程序"""
def __init__(self):
print("游戏初始化")
pg.init()
# 1. 创建游戏的窗口
self.screen = pg.display.set_mode(SCREEN_RECT.size)
# 2. 创建游戏的时钟
self.clock = pg.time.Clock()
# 3. 调用私有方法,精灵和精灵组的创建
self.__create_sprites()
# 4. 添加敌机
pg.time.set_timer(CREATE_ENEMY_EVENT, 1000)
def __create_sprites(self): # 创建精灵组
# 创建背景精灵和精灵组
bg1 = Background()
bg2 = Background(True)
self.back_group = pg.sprite.Group(bg1, bg2)
self.enemy_group = pg.sprite.Group()
# 创建英雄的精灵和精灵组
self.hero = Hero() # 保存到self中, 因为后续需要对它增加子弹
self.hero_group = pg.sprite.Group(self.hero)
def start_game(self):
print("游戏开始...")
while True:
# 1. 设置刷新帧率
self.clock.tick(FRAME_PER_SEC)
# 2. 事件监听
self.__event_handler()
# 3. 碰撞检测
self.__check_collide()
# 4. 更新/绘制精灵组
self.__update_sprites()
# 5. 更新显示
pg.display.update()
def __event_handler(self):
for event in pg.event.get():
# 判断是否退出游戏
if event.type == pg.QUIT:
PlaneGame.__game_over()
elif event.type == CREATE_ENEMY_EVENT:
print("敌机出场...")
enemy = Enemy()
self.enemy_group.add(enemy)
# elif event.type == pg.KEYDOWN and event.key == pg.K_RIGHT:
# print("向右移动")
keys_pressed = pg.key.get_pressed()
if keys_pressed[pg.K_RIGHT]:
self.hero.speed = 2
elif keys_pressed[pg.K_LEFT]:
self.hero.speed = -2
else:
self.hero.speed = 0
def __check_collide(self): # 碰撞检测
pass
def __update_sprites(self):
# 更新背景精灵
self.back_group.update()
self.back_group.draw(self.screen)
# 更新敌机精灵
self.enemy_group.update()
self.enemy_group.draw(self.screen)
# 更新英雄精灵
self.hero_group.update()
self.hero_group.draw(self.screen)
@staticmethod
def __game_over():
print("游戏结束")
pg.quit()
exit()
if __name__=="__main__":
# 创建游戏对象
game = PlaneGame()
# 开始游戏
game.start_game()