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

目录

[13.4.4 向下移动外星人群并改变移动方向](#13.4.4 向下移动外星人群并改变移动方向)

game_functions.py

alien_invasion.py

[13.5 射杀外星人](#13.5 射杀外星人)

[13.5.1 检测子弹与外星人的碰撞](#13.5.1 检测子弹与外星人的碰撞)

game_functions.py

alien_invasion.py

[13.5.2 为测试创建大子弹](#13.5.2 为测试创建大子弹)

[13.5.3 生成新的外星人群](#13.5.3 生成新的外星人群)

game_functions.py

alien_invasion.py

[13.5.4 提高子弹的速度](#13.5.4 提高子弹的速度)

settings.py

[13.5.5 重构 update_bullets()](#13.5.5 重构 update_bullets())

game_functions.py

[13.6 结束游戏](#13.6 结束游戏)

[13.6.1 检测外星人和飞船碰撞](#13.6.1 检测外星人和飞船碰撞)

game_functions.py

alien_invasion.py

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!


13.4.4 向下移动外星人群并改变移动方向

有外星人到达屏幕边缘时,需要将整群外星人下移,并改变它们的移动方向。我们需要对 game_functions.py做重大修改,因为我们要在这里检查是否有外星人到达了左边缘或右边缘。为此, 我们编写函数check_fleet_edges()和change_fleet_direction(),并对update_aliens()进行修改:

game_functions.py
python 复制代码
def check_fleet_edges(ai_settings, aliens):
 """有外星人到达边缘时采取相应的措施"""
1 for alien in aliens.sprites():
 if alien.check_edges():
 change_fleet_direction(ai_settings, aliens)
 break
def change_fleet_direction(ai_settings, aliens):
 """将整群外星人下移,并改变它们的方向"""
 for alien in aliens.sprites():
2 alien.rect.y += ai_settings.fleet_drop_speed
 ai_settings.fleet_direction *= -1
def update_aliens(ai_settings, aliens):
 """
 检查是否有外星人位于屏幕边缘,并更新整群外星人的位置
 """
3 check_fleet_edges(ai_settings, aliens)
 aliens.update() 

在check_fleet_edges()中,我们遍历外星人群,并对其中的每个外星人调用check_edges() (见1)。如果check_edges()返回True,我们就知道相应的外星人位于屏幕边缘,需要改变外星人 群的方向,因此我们调用change_fleet_direction()并退出循环。在change_fleet_direction()中, 我们遍历所有外星人,将每个外星人下移fleet_drop_speed设置的值(见2);然后,将fleet_ direction的值修改为其当前值与1的乘积。

我们修改了函数update_aliens(),在其中通过调用check_fleet_edges()来确定是否有外星人 位于屏幕边缘。现在,函数update_aliens()包含形参ai_settings,因此我们调用它时指定了与 ai_settings对应的实参:

alien_invasion.py
python 复制代码
# 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
 gf.update_bullets(bullets)
 gf.update_aliens(ai_settings, aliens)
 gf.update_screen(ai_settings, screen, ship, aliens, bullets)

如果你现在运行这个游戏,外星人群将在屏幕上来回移动,并在抵达屏幕边缘后向下移动。 现在可以开始射杀外星人,检查是否有外星人撞到飞船,或抵达了屏幕底端。

13.5 射杀外星人

我们创建了飞船和外星人群,但子弹击中外星人时,将穿过外星人,因为我们还没有检查碰 撞。在游戏编程中,碰撞指的是游戏元素重叠在一起。要让子弹能够击落外星人,我们将使用 sprite.groupcollide()检测两个编组的成员之间的碰撞。

13.5.1 检测子弹与外星人的碰撞

子弹击中外星人时,我们要马上知道,以便碰撞发生后让外星人立即消失。为此,我们将在 更新子弹的位置后立即检测碰撞。 方法sprite.groupcollide()将每颗子弹的rect同每个外星人的rect进行比较,并返回一个字 典,其中包含发生了碰撞的子弹和外星人。在这个字典中,每个键都是一颗子弹,而相应的值都 是被击中的外星人(第14章实现记分系统时,也会用到这个字典)。 在函数update_bullets()中,使用下面的代码来检查碰撞:

game_functions.py
python 复制代码
def update_bullets(aliens, bullets):
 """更新子弹的位置,并删除已消失的子弹"""
 --snip--
 # 检查是否有子弹击中了外星人
 # 如果是这样,就删除相应的子弹和外星人
 collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

新增的这行代码遍历编组bullets中的每颗子弹,再遍历编组aliens中的每个外星人。每当 有子弹和外星人的rect重叠时,groupcollide()就在它返回的字典中添加一个键值对。两个实参True告诉Pygame删除发生碰撞的子弹和外星人。(要模拟能够穿行到屏幕顶端的高能子弹------消 灭它击中的每个外星人,可将第一个布尔实参设置为False,并让第二个布尔实参为True。这样 被击中的外星人将消失,但所有的子弹都始终有效,直到抵达屏幕顶端后消失。) 我们调用update_bullets()时,传递了实参aliens:

alien_invasion.py
python 复制代码
# 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, ship, bullets)
 ship.update()
 gf.update_bullets(aliens, bullets)
 gf.update_aliens(ai_settings, aliens)
 gf.update_screen(ai_settings, screen, ship, aliens, bullets) 

如果你此时运行这个游戏,被击中的外星人将消失。如图13-5所示,其中有一部分外星人被 击落。


13.5.2 为测试创建大子弹

只需通过运行这个游戏就可以测试其很多功能,但有些功能在正常情况下测试起来比较烦 琐。例如,要测试代码能否正确地处理外星人编组为空的情形,需要花很长时间将屏幕上的外星 人都击落。测试有些功能时,可以修改游戏的某些设置,以便专注于游戏的特定方面。例如,可以缩小屏 幕以减少需要击落的外星人数量,也可以提高子弹的速度,以便能够在单位时间内发射大量子弹。

测试这个游戏时,我喜欢做的一项修改是增大子弹的尺寸,使其在击中外星人后依然有效, 如图13-6所示。请尝试将bullet_width设置为300,看看将所有外星人都射杀有多快! 类似这样的修改可提高测试效率,还可能激发出如何赋予玩家更大威力的思想火花。(完成 测试后,别忘了将设置恢复正常。)


13.5.3 生成新的外星人群

这个游戏的一个重要特点是外星人无穷无尽,一个外星人群被消灭后,又会出现一群外星人。 要在外星人群被消灭后又显示一群外星人,首先需要检查编组aliens是否为空。如果为空, 就调用create_fleet()。我们将在update_bullets()中执行这种检查,因为外星人都是在这里被 消灭的:

game_functions.py
python 复制代码
def update_bullets(ai_settings, screen, ship, aliens, bullets):
 --snip--
 # 检查是否有子弹击中了外星人
 # 如果是,就删除相应的子弹和外星人
 collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
1 if len(aliens) == 0:
 # 删除现有的子弹并新建一群外星人
2 bullets.empty()
 create_fleet(ai_settings, screen, ship, aliens)

在1处,我们检查编组aliens是否为空。如果是,就使用方法empty()删除编组中余下的所 有精灵,从而删除现有的所有子弹。我们还调用了create_fleet(),再次在屏幕上显示一群外 星人。 现在,update_bullets()的定义包含额外的形参ai_settings、screen和ship,因此我们需要 更新alien_invasion.py中对update_bullets()的调用:

alien_invasion.py
python 复制代码
# 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, ship, bullets)
 ship.update()
 gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
 gf.update_aliens(ai_settings, aliens)
 gf.update_screen(ai_settings, screen, ship, aliens, bullets) 

现在,当前外星人群消灭干净后,将立刻出现一个新的外星人群.

13.5.4 提高子弹的速度

如果你现在尝试在这个游戏中射杀外星人,可能发现子弹的速度比以前慢,这是因为在每次 循环中, Pygame 需要做的工作更多了。为提高子弹的速度,可调整 settings.py 中 bullet_speed_factor的值。例如,如果将这个值增大到3,子弹在屏幕上向上穿行的速度将变得 相当快:

settings.py
python 复制代码
 # 子弹设置
 self.bullet_speed_factor = 3
 self.bullet_width = 3
 --snip-- 

这项设置的最佳值取决于你的系统速度,请找出适合你的值吧。

13.5.5 重构 update_bullets()

下面来重构update_bullets(),使其不再完成那么多任务。我们将把处理子弹和外星人碰撞 的代码移到一个独立的函数中:

game_functions.py
python 复制代码
def update_bullets(ai_settings, screen, ship, aliens, bullets):
 --snip
 # 删除已消失的子弹
 for bullet in bullets.copy():
 if bullet.rect.bottom <= 0:
 bullets.remove(bullet)
 check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets)
def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):
 """响应子弹和外星人的碰撞"""
 # 删除发生碰撞的子弹和外星人
 collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
 if len(aliens) == 0:
 # 删除现有的所有子弹,并创建一个新的外星人群
 bullets.empty()
 create_fleet(ai_settings, screen, ship, aliens)

我们创建了一个新函数------check_bullet_alien_collisions(),以检测子弹和外星人之间的 碰撞,以及在整群外星人都被消灭干净时采取相应的措施。这避免了update_bullets()太长,简 化了后续的开发工作。

13.6 结束游戏

如果玩家根本不会输,游戏还有什么趣味和挑战性可言?如果玩家没能在足够短的时间内将 整群外星人都消灭干净,且有外星人撞到了飞船,飞船将被摧毁。与此同时,我们还限制了可供 玩家使用的飞船数,而有外星人抵达屏幕底端时,飞船也将被摧毁。玩家用光了飞船后,游戏便 结束。

13.6.1 检测外星人和飞船碰撞

我们首先检查外星人和飞船之间的碰撞,以便外星人撞上飞船时我们能够作出合适的响应。 我们在更新每个外星人的位置后立即检测外星人和飞船之间的碰撞。

game_functions.py
python 复制代码
def update_aliens(ai_settings, ship, aliens):
 """ 
检查是否有外星人到达屏幕边缘
 然后更新所有外星人的位置
 """
 check_fleet_edges(ai_settings, aliens)
 aliens.update()
 # 检测外星人和飞船之间的碰撞
1 if pygame.sprite.spritecollideany(ship, aliens):
2 print("Ship hit!!!") 

方法spritecollideany()接受两个实参:一个精灵和一个编组。它检查编组是否有成员与精 灵发生了碰撞,并在找到与精灵发生了碰撞的成员后就停止遍历编组。在这里,它遍历编组 aliens,并返回它找到的第一个与飞船发生了碰撞的外星人。 如果没有发生碰撞,spritecollideany()将返回None,因此Ø处的if代码块不会执行。如果 找到了与飞船发生碰撞的外星人,它就返回这个外星人,因此if代码块将执行:打印"Ship hit!!!" (见)。(有外星人撞到飞船时,需要执行的任务很多:需要删除余下的所有外星人和子弹,让 飞船重新居中,以及创建一群新的外星人。编写完成这些任务的代码前,需要确定检测外星人和 飞船碰撞的方法是否可行。而为确定这一点,最简单的方式是编写一条print语句。) 现在,我们需要将ship传递给update_aliens():

alien_invasion.py
python 复制代码
# 开始游戏主循环
 while True:
 gf.check_events(ai_settings, screen, ship, bullets)
 ship.update()
 gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
 gf.update_aliens(ai_settings, ship, aliens)
 gf.update_screen(ai_settings, screen, ship, aliens, bullets)

现在如果你运行这个游戏,则每当有外星人撞到飞船时,终端窗口都将显示"Ship hit!!!"。 测试这项功能时,请将alien_drop_speed设置为较大的值,如50或100,这样外星人将更快地撞到 飞船。


关于"Python"的核心知识点整理大全25-CSDN博客

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!

相关推荐
卷毛的技术笔记35 分钟前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥35 分钟前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog37 分钟前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008111 小时前
FastAPI APIRouter
开发语言·python
Benszen1 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆1 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木1 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r1 小时前
Java调用链MCP分析工具
java·python·ai编程
Oll Correct1 小时前
实验二十九:TCP的运输连接管理
网络·笔记
杨充1 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法