Python应用实例(一)外星人入侵(二)

news2025/1/13 17:35:10

1.添加飞船图像

下面将飞船加入游戏中。为了在屏幕上绘制玩家的飞船,我们将加载一幅图像,再使用Pygame方法blit()绘制它。

为游戏选择素材时,务必要注意许可。最安全、最不费钱的方式是使用Pixabay等网站提供的免费图形,无须授权许可即可使用并修改。

在游戏中几乎可以使用任何类型的图像文件,但使用位图(.bmp)文件最为简单,因为Pygame默认加载位图。虽然可配置Pygame以使用其他文件类型,但有些文件类型要求你在计算机上安装相应的图像库。大多数图像为.jpg、.png或.gif格式,但可使用Photoshop、GIMP和Paint等工具将其转换为位图。

选择图像时,要特别注意背景色。请尽可能选择背景为透明或纯色的图像,便于使用图像编辑器将其背景替换为任意颜色。图像的背景色与游戏的背景色匹配时,游戏看起来最漂亮。你也可以将游戏的背景色设置成图像的背景色。

就游戏《外星人入侵》而言,可使用文件ship.bmp,这个文件的背景色与项目使用的设置相同。请在项目文件夹(alien_invasion)中新建一个名为images的文件夹,并将文件ship.bmp保存在其中。

在这里插入图片描述

在这里插入图片描述

1.1 创建ship类

选择用于表示飞船的图像后,需要将其显示到屏幕上。我们创建一个名为ship的模块,其中包含Ship类,负责管理飞船的大部分行为。

  import pygame

  class Ship:
      """管理飞船的类"""

      def __init__(self, ai_game):
          """初始化飞船并设置其初始位置。"""
❶         self.screen = ai_game.screen
❷         self.screen_rect = ai_game.screen.get_rect()

          # 加载飞船图像并获取其外接矩形。
❸         self.image = pygame.image.load('images/ship.bmp')
          self.rect = self.image.get_rect()

          # 对于每艘新飞船,都将其放在屏幕底部的中央。
❹         self.rect.midbottom = self.screen_rect.midbottom

❺     def blitme(self):
          """在指定位置绘制飞船。"""
          self.screen.blit(self.image, self.rect)

Pygame之所以高效,是因为它让你能够像处理矩形(rect对象)一样处理所有的游戏元素,即便其形状并非矩形。像处理矩形一样处理游戏元素之所以高效,是因为矩形是简单的几何形状。例如,通过将游戏元素视为矩形,Pygame能够更快地判断出它们是否发生了碰撞。这种做法的效果通常很好,游戏玩家几乎注意不到我们处理的并不是游戏元素的实际形状。在这个类中,我们将把飞船和屏幕作为矩形进行处理。

定义这个类之前,导入了模块pygame。Ship的方法__init__()接受两个参数:引用self和指向当前AlienInvasion实例的引用。这让Ship能够访问AlienInvasion中定义的所有游戏资源。在❶处,将屏幕赋给了Ship的一个属性,以便在这个类的所有方法中轻松访问。在❷处,使用方法get_rect()访问屏幕的属性rect,并将其赋给了self.screen_rect,这让我们能够将飞船放到屏幕的正确位置。

调用pygame.image.load()加载图像,并将飞船图像的位置传递给它(见❸)。该函数返回一个表示飞船的surface,而我们将这个surface赋给了self.image。加载图像后,使用get_rect()获取相应surface的属性rect,以便后面能够使用它来指定飞船的位置。

处理rect对象时,可使用矩形四角和中心的[插图]坐标和[插图]坐标。可通过设置这些值来指定矩形的位置。要让游戏元素居中,可设置相应rect对象的属性center、centerx或centery;要让游戏元素与屏幕边缘对齐,可使用属性top、bottom、left或right。除此之外,还有一些组合属性,如midbottom、midtop、midleft和midright。要调整游戏元素的水平或垂直位置,可使用属性x和y,分别是相应矩形左上角的[插图]坐标和[插图]坐标。这些属性让你无须做游戏开发人员原本需要手工完成的计算,因此会经常用到。

注意 在Pygame中,原点(0, 0)位于屏幕左上角,向右下方移动时,坐标值将增大。在1200 × 800的屏幕上,原点位于左上角,而右下角的坐标为(1200, 800)。这些坐标对应的是游戏窗口,而不是物理屏幕。

我们要将飞船放在屏幕底部的中央。为此,将self.rect.midbottom设置为表示屏幕的矩形的属性midbottom(见❹)。Pygame使用这些rect属性来放置飞船图像,使其与屏幕下边缘对齐并水平居中。

在❺处,定义了方法blitme(),它将图像绘制到self.rect指定的位置。

1.2 在屏幕上绘制飞船

下面更新alien_invasion.py,创建一艘飞船并调用其方法blitme():

  --snip--
  from settings import Settings
  from ship import Ship

  class AlienInvasion:
      """管理游戏资源和行为的类"""

      def __init__(self):
          --snip--
          pygame.display.set_caption("Alien Invasion")

❶         self.ship = Ship(self)

      def run_game(self):
              --snip--
              # 每次循环时都重绘屏幕。
              self.screen.fill(self.settings.bg_color)
❷             self.ship.blitme()

              # 让最近绘制的屏幕可见。
              pygame.display.flip()
  --snip--

导入Ship类,并在创建屏幕后创建一个Ship实例(见❶)。调用Ship()时,必须提供一个参数:一个AlienInvasion实例。在这里,self指向的是当前AlienInvasion实例。这个参数让Ship能够访问游戏资源,如对象screen。我们将这个Ship实例赋给了self.ship。

填充背景后,调用ship.blitme()将飞船绘制到屏幕上,确保它出现在背景前面(见❷)。

现在如果运行alien_invasion.py,将看到飞船位于空游戏屏幕底部的中央,如图所示。

在这里插入图片描述

2.重构:方法_check_events()和_update_screen()

在大型项目中,经常需要在添加新代码前重构既有代码。重构旨在简化既有代码的结构,使其更容易扩展。本节将把越来越长的方法run_game()拆分成两个辅助方法(helper method)。辅助方法在类中执行任务,但并非是通过实例调用的。在Python中,辅助方法的名称以单个下划线打头。

2.1 方法_check_events()

我们将把管理事件的代码移到一个名为_check_events()的方法中,以简化run_game()并隔离事件管理循环。通过隔离事件循环,可将事件管理与游戏的其他方面(如更新屏幕)分离。

下面是新增方法_check_events()后的AlienInvasion类,只有run_game()的代码受到影响:

      def run_game(self):
          """开始游戏主循环。"""
          while True:
❶             self._check_events()
              # 每次循环时都重绘屏幕。
              --snip--def _check_events(self):
          """响应按键和鼠标事件。"""
          for event in pygame.event.get():
              if event.type == pygame.QUIT:
                  sys.exit()

新增方法_check_events()(见❷),并将检查玩家是否单击了关闭窗口按钮的代码移到该方法中。

要调用当前类的方法,可使用句点表示法,并指定变量名self和要调用的方法的名称(见❶)。我们在run_game()的while循环中调用这个新增的方法。

2.2 方法_update_screen()

为进一步简化run_game(),将更新屏幕的代码移到一个名为_update_screen()的方法中:

      def run_game(self):
          """开始游戏主循环。"""
          while True:
              self._check_events()
              self._update_screen()

      def _check_events(self):
          --snip--

      def _update_screen(self):
          """更新屏幕上的图像,并切换到新屏幕。"""
          self.screen.fill(self.settings.bg_color)
          self.ship.blitme()

          pygame.display.flip()

我们将绘制背景和飞船以及切换屏幕的代码移到了方法_update_screen()中。现在,run_game()中的主循环简单多了,很容易看出在每次循环中都检测了新发生的事件并更新了屏幕。

如果你开发过大量的游戏,可能早就开始像这样将代码放到不同的方法中了。不过如果你从未开发过这样的项目,可能不知道如何组织代码。这里采用的做法是,先编写可行的代码,等代码越来越复杂时再进行重构,以向你展示真正的开发过程:先编写尽可能简单的代码,等项目越来越复杂后对其进行重构。

对代码进行重构使其更容易扩展后,可以开始处理游戏的动态方面了!

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

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

相关文章

强者游戏-敢来挑战否-Amazon DeepRacer League

Amazon DeepRacer中国峰会总决赛 Amazon DeepRacer 自动驾驶赛车名校邀请赛会在6月27日-28日举办的Amazon DeepRacer中国峰会总决赛时同步启动。勇哥的目标是拿个比较好的名词。大家如果有参加这次活动的可以过来一起搞哦。下面我来具体介绍一下这次峰会,以及比赛的…

PyTorch C++ 前端是 PyTorch 机器学习框架的纯 C++ 接口

使用 PyTorch C 前端 PyTorch C 前端是 PyTorch 机器学习框架的纯 C 接口。 虽然 PyTorch 的主要接口自然是 Python,但此 Python API 位于强大的 C 代码库之上,提供基本的数据结构和功能,例如张量和自动微分。 C 前端公开了纯 C 11 API&…

常见面试题之线程基础知识

1. 线程和进程的区别? 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理IO的。 当一…

DataStructure01|ArrayList和顺序表

ArrayList与顺序表 1.线性表 ​ 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列… ​ 线性表在逻辑上是线性结构,也就说…

产品设计.从用户体验五要素出发,谈如何设计产品

用户调研--产品定位---产品方案---视觉设计 作者 | 渐渐见减减简https://www.zcool.com.cn/article/ZMTEyNDA2NA.html 用户体验五要素是一种产品分析与设计的方法论,帮助我们以正确方式从0到1设计一款产品。 1 战略层 企业做一个产品前,都要明确几个问题…

多目标樽海鞘算法MATLAB实战(附源码)

今天给大家分享多目标樽海鞘算法,主要从算法原理和代码实战展开。需要了解智能算法、机器学习、深度学习和信号处理相关理论的可以后台私信哦,下一期分享的内容就是你想了解的内容。 一、算法原理 上一篇分享的SSA算法能够驱动salps向食物来源靠近&…

【Flutter】包管理(6)Flutter 状态管理 Provider 深入使用指南

文章目录 一、 前言二、 ProxyProvider 的使用三、 处理异步数据四、 性能优化五、 版本信息六、 总结一、 前言 在我们的上一篇文章中,我们介绍了 Flutter 中 Provider 包的基本使用。 在这篇文章中,我们将深入探讨 Provider 的高级使用方法,包括如何使用 ProxyProvider,…

Green板 和Red板和Nv EVM板比较

001 电源开关、 复位、烧写按钮 G:绿板 K3: Reset press RN K1: Brush RECOVERY button K2: Start button Power ON R: 红板 K3: POWER_KEY K2: FORCE_RECOVERY K1: RESET_KEY 002 USB设计 烧写连接器 G: 绿板 J6:TYPE C 烧写连接器 USB0_DP …

streamlit——搭建作业、文件上传网站(代码编写、服务器部署)

使用streamlit搭建简单的作业提交网站 文章目录 使用streamlit搭建简单的作业提交网站一、引言二、streamlit代码三、搭建到服务器中1、放行安全组2、将代码放到服务器中3、配置依赖4、运行代码 一、引言 由于我平时需要收集各种类型的作业文件。但传统的微信收文件方式很让我…

PyQt5中文手册

PyQt5中文手册 一、介绍 本教程的目的是带领你入门PyQt5。教程内所有代码都在Linux上测试通过。PyQt4 教程是PyQt4的教程,PyQt4是一个Python(同时支持2和3)版的Qt库。 关于 PyQt5 PyQt5 是Digia的一套Qt5应用框架与python的结合&#xff…

实训五:数据库安全控制 - 授权及回收权限

授权及回收权限 第1关:授权任务描述相关知识MySql系统库中的权限表访问控制的两个阶段:授予的权限等级:MySQL 权限类型grant 语句的基本语法格式revoke 语句的基本语法格式查看权限限制权限 编程要求测试说明参考代码 第2关:授权-…

论文悦读(5)——NVM文件系统之CtFS(FAST‘22)文件系统

CtFS(FAST22) 1. 背景(Background)1.1 NVM1.2 NVM文件系统1.3 快速索引方案 2. 观察与动机(Observation & Motivation)3. CtFS设计与实现(Design & Implementation)3.1 系统…

ASP.NET Dotnet 3.5实验室LIMS系统源码

LIMS系统功能包括:检测管理(合同管理、样品管理、样品收发管理、工作任务分配、检测结果登记、复核及审核、留样管理等)、报告管理(报告编制、审核、签发、打印等)、原始记录管理、仪器设备管理、消耗品管理、文件管理…

Oralce系列十九:Oralce的体系结构

Oralce的体系结构 1. 物理结构2. 内存结构2.1 SGA2.2 后台进程 3. 逻辑结构 1. 物理结构 Oracle数据库的物理结构由参数文件、控制文件、数据文件和日志文件组成,用于存储和管理数据库的数据和元数据,每个文件都扮演着不可或缺的角色。 参数文件用于配…

盘点那些VS Code上的常用插件

插件可以使代码开发过程变得更加轻松和高效 文章目录 前言中文版主题插件显示错误游戏插件连接数据库拼写检查插件前端智能提示刷算法题的插件美化注释的插件美化括号的插件自动补全路径和文件名在浏览器中打开 HTML 文件在 VS Code 里面使用 Postman同步 VS Code 配置的插件 前…

MFC第七天 单机版数据库增删改的方法和用户登录(密码修改)、权限管理功能的员工管理系统的应用 以及 CCombox类的属性和方法

文章目录 员工管理系统的应用对TCHAR类型简介:Unicode软件开发中的文字转换方式有三种 CComboBox控件属性和类库介绍CBS_组合框控件属性CComboBox常用方法 员工管理系统示例代码如下Employer_sql.hEmployer_sql.cppMainDlg.hMainDlg.cpp: 实现文件CLoginDlg.hCLogin…

入坑 TS(一)

1、TS 采用类型后置的语法 const str: string "我是字符串"; const num: number "我是数值"; const bool: boolean false;函数怎么写? // 有返回值 function sayHello(str: string): string {return str; } // 无返回值 function sayHello…

Java throws关键字

Java的throws关键字用于声明异常。它向程序员提供了可能发生异常的信息。 因此,最好为程序员提供异常处理代码,以便保持程序的正常流程。 异常处理主要用于处理已检查异常。如果出现任何未检查的异常,例如NullPointerException,则…

jjy-shareV2.0一键分享到微博,QQ空间,QQ好友,微信

介绍 jjy-shareV2.0一键分享到微博,QQ空间,QQ好友,微信 作者:极纪元-橙 作者博客:https://cplvfx.blog.csdn.net/ 码云Gitee:橙cplvfx极纪元 (cplvfx) - Gitee.com 项目地址:jjy-shareV2.…

登录认证(全集)--jwt,Filter,Interceptor详细说明

一、登录校验 问题:在未登录情况下,我们也可以直接访问部门管理、员工管理等功能。由于浏览器与web服务器中的数据交互是通过HTTP协议的,而HTTP协议是无状态的–即每个页面中的请求和响应都是独立的,没有状态存在。所以我们需要进…