irpas技术客

Python-项目实战--飞机大战-英雄登场(7)_天寒心亦热

irpas 6423

目标

设计英雄和子弹类

使用pygame.key.get_pressed()移动英雄

发射子弹

1.设计英雄和子弹类 1.1英雄需求

游戏启动后,英雄出现在屏幕的水平中间位置,距离屏幕底部120像素

英雄每隔0.5秒发射一次子弹,每次连发三枚子弹

英雄默认不会移动,需要通过左/右方向键,控制英雄在水平方向移动

1.2子弹需求

子弹从英雄的正上方发射沿直线向上方飞行,飞出屏幕后,需要从精灵组中删除

Hero -- 英雄

初始化方法

指定英雄图片

初始速度 = 0 -- 英雄默认静止不动

定义bullets子弹精灵组保存子弹精灵

重写update()方法

英雄需要水平移动

并且需要保证不能移出屏幕

增加bullets属性,记录所有子弹精灵

增加fire方法,用于发射子弹

Bullet -- 子弹

初始化方法

指定子弹图片

初始速度= -2 -- 子弹需要向上方飞行

重写update()方法

判断是否飞出屏幕,如果是,从精灵组删除

2.创建英雄 2.1准备英雄类 分析

在plane_sprites新建Hero类

重写初始化方法,直接指定图片名称,并且将初始速度设置为0

设置英雄的初始位置

centerx = x + 0.5 * width

centery = y + 0.5 * height

bottom = y + height

代码演示

在plane_sprites.py中新建Hero类

class Hero(GameSprite): """英雄精灵""" def __init__(self): # 1.调用父类方法,设置image&speed super().__init__("./images/me1.png", 0) # 2.设置英雄的初始位置 self.rect.centerx = SCREEN_RECT.centerx self.rect.bottom = SCREEN_RECT.bottom - 120 2.2绘制英雄 分析

在__create_sprites,添加英雄精灵和英雄精灵组

后续要针对英雄做碰撞检测以及发射子弹,所以英雄需要单独定义成属性

在__update_sprites,让英雄精灵组调用update和draw方法

代码演示

在plane_main.py中修改__create_sprites方法

# 创建英雄的精灵和精灵组 self.hero = Hero() self.hero_group = pygame.sprite.Group(self.hero)

在plane_main.py中修改__update_sprites方法

self.hero_group.update() self.hero_group.draw(self.screen) 3.移动英雄位置 在pygame中针对键盘按键的捕获,有两种方式

第一种方式:判断event.type == pygame.KEYDOWN

第二种方式:

首先使用pygame.key.get_pressed()返回所有按键元组

通过键盘常量,判断元组中某一个键是否被按下 -- 如果被按下,对应数值为1

请问:这两种方式的区别?

第一种方式

向右移动的按键如果被一直按下,控制台只会输出一个 向右移动,需要松开按键重新按下,飞机才能持续向右移动

elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT: print("向右移动...")

第二种方式

向右移动的按键如果被一直按下(按下不放),控制台会输出多个 向右移动,按键不需要松开,飞机就可以持续向右移动

# 使用键盘提供的方法获取键盘按键。返回所有按键的元组,如果某个键被按下,对应的值会是1 keys_pressed = pygame.key.get_pressed() # 判是否按下了方向键 if keys_pressed[pygame.K_RIGHT]: print("向右移动...")

结论

第一种方式event.type用户 必须要抬起按键才算一次 按键事件,操作灵活性会大打折扣

第二种方式用户可以按住方向键不放,就能够实现持续向某一个方向移动了,操作灵活性更好

3.1移动英雄位置 演练步骤

在Hero类中重写update方法

用速度speed和英雄rect.x进行叠加

不需要调用父类方法 -- 父类方法只是实现了单纯的垂直运动

在__event_handler方法中根据左右方向键设置英雄的速度

向右 => speed = 2

向左 => speed =-2

其他 => speed = 0

代码演练

在Hero类,重写update()方法,根据速度水平移动英雄的飞机

在plane_sprites.py的Hero类中重写update()方法

def update(self): # 英雄在水平方向移动 self.rect.x += self.speed

在plane_main.py的__event_handler方法中根据左右方向键设置英雄的速度

# 使用键盘提供的方法获取键盘按键。返回所有按键的元组,如果某个键被按下,对应的值会是1 keys_pressed = pygame.key.get_pressed() # 判是否按下了方向键 if keys_pressed[pygame.K_RIGHT]: self.hero.speed = 2 elif keys_pressed[pygame.K_LEFT]: self.hero.speed = -2 else: self.hero.speed = 0 3.2控制英雄运动边界

在plane_sprites.py的Hero类的update()方法中判断英雄是否超出屏幕边界

right = x + width利用right属性可以非常容易的针对右侧设置精灵位置

代码演练

在plane_sprites.py的Hero类的update()方法中判断英雄是否超出屏幕边界

def update(self): # 英雄在水平方向移动 self.rect.x += self.speed # 控制英雄不能离开屏幕 if self.rect.x < 0: self.rect.x = 0 elif self.rect.right > SCREEN_RECT.right: self.rect.right = SCREEN_RECT.right 4.发射子弹

需求回顾 -- 英雄需求

游戏启动后,英雄出现在屏幕的水平中间位置,距离屏幕底部120像素

英雄每隔0.5秒发射一次子弹,每次连发三枚子弹

英雄默认不会移动,需要通过左/右方向键,控制英雄在水平方向移动

4.1添加发射子弹事件 分析

pygame的定时器使用方法非常固定

定义定时器常量 -- eventid

在初始化方法中,调用set_timer方法设置定时器事件

在游戏循环中,监听定时器事件

代码演练

在plane_sprites.py中的Hero类中定义fire方法

def fire(self): print("发射子弹...")

在plane_sprites.py中的顶部定义英雄发射子弹事件

# 英雄发射子弹事件 HERO_FIRE_EVENT = pygame.USEREVENT + 1

在plane_main.py中的PlaneGame类的__init__方法中修改定时器事件

pygame.time.set_timer(HERO_FIRE_EVENT, 500)

在plane_main.py中的PlaneGame类的__event_handler方法中让英雄发射子弹

elif event.type == HERO_FIRE_EVENT: self.hero.fire() 4.2定义子弹类

需求回顾 -- 子弹需求

子弹从英雄的正上方发射沿直线向上方飞行,飞出屏幕后,需要从精灵组中删除

Bullet -- 子弹

初始化方法

指定子弹图片

初始速度= -2 -- 子弹需要向上方飞行

重写update()方法

判断是否飞出屏幕,如果是,从精灵组删除

定义子弹类 分析

在plane_sprites.py新建Bullet继承自GameSprite

重写初始化方法,调用父类方法,直接指定图片名称,并且设置初始速度

重写update()方法,调用父类方法,判断子弹飞出屏幕从精灵组删除

代码演练 class Bullet(GameSprite): """子弹精灵""" def __init__(self): # 调用父类方法,设置子弹图片,设置初始速度 super().__init__("./images/bullet1.png", -2) def update(self): # 调用父类方法,让子弹沿着垂直方向飞行 super().update() # 判断子弹是否飞出屏幕 if self.rect.bottom < 0: self.kill() 4.3发射子弹 演练步骤

在Hero的初始化方法中创建子弹精灵组属性

修改plane_main.py的__update_sprites方法,让子弹精灵组调用update和draw方法

实现fire()方法

创建子弹精灵

设置初始位置 -- 在英雄的正上方

将子弹添加到精灵组

代码实现

初始化方法

plane_sprites.py中的Hero类中修改初始化方法

# 3.创建子弹精灵组 self.bullets = pygame.sprite.Group()

修改fire()方法

plane_sprites.py中的Hero类中修改fire()方法

def fire(self): print("发射子弹...") # 1.创建子弹精灵 bullet = Bullet() # 2.设置精灵位置,比英雄的y值小20个像素 bullet.rect.bottom = self.rect.y - 20 bullet.rect.centerx = self.rect.centerx # 3.将精灵添加到精灵组 self.bullets.add(bullet) 一次发射三枚子弹

修改fire()方法

plane_sprites.py中的Hero类中修改fire()方法,利用for循环

def fire(self): print("发射子弹...") for i in (0, 1, 2): # 1.创建子弹精灵 bullet = Bullet() # 2.设置精灵位置,比英雄的y值小20个像素 bullet.rect.bottom = self.rect.y - i * 20 bullet.rect.centerx = self.rect.centerx # 3.将精灵添加到精灵组 self.bullets.add(bullet)

内容总结于:https://space.bilibili.com/37974444


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Python项目实战 #英雄需求和子弹需求创建英雄