关于“Python”的核心知识点整理大全34

目录

第13 章

外星人

13.1 回顾项目

game_functions.py

13.2 创建第一个外星人

13.2.1 创建 Alien 类

alien.py

13.2.2 创建 Alien 实例

alien_invasion.py

13.2.3 让外星人出现在屏幕上

game_functions.py

13.3 创建一群外星人

13.3.1 确定一行可容纳多少个外星人

注意

13.3.2 创建多行外星人

alien_invasion.py

game_functions.py

13.3.3 创建外星人群

game_functions.py

注意


第13 章

外星人

13.1 回顾项目

开发较大的项目时,进入每个开发阶段前回顾一下开发计划,搞清楚接下来要通过编写代码 来完成哪些任务都是不错的主意。本章涉及以下内容。

 研究既有代码,确定实现新功能前是否要进行重构。

 在屏幕左上角添加一个外星人,并指定合适的边距。

 根据第一个外星人的边距和屏幕尺寸计算屏幕上可容纳多少个外星人。我们将编写一个 循环来创建一系列外星人,这些外星人填满了屏幕的上半部分。

 让外星人群向两边和下方移动,直到外星人被全部击落,有外星人撞到飞船,或有外星 人抵达屏幕底端。如果整群外星人都被击落,我们将再创建一群外星人。如果有外星人 撞到了飞船或抵达屏幕底端,我们将销毁飞船并再创建一群外星人。

 限制玩家可用的飞船数量,配给的飞船用完后,游戏结束。

我们将在实现功能的同时完善这个计划,但就目前而言,该计划已足够详尽。

在给项目添加新功能前,还应审核既有代码。每进入一个新阶段,通常项目都会更复杂,因 此最好对混乱或低效的代码进行清理。

我们在开发的同时一直不断地重构,因此当前需要做的清理工作不多,但每次为测试新功能而运行这个游戏时,都必须使用鼠标来关闭它,这太讨厌了。下面来添加一个结束游戏的快捷键Q:

game_functions.py
def check_keydown_events(event, ai_settings, screen, ship, bullets):--snip--elif event.key == pygame.K_q:sys.exit() 

在check_keydown_events()中,我们添加了一个代码块,以便在玩家按Q时结束游戏。这样 的修改很安全,因为Q键离箭头键和空格键很远,玩家不小心按Q键而导致游戏结束的可能性不 大。现在测试时可按Q关闭游戏,而无需使用鼠标来关闭窗口了。

13.2 创建第一个外星人

在屏幕上放置外星人与放置飞船类似。每个外星人的行为都由Alien类控制,我们将像创建 Ship类那样创建这个类。出于简化考虑,我们也使用位图来表示外星人。你可以自己寻找表示外 星人的图像,也可使用图13-1所示的图像,可在本书配套资源(https://www.nostarch.com/ pythoncrashcourse/)中找到。这幅图像的背景为灰色,与屏幕背景色一致。请务必将你选择的图 像文件保存到文件夹images中。

13.2.1 创建 Alien 类

下面来编写Alien类:

alien.py
import pygame
from pygame.sprite import Sprite 
class Alien(Sprite):"""表示单个外星人的类"""def __init__(self, ai_settings, screen):"""初始化外星人并设置其起始位置"""super(Alien, self).__init__()self.screen = screenself.ai_settings = ai_settings# 加载外星人图像,并设置其rect属性self.image = pygame.image.load('images/alien.bmp')self.rect = self.image.get_rect()# 每个外星人最初都在屏幕左上角附近
1 self.rect.x = self.rect.widthself.rect.y = self.rect.height# 存储外星人的准确位置self.x = float(self.rect.x)def blitme(self):"""在指定位置绘制外星人"""self.screen.blit(self.image, self.rect)

除位置不同外,这个类的大部分代码都与Ship类相似。每个外星人最初都位于屏幕左上 角附近,我们将每个外星人的左边距都设置为外星人的宽度,并将上边距设置为外星人的高 度(见1)。

13.2.2 创建 Alien 实例

下面在alien_invasion.py中创建一个Alien实例:

alien_invasion.py
--snip--
from ship import Ship
from alien import Alien
import game_functions as gf
def run_game():--snip--# 创建一个外星人alien = Alien(ai_settings, screen)# 开始游戏主循环while True:gf.check_events(ai_settings, screen, ship, bullets)ship.update()gf.update_bullets(bullets)gf.update_screen(ai_settings, screen, ship, alien, bullets)
run_game()

在这里,我们导入了新创建的Alien类,并在进入主while循环前创建了一个Alien实例。我们 没有修改外星人的位置,因此该while循环没有任何新东西,但我们修改了对update_screen()的 调用,传递了一个外星人实例。

13.2.3 让外星人出现在屏幕上

为让外星人出现在屏幕上,我们在update_screen()中调用其方法blitme():

game_functions.py
def update_screen(ai_settings, screen, ship, alien, bullets):--snip--# 在飞船和外星人后面重绘所有的子弹for bullet in bullets:bullet.draw_bullet()ship.blitme()alien.blitme()# 让最近绘制的屏幕可见pygame.display.flip()

我们先绘制飞船和子弹,再绘制外星人,让外星人在屏幕上位于最前面。图13-2显示了屏幕 上的第一个外星人。

第一个外星人正确地现身后,下面来编写绘制一群外星人的代码。

13.3 创建一群外星人

要绘制一群外星人,需要确定一行能容纳多少个外星人以及要绘制多少行外星人。我们将首 先计算外星人之间的水平间距,并创建一行外星人,再确定可用的垂直空间,并创建整群外星人。

13.3.1 确定一行可容纳多少个外星人

为确定一行可容纳多少个外星人,我们来看看可用的水平空间有多大。屏幕宽度存储在 ai_settings.screen_width中,但需要在屏幕两边都留下一定的边距,把它设置为外星人的宽度。 由于有两个边距,因此可用于放置外星人的水平空间为屏幕宽度减去外星人宽度的两倍:

available_space_x = ai_settings.screen_width – (2 * alien_width)

我们还需要在外星人之间留出一定的空间,即外星人宽度。因此,显示一个外星人所需的水 平空间为外星人宽度的两倍:一个宽度用于放置外星人,另一个宽度为外星人右边的空白区域。 为确定一行可容纳多少个外星人,我们将可用空间除以外星人宽度的两倍:

number_aliens_x = available_space_x / (2 * alien_width) 

我们将在创建外星人群时使用这些公式。


注意

令人欣慰的是,在程序中执行计算时,一开始你无需确定公式是正确的,而可以尝试直 接运行程序,看看结果是否符合预期。即便是在最糟糕的情况下,也只是屏幕上显示的 外星人太多或太少。你可以根据在屏幕上看到的情况调整计算公式。


13.3.2 创建多行外星人

为创建一行外星人,首先在alien_invasion.py中创建一个名为aliens的空编组,用于存储全部 外星人,再调用game_functions.py中创建外星人群的函数:

alien_invasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():--snip--# 创建一艘飞船、一个子弹编组和一个外星人编组ship = Ship(ai_settings, screen)bullets = Group() 
1 aliens = Group()# 创建外星人群
2 gf.create_fleet(ai_settings, screen, aliens)# 开始游戏主循环while True:--snip—
3 gf.update_screen(ai_settings, screen, ship, aliens, bullets)
run_game()

由于我们不再在alien_invasion.py中直接创建外星人,因此无需在这个文件中导入Alien类。 1处创建了一个空编组,用于存储所有的外星人。接下来,调用稍后将编写的函数 create_fleet()(见2),并将ai_settings、对象screen和空编组aliens传递给它。然后,修改对 update_screen()的调用,让它能够访问外星人编组(见3)。 我们还需要修改update_screen():

game_functions.py
def update_screen(ai_settings, screen, ship, aliens, bullets):--snip--ship.blitme()aliens.draw(screen)# 让最近绘制的屏幕可见pygame.display.flip() 

对编组调用draw()时,Pygame自动绘制编组的每个元素,绘制位置由元素的属性rect决定。 在这里,aliens.draw(screen)在屏幕上绘制编组中的每个外星人。

13.3.3 创建外星人群

现在可以创建外星人群了。下面是新函数create_fleet(),我们将它放在game_functions. py的末尾。我们还需要导入Alien类,因此务必在文件game_functions.py开头添加相应的import 语句:

game_functions.py
--snip--
from bullet import Bullet
from alien import Alien
--snip--
def create_fleet(ai_settings, screen, aliens):"""创建外星人群"""# 创建一个外星人,并计算一行可容纳多少个外星人# 外星人间距为外星人宽度
1 alien = Alien(ai_settings, screen)
2 alien_width = alien.rect.width
3 available_space_x = ai_settings.screen_width - 2 * alien_width
4 number_aliens_x = int(available_space_x / (2 * alien_width))
# 创建第一行外星人
5 for alien_number in range(number_aliens_x):# 创建一个外星人并将其加入当前行
6 alien = Alien(ai_settings, screen)alien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.xaliens.add(alien) 

这些代码大都在前面详细介绍过。为放置外星人,我们需要知道外星人的宽度和高度,因此 在执行计算前,我们先创建一个外星人(见1)。这个外星人不是外星人群的成员,因此没有将 它加入到编组aliens中。在2处,我们从外星人的rect属性中获取外星人宽度,并将这个值存储 到alien_width中,以免反复访问属性rect。在3处,我们计算可用于放置外星人的水平空间,以 及其中可容纳多少个外星人。

相比于前面介绍的工作,这里唯一的不同是使用了int()来确保计算得到的外星人数量为整 数(见4),因为我们不希望某个外星人只显示一部分,而且函数range()也需要一个整数。函数 int()将小数部分丢弃,相当于向下圆整(这大有裨益,因为我们宁愿每行都多出一点点空间, 也不希望每行的外星人之间过于拥挤)。

接下来,我们编写了一个循环,它从零数到要创建的外星人数(见5)。在这个循环的主体 中,我们创建一个新的外星人,并通过设置x坐标将其加入当前行(见6)。将每个外星人都往右 推一个外星人的宽度。接下来,我们将外星人宽度乘以2,得到每个外星人占据的空间(其中包 括其右边的空白区域),再据此计算当前外星人在当前行的位置。最后,我们将每个新创建的外 星人都添加到编组aliens中。 如果你现在运行这个游戏,将看到第一行外星人,如图13-3所示。

这行外星人在屏幕上稍微偏向了左边,这实际上是有好处的,因为我们将让外星人群往右移, 触及屏幕边缘后稍微往下移,然后往左移,以此类推。就像经典游戏《太空入侵者》,相比于只 往下移,这种移动方式更有趣。我们将让外形人群不断这样移动,直到所有外星人都被击落或有 外星人撞上飞船或抵达屏幕底端。


注意

根据你选择的屏幕宽度,在你的系统中,第一行外星人的位置可能稍有不同


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

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

相关文章

使用Pycharm一键将.ui文件生成.py文件配置教程、一键打开QTDesigner教程

2df3621a-7ffd-4f18-9735-b86464b83a5b 前言 我痛恨所有将白嫖归为理所应当的猪🐖。 教程 打开pycharm之后,依次点击File->Settings->Tools->External Tools,进入如下界面: 1、配置快捷打开Qt Designer 点击号&…

探索鸿蒙:了解华为鸿蒙操作系统的基础课程

目录 学习目标: 学习内容: 学习时间: 学习产出: 介绍鸿蒙操作系统的起源和发展历程。 理解鸿蒙操作系统的核心概念和体系结构。 学习如何搭建和配置鸿蒙开发环境。 掌握基础的鸿蒙应用开发技术,包括应用的创建、…

在x64上构建智能家居(home assistant)(二)(新版Debain12)连接Postgresql数据库

新版数据库安装基本和旧版相同,大部分可以参考旧版本在x64上构建智能家居(home assistant)(二)连接Postgresql数据库_homeassist 数据库-CSDN博客 新版本的home assistant系统安装,我在原来写的手顺上直接修改了,需要的可以查看在x64上构建智能家居(home…

【小白专用】php pdo方式连接sqlserver 设置方法 更新23.12.21

windows系统的拓展相对来说比较好安装&#xff0c;直接下载对应的dll文件&#xff0c;修改php.ini配置文件即可。 添加PHP对SQL SERVER的支持 1.新建PHP 文件&#xff0c;输入内容&#xff1a; <?php echo phpinfo(); ?> 2.运行后&#xff0c;可以查看到如下数据&…

微服务之服务注册与发现

服务注册发现 服务注册就是维护一个登记簿&#xff0c;它管理系统内所有的服务地址。当新的服务启动后&#xff0c;它会向登记簿交待自己的地址信息。服务的依赖方直接向登记簿要 Service Provider 地址就行了。当下用于服务注册的工具非常多 ZooKeeper&#xff0c;Consul&…

Git 软件安装及配置指南

目录 前言1 访问 Git 官网2 选择适用于操作系统的版本3 下载并运行Git 安装程序4 安装过程的选择组件和配置5 验证安装结语 前言 在进行软件开发或协作项目时&#xff0c;使用版本控制工具至关重要。Git 是一个强大且流行的版本控制系统&#xff0c;本文将介绍 Git 的安装步骤…

vue2 之 实现pdf电子签章

一、前情提要 1. 需求 仿照e签宝&#xff0c;实现pdf电子签章 > 拿到pdf链接&#xff0c;移动章的位置&#xff0c;获取章的坐标 技术 : 使用fabric pdfjs-dist vuedraggable 2. 借鉴 一位大佬的代码仓亏 : 地址 一位大佬写的文章 &#xff1a;地址 3. 优化 在大佬的代码…

浅述无人机技术在地质灾害应急救援场景中的应用

12月18日23时&#xff0c;甘肃临夏州积石山县发生6.2级地震&#xff0c;震源深度10千米&#xff0c;灾区电力、通信受到影响。地震发生后&#xff0c;无人机技术也火速应用在灾区的应急抢险中。目前&#xff0c;根据受灾地区实际情况&#xff0c;翼龙-2H应急救灾型无人机已出动…

网络安全-API接口安全

本文为作者学习文章&#xff0c;按作者习惯写成&#xff0c;如有错误或需要追加内容请留言&#xff08;不喜勿喷&#xff09; 本文为追加文章&#xff0c;后期慢慢追加 API接口概念 API接口&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&…

Python---socket之send和recv原理剖析

1. 认识TCP socket的发送和接收缓冲区 当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区&#xff0c;这个发送和接收缓冲区指的就是内存中的一片空间。 2. send原理剖析 send是不是直接把数据发给服务端? 不是&#xff0c;要想发数据&#xff0c;必须得…

【SpringMVC】SpringMVC的请求与响应

文章目录 0. Tomcat环境的配置1. PostMan工具介绍创建WorkSpace建立新的请求 2. 请求映射路径案例结构与代码案例结构案例代码 案例存在问题解决方案方法方法升级版——配置请求路径前缀注解总结 3. Get请求与Post请求案例结构与案例代码案例结构案例代码 Get请求Post请求接收中…

3. BlazorSignalRApp 结合使用 ASP.NET Core SignalR 和 Blazor

参考&#xff1a;https://learn.microsoft.com/zh-cn/aspnet/core/blazor/tutorials/signalr-blazor?viewaspnetcore-8.0&tabsvisual-studio 1.创建新项目 BlazorSignalRApp 2.添加项目依赖项 依赖项&#xff1a;Microsoft.AspNetCore.SignalR.Client 方式1 管理解决方案…

SOLIDWORKS Flow Simulation升力仿真分析

仿真飞车起飞和飞机起飞的原理相同,当等质量的空气同时通过机翼上表面和下表面时,会在机翼上下方形成不同流速,空气通过机翼上表面时流速大&#xff0c;压强较小;通过下表面时流速较小,压强大。此时飞车会受一个向上的合力,即向上的升力,空气速度越快,升力越大,当升力大于飞车重…

力扣每日一题day36[112.路径总和]

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指没有子节点…

SQL基础:查询的基本使用

上一节我们讲述了记录的基本操作&#xff0c;这一节我们来单独讲一下查询。 查询基本结构 首先我们来看下查询的基本结构 SELECTcolumn1,column2,... FROMtable_name [WHEREcondition] [GROUP BYcolumn1, column2, ...] [HAVINGaggregate_function(column) condition] [ORDE…

【算法】算法题-20231222

这里写目录标题 一、1002. 查找共用字符二、1047. 删除字符串中的所有相邻重复项三、面试题 01.04. 回文排列 一、1002. 查找共用字符 给你一个字符串数组 words &#xff0c;请你找出所有在 words 的每个字符串中都出现的共用字符&#xff08; 包括重复字符&#xff09;&…

SpringIOC之MethodBasedEvaluationContext

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

React和umi搭建项目的操作步骤

​​​​​​一、react脚手架新建项目 (1.1)、命令行 前提&#xff1a;react ES2015,nodejs v8 npx create-react-app myReactName //2022年v16以下版本 myReactName(自定义项目名) react中文官网&#xff0c;快速上手&#xff1a;react中文官网 react框架&#xff0c;…

基于Linphone android sdk开发Android软话机

1.Linphone简介 1.1 简介 LinPhone是一个遵循GPL协议的开源网络电话或者IP语音电话&#xff08;VOIP&#xff09;系统&#xff0c;其主要如下。使用linphone&#xff0c;开发者可以在互联网上随意的通信&#xff0c;包括语音、视频、即时文本消息。linphone使用SIP协议&#…

CGAL的3D Alpha Shapes

假设我们给定一个二维或三维的点集S&#xff0c;我们希望得到类似“这些点形成的形状”的东西。这是一个相当模糊的概念&#xff0c;可能有许多可能的解释&#xff0c;阿尔法形状就是其中之一。阿尔法形状可用于从密集的无组织数据点集进行形状重建。事实上&#xff0c;阿尔法形…