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

简介: 关于“Python”的核心知识点整理大全33

bed3f16847a8b4ee1bba45c403f3668c_dfe7b6d33bc94ac0931266c9837fed8d.png

12.8.3 将子弹存储到编组中

定义Bullet类和必要的设置后,就可以编写代码了,在玩家每次按空格键时都射出一发子弹。 首先,我们将在alien_invasion.py中创建一个编组(group),用于存储所有有效的子弹,以便能够 管理发射出去的所有子弹。这个编组将是pygame.sprite.Group类的一个实例;pygame.sprite. Group类类似于列表,但提供了有助于开发游戏的额外功能。在主循环中,我们将使用这个编组 在屏幕上绘制子弹,以及更新每颗子弹的位置:

alien_invasion.py

import pygame
from pygame.sprite import Group
--snip--
def run_game():
 --snip--
 # 创建一艘飞船
 ship = Ship(ai_settings, screen)
 # 创建一个用于存储子弹的编组
1 bullets = Group()
 # 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, ship, bullets)
 ship.update()
2 bullets.update()
 gf.update_screen(ai_settings, screen, ship, bullets)
run_game()

我们导入了pygame.sprite中的Group类。在1处,我们创建了一个Group实例,并将其命名为 bullets。这个编组是在while循环外面创建的,这样就无需每次运行该循环时都创建一个新的子 弹编组。


注意

如果在循环内部创建这样的编组,游戏运行时将创建数千个子弹编组,导致游戏慢得像 蜗牛。如果游戏停滞不前,请仔细查看主while循环中发生的情况。


我们将bullets传递给了check_events()和update_screen()。在check_events()中,需要在玩 家按空格键时处理bullets;而在update_screen()中,需要更新要绘制到屏幕上的bullets。 当你对编组调用update()时,编组将自动对其中的每个精灵调用update(),因此代码行 bullets.update()将为编组bullets中的每颗子弹调用bullet.update()。

12.8.4 开火

在game_functions.py中,我们需要修改check_keydown_events(),以便在玩家按空格键时发射 一颗子弹。我们无需修改check_keyup_events(),因为玩家松开空格键时什么都不会发生。我们 还需修改update_screen(),确保在调用flip()前在屏幕上重绘每颗子弹。下面是对game_ functions.py所做的相关修改:

game_functions.py

--snip--
from bullet import Bullet
1 def check_keydown_events(event, ai_settings, screen, ship, bullets):
 --snip--
2 elif event.key == pygame.K_SPACE:
 # 创建一颗子弹,并将其加入到编组bullets中
 new_bullet = Bullet(ai_settings, screen, ship)
 bullets.add(new_bullet)
 --snip--
3 def check_events(ai_settings, screen, ship, bullets):
 """响应按键和鼠标事件"""
 for event in pygame.event.get():
 --snip--
 elif event.type == pygame.KEYDOWN:
 check_keydown_events(event, ai_settings, screen, ship, bullets)
 --snip--
4 def update_screen(ai_settings, screen, ship, bullets):
 --snip--
 # 在飞船和外星人后面重绘所有子弹
5 for bullet in bullets.sprites():
 bullet.draw_bullet()
 ship.blitme()
 --snip--

编组bulltes传递给了check_keydown_events()(见1)。玩家按空格键时,创建一颗新子弹(一 个名为new_bullet的Bullet实例),并使用方法add()将其加入到编组bullets中(见2);代码 bullets.add(new_bullet)将新子弹存储到编组bullets中。

在check_events()的定义中,我们需要添加形参bullets(见3);调用check_keydown_events() 时,我们也需要将bullets作为实参传递给它。 在 4 处,我们给在屏幕上绘制子弹的 update_screen() 添加了形参 bullets 。方法 bullets.sprites()返回一个列表,其中包含编组bullets中的所有精灵。为在屏幕上绘制发射的 所有子弹,我们遍历编组bullets中的精灵,并对每个精灵都调用draw_bullet()(见5)。 如果此时运行alien_invasion.py,将能够左右移动飞船,并发射任意数量的子弹。子弹在屏 幕上向上穿行,抵达屏幕顶部后消失,如图12-3所示。可在settings.py中修改子弹的尺寸、颜色和 速度。

02e34e3ad043a91389ad1f404b587b58_8ccf617e23694f048a6384804b64bd4a.png

12.8.5 删除已消失的子弹

当前,子弹抵达屏幕顶端后消失,这仅仅是因为Pygame无法在屏幕外面绘制它们。这些子 弹实际上依然存在,它们的y坐标为负数,且越来越小。这是个问题,因为它们将继续消耗内存 和处理能力。 我们需要将这些已消失的子弹删除,否则游戏所做的无谓工作将越来越多,进而变得越来越 慢。为此,我们需要检测这样的条件,即表示子弹的rect的bottom属性为零,它表明子弹已穿过 屏幕顶端:

alien_invasion.py

# 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, ship, bullets)
 ship.update()
 bullets.update()
 # 删除已消失的子弹
1 for bullet in bullets.copy():
2 if bullet.rect.bottom <= 0:
3 bullets.remove(bullet)
4 print(len(bullets))
 gf.update_screen(ai_settings, screen, ship, bullets)

在for循环中,不应从列表或编组中删除条目,因此必须遍历编组的副本。我们使用了方法 copy()来设置for循环(见1),这让我们能够在循环中修改bullets。我们检查每颗子弹,看看它 是否已从屏幕顶端消失(2)。如果是这样,就将其从bullets中删除(见3)。在4处,我们使 用了一条print语句,以显示当前还有多少颗子弹,从而核实已消失的子弹确实删除了。 如果这些代码没有问题,我们发射子弹后查看终端窗口时,将发现随着子弹一颗颗地在屏幕 顶端消失,子弹数将逐渐降为零。运行这个游戏并确认子弹已被删除后,将这条print语句删除。 如果你留下这条语句,游戏的速度将大大降低,因为将输出写入到终端而花费的时间比将图形绘 制到游戏窗口花费的时间还多。

12.8.6 限制子弹数量

很多射击游戏都对可同时出现在屏幕上的子弹数量进行限制,以鼓励玩家有目标地射击。下 面在游戏《外星人入侵》中作这样的限制。 首先,在settings.py中存储所允许的最大子弹数:

settings.py

这将未消失的子弹数限制为3颗。在game_functions.py的check_keydown_events()中,我们在 创建新子弹前检查未消失的子弹数是否小于该设置:

game_functions.py

def check_keydown_events(event, ai_settings, screen, ship, bullets):
 --snip--
 elif event.key == pygame.K_SPACE:
 # 创建新子弹并将其加入到编组bullets中
 if len(bullets) < ai_settings.bullets_allowed:
 new_bullet = Bullet(ai_settings, screen, ship)
 bullets.add(new_bullet)

玩家按空格键时,我们检查bullets的长度。如果len(bullets)小于3,我们就创建一个新子 弹;但如果已有3颗未消失的子弹,则玩家按空格键时什么都不会发生。如果你现在运行这个游 戏,屏幕上最多只能有3颗子弹。

12.8.7 创建函数 update_bullets()

编写并检查子弹管理代码后,可将其移到模块game_functions中,以让主程序文件 alien_invasion.py尽可能简单。我们创建一个名为update_bullets()的新函数,并将其添加到game_functions.py的末尾:

game_functions.py

def update_bullets(bullets):
 """更新子弹的位置,并删除已消失的子弹"""
 # 更新子弹的位置
 bullets.update()
 # 删除已消失的子弹
 for bullet in bullets.copy():
 if bullet.rect.bottom <= 0:
 bullets.remove(bullet)

update_bullets()的代码是从alien_invasion.py剪切并粘贴而来的,它只需要一个参数,即编 组bullets。 alien_invasion.py中的while循环又变得很简单了:

alien_invasion.py

# 开始游戏主循环
 while True:
1 gf.check_events(ai_settings, screen, ship, bullets)
2 ship.update()
3 gf.update_bullets(bullets)
4 gf.update_screen(ai_settings, screen, ship, bullets)

我们让主循环包含尽可能少的代码,这样只要看函数名就能迅速知道游戏中发生的情况。主 循环检查玩家的输入(见1),然后更新飞船的位置(见2)和所有未消失的子弹的位置(见3)。 接下来,我们使用更新后的位置来绘制新屏幕(见4)。

12.8.8 创建函数 fire_bullet()

下面将发射子弹的代码移到一个独立的函数中,这样,在check_keydown_events()中只需使 用一行代码来发射子弹,让elif代码块变得非常简单:

game_functions.py

def check_keydown_events(event, ai_settings, screen, ship, bullets):
 """响应按键"""
 --snip--
 elif event.key == pygame.K_SPACE:
 fire_bullet(ai_settings, screen, ship, bullets)
def fire_bullet(ai_settings, screen, ship, bullets):
 """如果还没有到达限制,就发射一颗子弹"""
 #创建新子弹,并将其加入到编组bullets中
 if len(bullets) < ai_settings.bullets_allowed:
 new_bullet = Bullet(ai_settings, screen, ship)
 bullets.add(new_bullet)

函数fire_bullet()只包含玩家按空格键时用于发射子弹的代码;在check_keydown_events() 中,我们在玩家按空格键时调用fire_bullet()。 请再次运行alien_invasion.py,确认发射子弹时依然没有错误

12.9 小结

在本章中,你学习了:游戏开发计划的制定;使用Pygame编写的游戏的基本结构;如何设 置背景色,以及如何将设置存储在可供游戏的各个部分访问的独立类中;如何在屏幕上绘制图像, 以及如何让玩家控制游戏元素的移动;如何创建自动移动的元素,如在屏幕中向上飞驰的子弹, 以及如何删除不再需要的对象;如何定期重构项目的代码,为后续开发提供便利。 在第13章中,我们将在游戏《外星人入侵》中添加外星人。在第13章结束时,你将能够击落 外星人——但愿是在他们撞到飞船前!

目录
相关文章
|
1月前
|
测试技术 API Python
【10月更文挑战第1天】python知识点100篇系列(13)-几种方法让你的电脑一直在工作
【10月更文挑战第1天】 本文介绍了如何通过Python自动操作鼠标或键盘使电脑保持活跃状态,避免自动息屏。提供了三种方法:1) 使用PyAutoGUI,通过安装pip工具并执行`pip install pyautogui`安装,利用`moveRel()`方法定时移动鼠标;2) 使用Pymouse,通过`pip install pyuserinput`安装,采用`move()`方法移动鼠标绝对位置;3) 使用PyKeyboard,同样需安装pyuserinput,模拟键盘操作。文中推荐使用PyAutoGUI,因其功能丰富且文档详尽。
|
3月前
|
Python
python知识点
【8月更文挑战第27天】python知识点
3398 2
|
18天前
|
缓存 Java 索引
[Python]知识点
本文主要介绍了Python的一些高级知识点和使用细节,包括pip的使用、内置函数、列表、元组、字典、集合、变量、Lambda表达式、面向对象编程、异常处理、模块及标准库等。文章适合有一定Python基础的读者,重点在于深入理解和掌握Python的高级特性。文中还提供了大量示例代码,帮助读者更好地理解和应用这些知识点。
22 1
[Python]知识点
WK
|
3月前
|
存储 机器学习/深度学习 JSON
Python入门知识点
Python入门覆盖历史、设计理念、变量、数据类型、控制结构等。了解Python的发展,掌握动态类型的灵活性,熟悉整数、浮点数、字符串等数据类型。学会if/else、for/while循环构建逻辑流程,使用def定义函数,lambda快速创建匿名函数。通过类实现面向对象编程,利用模块和包组织代码。掌握try-except处理异常,open()进行文件操作。利用标准库和第三方库增强功能,理解集合、字典、列表推导式的应用,深入魔法方法、递归、装饰器等高级特性,以及上下文管理器和字符串、列表、元组的操作技巧。
WK
34 0
|
1月前
|
安全 Linux 数据安全/隐私保护
python知识点100篇系列(15)-加密python源代码为pyd文件
【10月更文挑战第5天】为了保护Python源码不被查看,可将其编译成二进制文件(Windows下为.pyd,Linux下为.so)。以Python3.8为例,通过Cython工具,先写好Python代码并加入`# cython: language_level=3`指令,安装easycython库后,使用`easycython *.py`命令编译源文件,最终生成.pyd文件供直接导入使用。
python知识点100篇系列(15)-加密python源代码为pyd文件
|
1月前
|
网络协议 数据库连接 Python
python知识点100篇系列(17)-替换requests的python库httpx
【10月更文挑战第4天】Requests 是基于 Python 开发的 HTTP 库,使用简单,功能强大。然而,随着 Python 3.6 的发布,出现了 Requests 的替代品 —— httpx。httpx 继承了 Requests 的所有特性,并增加了对异步请求的支持,支持 HTTP/1.1 和 HTTP/2,能够发送同步和异步请求,适用于 WSGI 和 ASGI 应用。安装使用 httpx 需要 Python 3.6 及以上版本,异步请求则需要 Python 3.8 及以上。httpx 提供了 Client 和 AsyncClient,分别用于优化同步和异步请求的性能。
python知识点100篇系列(17)-替换requests的python库httpx
|
1月前
|
调度 Python
python知识点100篇系列(20)-python协程与异步编程asyncio
【10月更文挑战第8天】协程(Coroutine)是一种用户态内的上下文切换技术,通过单线程实现代码块间的切换执行。Python中实现协程的方法包括yield、asyncio模块及async/await关键字。其中,async/await结合asyncio模块可更便捷地编写和管理协程,支持异步IO操作,提高程序并发性能。协程函数、协程对象、Task对象等是其核心概念。
|
28天前
|
Python Windows
python知识点100篇系列(24)- 简单强大的日志记录器loguru
【10月更文挑战第11天】Loguru 是一个功能强大的日志记录库,支持日志滚动、压缩、定时删除、高亮和告警等功能。安装简单,使用方便,可通过 `pip install loguru` 快速安装。支持将日志输出到终端或文件,并提供丰富的配置选项,如按时间或大小滚动日志、压缩日志文件等。还支持与邮件通知模块结合,实现邮件告警功能。
python知识点100篇系列(24)- 简单强大的日志记录器loguru
|
29天前
|
自然语言处理 Python Windows
python知识点100篇系列(23)- 使用stylecloud生成词云
【10月更文挑战第10天】`stylecloud` 是 `wordcloud` 的优化版,支持使用 Font Awesome 图标自定义词云形状,操作更简便。本文介绍如何安装 `jieba` 和 `stylecloud` 库,并使用它们生成中文词云。通过 `jieba` 进行分词,再利用 `stylecloud` 的 `gen_stylecloud` 方法生成具有特定形状和颜色的词云图像。
python知识点100篇系列(23)- 使用stylecloud生成词云
|
1月前
|
Java Python
> python知识点100篇系列(19)-使用python下载文件的几种方式
【10月更文挑战第7天】本文介绍了使用Python下载文件的五种方法,包括使用requests、wget、线程池、urllib3和asyncio模块。每种方法适用于不同的场景,如单文件下载、多文件并发下载等,提供了丰富的选择。
下一篇
无影云桌面