Python学习笔记50:游戏篇之外星人入侵(十一)
前言
本篇文章接着之前的内容,继续对游戏功能进行优化,主要是优化游戏状态以及对应的处理。
状态
一个游戏包含多种状态,这个状态是一个可以很复杂也可以很简单的内容。条件所限,我们这个游戏的状态就比较简单:
- 未开始
- 游戏中
- 暂停
- 结束
我们通过一个字段进行控制,并且将这个字段放置到setting
模块中。
class Setting:"""系统设置类"""def __init__(self):-- snip --# 游戏状态:0未开始,1游戏中,2暂停,3结束self.game_status = 0
处理状态
根据不同的状态值,我们先对main
模块进行简单的处理。
import pygame
from pygame.sprite import Groupimport alien_invasion.game_functions as gf
from alien_invasion.setting import Setting
from alien_invasion.ship import Shipdef run_game():"""启动游戏"""# 初始化pygamepygame.init()# 定义一个系统设置对象setting = Setting()# 新建窗口screen = pygame.display.set_mode((setting.screen_width, setting.screen_height))# 窗口命名pygame.display.set_caption(setting.caption)# 定义一个飞船对象ship = Ship(setting, screen)# 创建子弹编组bullets = Group()# 创建外星人编组aliens = Group()# 创建编组内的外星人gf.create_fleet(setting, screen, aliens)while True:if setting.game_status == 0:passelif setting.game_status == 1:# 处理监听事件gf.check_event(ship, setting, screen, bullets)# 移动飞船ship.move()# 更新子弹位置gf.update_bullets(bullets, aliens, setting, screen)# 更新外星人gf.update_aliens(aliens, setting, ship)# 刷新屏幕gf.update_screen(setting, screen, ship, bullets, aliens)elif setting.game_status == 2:passelif setting.game_status == 3:passif __name__ == '__main__':run_game()
状态对应的业务
现在,我们要对状态思考响应的游戏业务。
这里直接描述一下我个人简单预定的功能:
- 启动游戏,弹出窗口,显示欢迎来到游戏,按回车键开始游戏。其他所有按键不生效。
- 在游戏中,按下回车暂停游戏;暂停游戏时按下回车继续游戏
- 开始游戏后,任意时刻按下
Esc
键退出游戏,回到黑色窗口,显示游戏介绍,暂停一秒关闭游戏。
代码实现
我们在第二步已经简单的对状态值进行了处理,接下来就根据上面的业务在对应的状态处理部分一一填充。
首先我们处理开始游戏的状态。
开始游戏
首先我们需要在setting.game_status == 0
的条件下新建一个not_start()
函数,传入参数setting
和screen
。这两个参数一个是要回写状态值到配置模块中,一个是渲染游戏窗口需要的一些属性。
修改main
模块中循环处理的部分如下:
-- snip --while True:# 没啥用,方便编写代码的时候看看代码执行情况print(setting.game_status)if setting.game_status == 0:# 处理没启动的业务逻辑gf.not_start(setting, screen)-- snip --
main
模块处理好以后,我们在gf
模块进行实际的业务代码编写。
在函数中,我们需要完成两个功能,一个是渲染文字,一个是监听按键事件,是否有开始游戏,那么代码编写如下:
def not_start(setting, screen):# 先渲染文字handle_text(screen)print("not_start")# 处理监听事件for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:if setting.game_status == 0:setting.game_status = 1print("开始游戏")
这里监听事件的部分没有单独拉函数出来,主要是不影响阅读,不过因为渲染文字的函数有点行数并且也算一个比较独立的功能,所以又单独创建了一个函数,后面的结束也是如此。
另外虽然我们这个时候只监听是否按下回车键的这个事件,但是点击退出窗口的监听事件,在任何地方都不能忘了,不然到时候可能你的窗口关不了,只能去通过停止程序关闭。
监听事件的代码比较简单的,就是在确认是按下了回车,状态是0的时候,回写状态值即可。
我们看看文字渲染的代码。
文字渲染我们在项目开始之前介绍pygame
就提前讲过,相比大家都不陌生,看代码注释即可,代码如下:
def handle_text(screen):# 字体颜色pink = pygame.Color('#FFFFFF')# 使用Arial字体创建一个字体对象,32号,加粗,倾斜font = arial_bold = pygame.font.SysFont('Arial', 32, bold=True, italic=True)# 渲染文本text_surface1 = font.render("Welcome to the Game Of Alien Invasion", True, pink)# 获取文件的矩形区域text_rect1 = text_surface1.get_rect()# 设置文本Y坐标320,居中位置text_rect1.midtop = (screen.get_width() // 2, 320)# 渲染文本text_surface2 = font.render("Press The Enter Key To Start The Game", True, pink)# 获取文件的矩形区域text_rect2 = text_surface2.get_rect()# 设置文本Y坐标420,居中位置text_rect2.midtop = (screen.get_width() // 2, 420)# 绘制文本screen.blit(text_surface1, text_rect1)screen.blit(text_surface2, text_rect2)# 更新显示pygame.display.flip()
运行main模块,按下回车。
可以看到文字正常渲染,并且输出栏一直在出输出当前状态。
如果你觉得画面单调,可以自己加点东西渲染,pygame
渲染图片这些相比也不陌生了。
按下回车,游戏正常开始!
可以看到,已经进入到游戏页面,并且输出栏的状态值也变成了1。
游戏中
游戏中的处理比较简单,因为我们之前已经完成了游戏中的代码编写,所以我们只需要在游戏中的监听事件中加上回车键的监听事件暂停游戏。
ps: 这里其实也可以结束游戏,代码我先写上,但是不操作。业务代码也不复杂,就是多加一个Esc
键的监听事件。
gf
模块中的check_keydown_events()
函数代码修改如下:
def check_keydown_events(event, ship, setting, screen, bullets):"""响应按键"""if event.key == pygame.K_RIGHT:ship.moving_right = Trueelif event.key == pygame.K_LEFT:ship.moving_left = Trueelif event.key == pygame.K_UP:ship.moving_top = Trueelif event.key == pygame.K_DOWN:ship.moving_bottom = Trueelif event.key == pygame.K_SPACE:fire(bullets, screen, setting, ship)elif event.key == pygame.K_q:sys.exit()elif event.key == pygame.K_RETURN:if setting.game_status == 1:setting.game_status = 2print("暂停游戏")elif event.key == pygame.K_ESCAPE:setting.game_status = 3print("游戏结束")
启动main
模块,开始游戏后再按回车,效果如下:
可以看到,我们的飞船,子弹,外星人全部暂停住了,输出栏一直打印状态也变成了2(暂停)。
屏幕中显示了一些文字,这些其实是暂停的业务。
我们马上进行暂停的业务代码编写。
暂停游戏
参考开始游戏的实现,我们在暂停的分支下调用一个函数stop()
。
main
模块循环部分代码如下:
-- snip --while True:# 没啥用,方便编写代码的时候看看代码执行情况print(setting.game_status)if setting.game_status == 0:# 处理没启动的业务逻辑gf.not_start(setting, screen)elif setting.game_status == 1:# 处理监听事件gf.check_event(ship, setting, screen, bullets)# 移动飞船ship.move()# 更新子弹位置gf.update_bullets(bullets, aliens, setting, screen)# 更新外星人gf.update_aliens(aliens, setting, ship)# 刷新屏幕gf.update_screen(setting, screen, ship, bullets, aliens)elif setting.game_status == 2:gf.stop(setting, screen)-- snip --
同样,我们去到gf
模块创建stop()
函数并实现相应的功能,代码如下:
-- snip --
def stop(setting, screen):handle_stop_text(screen)for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:if setting.game_status == 2:setting.game_status = 1print("继续游戏")elif event.key == pygame.K_ESCAPE:setting.game_status == 3:print("结束游戏")
-- snip --
代码依旧分两部分实现,渲染文字和监听事件。在暂停的监听事件中我们和开始一样,监听关闭窗口,回车和结束,并在回车事件中回写状态值,让游戏继续运行,在Esc
时间中结束游戏。
文字渲染部分代码如下:
def handle_stop_text(screen):# 字体颜色pink = pygame.Color('#000000')# 使用Arial字体创建一个字体对象,32号,加粗,倾斜font = arial_bold = pygame.font.SysFont('Arial', 32, bold=True, italic=True)# 渲染文本text_surface1 = font.render("Game Stop", True, pink)# 获取文件的矩形区域text_rect1 = text_surface1.get_rect()# 设置文本Y坐标50,居中位置text_rect1.midtop = (screen.get_width() // 2, 320)# 渲染文本text_surface2 = font.render("Press The Enter Key To restore The Game", True, pink)# 获取文件的矩形区域text_rect2 = text_surface2.get_rect()# 设置文本Y坐标50,居中位置text_rect2.midtop = (screen.get_width() // 2, 420)# 绘制文本screen.blit(text_surface1, text_rect1)screen.blit(text_surface2, text_rect2)# 更新显示pygame.display.flip()
基本上就是复制开始的文字渲染,改了下文字内容。
效果的话这里就不展示了,就是暂停开始,开始暂停这一套。
结束游戏
在游戏中和暂停的时候,我们都可以通过按键Esc
实现游戏结束。
在main
模块的改动依旧是调用一个结束函数,但是结束函数不需要回写状态值,所以我们只需要一个screen
参数。
代码如下:
while True:# 没啥用,方便编写代码的时候看看代码执行情况print(setting.game_status)if setting.game_status == 0:# 处理没启动的业务逻辑gf.not_start(setting, screen)elif setting.game_status == 1:# 处理监听事件gf.check_event(ship, setting, screen, bullets)# 移动飞船ship.move()# 更新子弹位置gf.update_bullets(bullets, aliens, setting, screen)# 更新外星人gf.update_aliens(aliens, setting, ship)# 刷新屏幕gf.update_screen(setting, screen, ship, bullets, aliens)elif setting.game_status == 2:gf.stop(setting, screen)elif setting.game_status == 3:gf.end(screen)
gf
模块改动如下:
def end(screen):# 重新填充屏幕screen.fill((0, 0, 0))# 渲染文字handle_end_text(screen)# 休眠一秒sleep(1)# 退出pygame.quit()sys.exit()
和之前比对有一点不同,多了几部,其实没有特别含义,就是看起来流畅好看一点。
文字渲染代码如下:
def handle_end_text(screen):# 字体颜色pink = pygame.Color('#FFFFFF')# 使用Arial字体创建一个字体对象,32号,加粗,倾斜font = arial_bold = pygame.font.SysFont('Arial', 48, bold=True, italic=True)# 渲染文本text_surface1 = font.render("Game Over", True, pink)# 获取文件的矩形区域text_rect1 = text_surface1.get_rect()# 设置文本Y坐标50,居中位置text_rect1.midtop = (screen.get_width() // 2, screen.get_height() // 2)# 绘制文本screen.blit(text_surface1, text_rect1)# 更新显示pygame.display.flip()
运行效果如下:
结尾
今天的内容就是这些,设定状态值,并且在对应的状态中处理不同的逻辑,渲染不同的画面。
当然我们是学习,所以内容都比较简单,有兴趣的话可以深入一下加点自己的元素进去。
后面我们继续优化游戏功能,加油!!!
相关文章:

Python学习笔记50:游戏篇之外星人入侵(十一)
前言 本篇文章接着之前的内容,继续对游戏功能进行优化,主要是优化游戏状态以及对应的处理。 状态 一个游戏包含多种状态,这个状态是一个可以很复杂也可以很简单的内容。条件所限,我们这个游戏的状态就比较简单: 未…...

vue3踩坑问题记录
//vue3element-plus //1、placeholder换行显示 const startTxt ref() const contentText ref<any>() startTxt.value "请描述问题内容、例如:" historyData.prompt.forEach((el:any)>{contentText.value \n${el.question}}) <ElInputv-mo…...

Python 爬虫实战:Scrapy 框架详解与应用
🛠️ Scrapy 框架基本使用 Scrapy 是一个强大的 Python 爬虫框架,提供了用于提取和处理网页数据的功能。以下是 Scrapy 的基本使用步骤: 安装 Scrapy pip install scrapy创建 Scrapy 项目 scrapy startproject myproject这将生成一个基础…...

60 函数参数——关键参数
关键参数主要指调用函数时的参数传递方式,与函数定义无关。 通过关键参数可以按参数名字传递值,明确指定哪个值传递给哪个参数,实参顺序可以和形参顺序不一致,但不影响参数值的传递结果,避免了用户需要牢记参数位置和…...

wps 最新 2019 专业版 下载安装教程,解锁全部功能,免费领取
文章目录 前言软件介绍软件下载安装步骤激活步骤小福利(安卓APP)软件介绍软件下载安装步骤 前言 本篇文章主要针对WPS2019专业版的安装下载进行详细讲解,软件已激活,可放心使用;并且可以进行账号登录,进行…...

前端(三):Ajax
一、Ajax Asynchronous JavaScript And XML,简称Ajax,是异步的JavaScript和XML。 作用:数据交换,通过Ajax可以给服务器发送请求,并获取服务器响应的数据。异步交互:可以在不重新加载整个页面的情况下&…...

启动 /使用/关闭 Redis 服务器
1. Linux 启动 Linux 系统启动 Redis 有两种方法,分别是前台启动,后台启动,两者各有差异; (1)前台启动 首先,需要进入 bin 路径(安装路径不同输入的命令也不同); 个人的命令(一般…...

Linux系统中的高级SELinux安全策略定制技术
随着信息技术的发展,计算机系统的安全性变得越来越重要。在开源世界中,Linux作为一种广泛应用的操作系统,其安全性一直备受关注。其中,SELinux(Security-Enhanced Linux)作为Linux系统中的一个安全模块&…...

使用 Ansible Blocks 进行错误处理
注:机翻,未校。 How to Use Ansible Blocks Make your Playbooks more readable and maintainable using Blocks feature in Ansible. 使用 Ansible 中的块功能使 Playbook 更具可读性和可维护性。 Jul 15, 2024 — LHB Community How to Use Ansible…...

java中的静态变量和实例变量的区别
java中的静态变量和实例变量的区别 在Java中,静态变量(也称为类变量)和实例变量是两种不同类型的变量,它们在多个方面存在显著的区别。以下是它们之间的一些主要区别: 存储位置 静态变量:存储在方法区&am…...

【Effecutive C++】条款02 尽量以const, enum, inline替换 #define
Prefer consts, enums, and inline to #define. 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#define不被视为语言的一部分。那正是它的问题所在。当你做出这样的事情: #define ASPECT_RATIO 1.653记号名称ASPECT_RATIO也许从未被编译…...

leetcode-226. 翻转二叉树
题目描述 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 输入:root [2,1,3] 输出:[2,3,1]…...

用的到linux-tomcat端口占用排查-Day5
前言: 最近使用tomcat搭建了一套测试环境的应用,整个搭建过程也很简单,就是将部署包上传至服务器☞解压☞启动tomcat服务器,当然服务器也是成功启动了,但是发现前端应用报404,具体如下图所示。 一、现象及思…...

mqtt协议详解(0)初步认识mqtt
文章目录 1. 介绍2. 主要特性3. 架构1. 介绍 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种构建在TCP/IP协议之上的轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境,例如IOT。 MQTT 协议于 1…...

Java语言程序设计基础篇_编程练习题*16.7 (设置时钟的时间)
*16.7 (设置时钟的时间) 编写一个程序,显示一个时钟,并通过在三个文本域中输入小时、分钟和秒 钟来设置时钟的时间,如图16-38b 所示。使用程序清单14-21的ClockPane改变时钟大小使其居于面板中央 习题思路 实例化一个ClockPane(在程序清单1…...

YOLOv8新版本支持实时检测Transformer(RT-DETR)、SAM分割一切
原文:YOLOv8新版本支持实时检测Transformer(RT-DETR)、SAM分割一切 - 知乎 (zhihu.com) 一、SAM 分割任何模型 (Segment Anything Model - SAM) 是一种突破性的图像分割模型,可实现具有实时性能的快速分割。 项目地址 https://github.com/facebookresearch/segment-…...

【传输层协议】UDP和TCP协议
文章目录 UDP协议UDP特点UDP的缓冲区基于UDP的应用层协议 TCP协议6位标志位:确认应答机制超时重传机制连接管理机制(握手和挥手)服务端状态转换过程客户端状态转换过程TIME_WAIT状态CLOSE_WAIT状态 为什么是三次握手和四次挥手滑动窗口如果发…...

Java Excel复杂表头,表头合并单元格
Java Excel复杂表头,表头合并单元格 效果预览 一、maven依赖 <!--操作excel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.1</version><scope>test</…...

Java整合腾讯云发送短信实战Demo
简介 在现代应用开发中,短信服务是非常重要的功能之一。它可以用于用户验证、通知等各种场景。本文将介绍如何使用Java整合腾讯云短信服务,并提供一个完整的实战示例代码。 环境准备 在开始之前,确保你已经完成以下准备工作: 注…...

电路中电阻,电容和电感作用总结
电阻作用 1,上拉电阻 电阻的连接一般是一端接上拉的电源(一般与芯片信号的电压值相匹配),另一端连接芯片引脚所对应的信号大概如下图 功能:一、预置某些引脚的功能,例如复位信号拉高(失能&…...

OrangePi AIpro学习1 —— 烧写和ssh系统
目录 一、下载烧写工具和系统 二、烧写和启动 2.1 烧写和启动 2.2 烧写失败后的问题解决 三、串口连接到主机 3.1 串口连接到主机 四、网络连接到主机 4.1 修改香橙派IP地址 4.2 win11配置以太网静态ip 4.4 主机和香橙派直连 4.5 主机和香橙派连接到同一个路由器 五…...

Gather 全球化进程迅速 多重利好推动未来发展
在过去的几周里,Gather的全球化发展十分迅速,并取得了一系列重要成绩,这些成绩进一步巩固了Gather在区块链和去中心化通信领域的地位,并为未来的发展注入了强劲的动力。 $GAT代币成功进驻多家顶级交易所 7月19日,Gath…...

面试经典 222. 完全二叉树的节点个数
二叉树我最近刷的特别多,差不多快刷完了,但是有一种题型差点给我忽略了,那就是完全二叉树,这也是一个很重要的题型,今天刚好有一道题目可以来复习一下完全二叉树的特性 题目链接如下:https://leetcode.cn/…...

【css】3d柱状图-vue组件版
创建一个响应式圆柱形进度条组件 在现代网页设计中,圆柱形进度条是一种非常流行的视觉元素,用于展示数据的进度或状态。本文将介绍如何使用Vue.js和LESS创建一个响应式的圆柱形进度条组件。 组件结构 我们的组件由两部分组成:一个圆柱形的…...

《计算机组成原理》(第3版)第3章 系统总线 复习笔记
第3章 系统总线 一、总线的基本概念 总线是连接多个部件的信息传输线,是各部件共享的传输介质,如图3-1所示。 图3-1 面向CPU的双总线结构框图 倘若将CPU、主存和I/O设备都挂到一组总线上,便形成单总线结构的计算机,如图3-2所示…...

【网络安全】https协议的加密方案避免中间人攻击(MITM攻击)导致的数据泄露风险
目录 引言 概念准备 中间人 加密 数据摘要 && 数据指纹 数字签名 密钥加密 中间人攻击 CA证书 https加密的解决方案 个人主页:东洛的克莱斯韦克-CSDN博客 引言 http在应用层协议中是明文传输协议,它是通信双方传输数据时的一种约定。【…...

拼多多商家电话采集 拼多多店铺爬虫软件使用教程
拼多多商家电话采集和店铺爬虫软件使用教程: 商家电话采集: a. 打开拼多多网站,进入需要采集电话号码的店铺页面。 b. 打开浏览器开发者工具(一般按F12键或右键选择“检查”)。 c. 在开发者工具中切换到“网络”或“Ne…...

RK3566 MIPI屏调试记录
文章目录 1. 前言2. 环境介绍3. 思路介绍4. 确认要修改的设备树文件5. 设备树中修改关键引脚5.1. 添加dsi0节点5.2. 修改屏幕背光引脚5.3. 添加屏幕复位引脚5.4. 添加屏幕使能引脚 6. 修改屏幕timing参数7. 修改上下电时序8. 修改初始化序列和反初始化序列9. 显示路由配置10. 最…...

爬虫数据模拟真实设备请求头User-Agent生成(fake_useragent:一个超强的Python库)
在Python开发中,处理HTTP请求时经常需要模拟不同的用户代理(User-Agent)来绕过网站的反爬虫机制或进行兼容性测试。fake_useragent正是这样一个强大的Python库,它能够生成随机且多样化的用户代理字符串,让你的请求看起…...

【教育宝-注册安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...