Python-项目实战--飞机大战-英雄登场(7)

news2024/10/2 20:26:14

目标

  • 设计英雄和子弹类

  • 使用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,让英雄精灵组调用updatedraw方法

代码演示

  • 在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.pyHero类中重写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.pyHero类的update()方法中判断英雄是否超出屏幕边界

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

代码演练

  • plane_sprites.pyHero类的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方法,让子弹精灵组调用updatedraw方法

  • 实现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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vulnhub之CLOVER: 1

1.信息收集 输入arp-scan 192.168.239.0/24进行主机存活探测&#xff0c;可以看到192.168.239.171主机存活。 对192.168.239.171主机进行端口扫描&#xff0c;可以看到20、21、22、82、110、443、5781、8080。 发现21端口可以匿名登录&#xff0c;输入&#xff1a;anonymous…

牛客网Python篇数据分析习题(一)

1.现有一个Nowcoder.csv文件&#xff0c;它记录了牛客网的部分用户数据&#xff0c;包含如下字段&#xff08;字段与字段之间以逗号间隔&#xff09;&#xff1a; Nowcoder_ID&#xff1a;用户ID Level&#xff1a;等级 Achievement_value&#xff1a;成就值 Num_of_exercise&a…

春招快来了,杭电研究生学长聊聊踩过的坑,助你成功上岸

引言 大家好&#xff0c;我是James&#xff0c;由于之前文章内容浏览量太少以及这几个月的繁忙&#xff0c;一直没有静下心输出一些内容&#xff0c;随着疫情放开&#xff0c;新春来临&#xff0c;年后百业待兴&#xff0c;马上又是一年春季招聘。作为一个参加过2022年春&…

golang 通道类型

文章目录一、什么是通道类型二、通道产生的原因三、声明channel四、创建channel五、channel相关操作1、发送值2、接收值3、关闭通道3.1 注意3.2 特点四、通道类型1、无缓冲通道2、有缓冲通道五、单向通道一、什么是通道类型 Go 语言中的通道&#xff08;channel&#xff09;是一…

【ChatGpt】使用感受分享

作者&#xff1a;狮子也疯狂 专栏&#xff1a;《基础知识查漏》 坚持做好每一步&#xff0c;幸运之神自然会降临在你的身上 目录一. &#x1f981; 前言二. &#x1f981; 使用详情Ⅰ. &#x1f407; 使用过程Ⅱ. &#x1f407; 使用感受Ⅲ. &#x1f407; 遇到的问题3.1 我遇…

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容 在做PCB设计的时候,在1MM中心间距的BGA背面放置电容,是非常常见的设计,如何快速把电容等距放在BGA下方,除了借助辅助工具外,在Allegro升级到了172版本的时候,可以借助本身自带的功能实现快速放置,以下图…

【云原生】解读Kubernetes三层网络方案

在上一篇文章中&#xff0c;我以网桥类型的 Flannel 插件为例&#xff0c;为你讲解了 Kubernetes 里容器网络和 CNI 插件的主要工作原理。不过&#xff0c;除了这种模式之外&#xff0c;还有一种纯三层&#xff08;Pure Layer 3&#xff09;网络方案非常值得你注意。其中的典型…

【RabbitMQ五】——RabbitMQ路由模式(Routing)

RabbitMQ路由模式前言RabbitMQ模式的基本概念为什么要使用Rabbitmq 路由模式RabbitMQ路由模式组成元素路由模式完整代码Pom文件引入RabbtiMQ依赖RabbitMQ工具类生产者消费者1消费者2运行结果截图前言 通过本篇博客能够简单使用RabbitMQ的路由模式。 本篇博客主要是博主通过官网…

ROS运行机C++程序,移动

流程&#xff1a; 1.创建工作空间 mkdir catkin_ws cd catkin_ws mkdir src cd src catkin_init_workspace 2编译工作空间 cd ~/catkin_ws/ catkin_make catkin_make install 首先对ROS进行创建一个元功能包 3.设置环境变量 source devel/setup.bash source devel/setup.b…

Java基础知识

1. Java 基本功 1.1. Java 入门&#xff08;基础概念与常识&#xff09; 1.1.1. Java 语言有哪些特点?1.1.2. 关于 JVM JDK 和 JRE 最详细通俗的解答 1.1.2.1. JVM1.1.2.2. JDK 和 JRE 1.1.3. Oracle JDK 和 OpenJDK 的对比1.1.4. Java 和 C的区别?1.1.5. import java 和 jav…

每日学术速递2.11

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.IR、cs.MM 1.A Comprehensive Survey on Multimodal Recommender Systems: Taxonomy, Evaluation, and Future Directions 标题&#xff1a;关于多模态推荐系统的综合调查&#xff1a;分…

电子学会2020年6月青少年软件编程(图形化)等级考试试卷(三级)答案解析

目录 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 二、判断题&#xff08;共10题&#xff0c;每题2分&#xff0c;共20分&#xff09; 三、编程题&#xff08;共4题&#xff0c;共30分&#xff09; 青少年软件编程&#xff08;Scratch&…

leaflet 加载geojson文件并显示图形(示例代码051)

第051个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中加载geojson文件,将图形显示在地图上。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其他来练习 文章目录 示例效果配置方式示例源代码(…

【MyBatis】自定义映射resultMap

8.1、resultMap处理字段和属性的映射关系 若字段名和实体类中的属性名不一致&#xff0c;则可以通过resultMap设置自定义映射 <!--resultMap&#xff1a;设置自定义映射属性&#xff1a;id&#xff1a;表示自定义映射的唯一标识type&#xff1a;查询的数据要映射的实体类的…

基于PLUS+InVEST模型 生态系统服务多情景模拟预测

目录 第一章 理论基础与软件介绍 第二章 数据获取与制备 第三章 土地利用格局模拟 第四章 生态系统服务评估 第五章 时空变化及驱动机制分析 第六章 论文撰写技巧及案例分析 工业革命以来&#xff0c;社会生产力迅速提高&#xff0c;人类活动频繁&#xff0c;此外人口与日…

Rabbitmq业务难点

Rabbitmq业务难点1.消息生产者发送的消息无法路由到任何一个队列怎么处理?2.聊聊Rabbitmq的七种工作模式3.Rabbitmq的消息确认机制4.Rabbitmq的消息持久化5.发布确认模式如何确保生产者能够成功将消息投递到消息队列6. Rabbitmq基于队列设置消息过期时间和单独针对消息设置过期…

ByteHouse:基于ClickHouse的实时数仓能力升级解读

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 ByteHouse是火山引擎上的一款云原生数据仓库&#xff0c;为用户带来极速分析体验&#xff0c;能够支撑实时数据分析和海量数据离线分析。便捷的弹性扩缩容能力&…

数据结构 第八章 查找(静态查找表)

集合 1、集合中的数据元素除了属于同一集合外,没有任何的逻辑关系 2、在集合中,每个数据元素都有一个区别于其他元素的唯一标识(键值或者关键字值) 3、集合的运算&#xff1a; 1 查找某一元素是否存在(内部查找、外部查找) 2 将集合中的元素按照它的唯一标识进行排序4、集合的…

shell编程之awk

文章目录九、shell编程之awk9.1 什么是awk9.2 awk的工作流程9.3 awk程序执行方式9.4 awk基本语法9.4.1 awk的输出9.4.2 awk的变量9.4.3 awk操作符9.4.4 awk的模式9.4.5 awk控制语句9.4.6 awk使用数组9.4.7 awk内置函数9.5 awk 案例9.5.2 网站日志分析九、shell编程之awk 9.1 什…

Linux:软链接和硬链接的理解

Linux通过命令行创建快捷方式使用的命令是ln&#xff0c;这里就涉及到了软链接和硬链接&#xff0c;确实有些不好理解&#xff0c;如果你也一样&#xff0c;那么可以继续看下去了 目录ln命令语法实操创建软链接&#xff1a;ln -s [源文件或目录][目标文件或目录]创建硬链接&…