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

目录

[12.4.2 在屏幕上绘制飞船](#12.4.2 在屏幕上绘制飞船)

alien_invasion.py

[​编辑12.5 重构:模块 game_functions](#编辑12.5 重构:模块 game_functions)

[12.5.1 函数 check_events()](#12.5.1 函数 check_events())

game_functions.py

alien_invasion.py

[12.5.2 函数 update_screen()](#12.5.2 函数 update_screen())

game_functions.py

alien_invasion.py

[12.6 驾驶飞船](#12.6 驾驶飞船)

[12.6.1 响应按键](#12.6.1 响应按键)

[game_ functions.py](#game_ functions.py)

alien_invasion.py

[12.6.2 允许不断移动](#12.6.2 允许不断移动)

ship.py

game_functions.py

alien_invasion.py

[12.6.3 左右移动](#12.6.3 左右移动)

ship.py

game_functions.py

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

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


12.4.2 在屏幕上绘制飞船

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

alien_invasion.py
python 复制代码
--snip--
from settings import Settings
from ship import Ship
def run_game():
 --snip--
 pygame.display.set_caption("Alien Invasion")
 # 创建一艘飞船
1 ship = Ship(screen)
 # 开始游戏主循环
 while True:
 --snip--
 # 每次循环时都重绘屏幕
 screen.fill(ai_settings.bg_color)
2 ship.blitme()
 # 让最近绘制的屏幕可见
 pygame.display.flip()
run_game()

我们导入Ship类,并在创建屏幕后创建一个名为ship的Ship实例。必须在主while循环前面创 建该实例(见1),以免每次循环时都创建一艘飞船。填充背景后,我们调用ship.blitme()将飞 船绘制到屏幕上,确保它出现在背景前面(见2)。 现在如果运行alien_invasion.py,将看到飞船位于空游戏屏幕底部中央,如图12-2所示。

12.5 重构:模块 game_functions

在大型项目中,经常需要在添加新代码前重构既有代码。重构旨在简化既有代码的结构,使 其更容易扩展。在本节中,我们将创建一个名为game_functions的新模块,它将存储大量让游戏 《外星人入侵》运行的函数。通过创建模块game_functions,可避免alien_invasion.py太长,并使 其逻辑更容易理解。

12.5.1 函数 check_events()

我们将首先把管理事件的代码移到一个名为check_events()的函数中,以简化run_game()并 隔离事件管理循环。通过隔离事件循环,可将事件管理与游戏的其他方面(如更新屏幕)分离。 将check_events()放在一个名为game_functions的模块中:

game_functions.py
python 复制代码
import sys
import pygame
def check_events():
 """响应按键和鼠标事件"""
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 sys.exit() 

这个模块中导入了事件检查循环要使用的sys和pygame。当前,函数check_events()不需要任 何形参,其函数体复制了alien_invasion.py的事件循环。 下面来修改alien_invasion.py,使其导入模块game_functions,并将事件循环替换为对函数 check_events()的调用:

alien_invasion.py
python 复制代码
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():
 --snip--
 # 开始游戏主循环
 while True:
 gf.check_events()
 # 让最近绘制的屏幕可见
 --snip-- 

在主程序文件中,不再需要直接导入sys,因为当前只在模块game_functions中使用了它。出 于简化的目的,我们给导入的模块game_functions指定了别名gf。

12.5.2 函数 update_screen()

为进一步简化run_game(),下面将更新屏幕的代码移到一个名为update_screen()的函数中, 并将这个函数放在模块game_functions.py中:

game_functions.py
python 复制代码
--snip--
def check_events():
 --snip--
def update_screen(ai_settings, screen, ship):
 """更新屏幕上的图像,并切换到新屏幕"""
 # 每次循环时都重绘屏幕
 screen.fill(ai_settings.bg_color)
 ship.blitme()
 # 让最近绘制的屏幕可见
 pygame.display.flip()

新函数 update_screen() 包含三个形参: ai_settings 、 screen 和 ship 。现在需要将 alien_invasion.py的while循环中更新屏幕的代码替换为对函数update_screen()的调用:

alien_invasion.py
python 复制代码
--snip--
 # 开始游戏主循环
 while True:
 gf.check_events()
 gf.update_screen(ai_settings, screen, ship)
run_game()

这两个函数让while循环更简单,并让后续开发更容易:在模块game_functions而不是 run_game()中完成大部分工作。 鉴于我们一开始只想使用一个文件,因此没有立刻引入模块game_functions。这让你能够了 解实际的开发过程:一开始将代码编写得尽可能简单,并在项目越来越复杂时进行重构。 对代码进行重构使其更容易扩展后,可以开始处理游戏的动态方面了!

12.6 驾驶飞船

下面来让玩家能够左右移动飞船。为此,我们将编写代码,在用户按左或右箭头键时作出响 应。我们将首先专注于向右移动,再使用同样的原理来控制向左移动。通过这样做,你将学会如 何控制屏幕图像的移动。

12.6.1 响应按键

每当用户按键时,都将在Pygame中注册一个事件。事件都是通过方法pygame.event.get()获 取的,因此在函数check_events()中,我们需要指定要检查哪些类型的事件。每次按键都被注册 为一个KEYDOWN事件。 检测到KEYDOWN事件时,我们需要检查按下的是否是特定的键。例如,如果按下的是右箭头 键,我们就增大飞船的rect.centerx值,将飞船向右移动:

game_ functions.py
python 复制代码
def check_events(ship):
 """响应按键和鼠标事件"""
for event in pygame.event.get():
 if event.type == pygame.QUIT:
 sys.exit()
1 elif event.type == pygame.KEYDOWN:
2 if event.key == pygame.K_RIGHT:
 #向右移动飞船
3 ship.rect.centerx += 1

我们在函数check_events()中包含形参ship,因为玩家按右箭头键时,需要将飞船向右移动。 在函数check_events()内部,我们在事件循环中添加了一个elif代码块,以便在Pygame 检测到 KEYDOWN事件时作出响应(见)。我们读取属性event.key,以检查按下的是否是右箭头键 (pygame.K_RIGHT)(见)。如果按下的是右箭头键,就将ship.rect.centerx的值加1,从而将飞 船向右移动(见)。 在alien_invasion.py中,我们需要更新调用的check_events()代码,将ship作为实参传递给它:

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

如果现在运行alien_invasion.py,则每按右箭头键一次,飞船都将向右移动1像素。这是一个 开端,但并非控制飞船的高效方式。下面来改进控制方式,允许持续移动。

12.6.2 允许不断移动

玩家按住右箭头键不放时,我们希望飞船不断地向右移动,直到玩家松开为止。我们将让游 戏检测pygame.KEYUP事件,以便玩家松开右箭头键时我们能够知道这一点;然后,我们将结合使 用KEYDOWN和KEYUP事件,以及一个名为moving_right的标志来实现持续移动。 飞船不动时,标志moving_right将为False。玩家按下右箭头键时,我们将这个标志设置为 True;而玩家松开时,我们将这个标志重新设置为False。 飞船的属性都由Ship类控制,因此我们将给这个类添加一个名为moving_right的属性和一个 名为update()的方法。方法update()检查标志moving_right的状态,如果这个标志为True,就调 整飞船的位置。每当需要调整飞船的位置时,我们都调用这个方法。 下面是对Ship类所做的修改:

ship.py
python 复制代码
class Ship():
 def __init__(self, screen):
 --snip--
 # 将每艘新飞船放在屏幕底部中央
 self.rect.centerx = self.screen_rect.centerx
 self.rect.bottom = self.screen_rect.bottom
 # 移动标志
1 self.moving_right = False
2 def update(self):
 """根据移动标志调整飞船的位置"""
 if self.moving_right:
 self.rect.centerx += 1
 def blitme(self):
 --snip-- 

在方法__init__()中,我们添加了属性self.moving_right,并将其初始值设置为False(见)。 接下来,我们添加了方法update(),它在前述标志为True时向右移动飞船(见)。 下面来修改check_events(),使其在玩家按下右箭头键时将moving_right设置为True,并在 玩家松开时将moving_right设置为False:

game_functions.py
python 复制代码
def check_events(ship):
 """响应按键和鼠标事件"""
 for event in pygame.event.get():
 --snip--
 elif event.type == pygame.KEYDOWN:
 if event.key == pygame.K_RIGHT:
1 ship.moving_right = True
2 elif event.type == pygame.KEYUP:
 if event.key == pygame.K_RIGHT:
 ship.moving_right = False 

在处,我们修改了游戏在玩家按下右箭头键时响应的方式:不直接调整飞船的位置,而只 是将moving_right设置为True。在处,我们添加了一个新的elif代码块,用于响应KEYUP事件: 玩家松开右箭头键(K_RIGHT)时,我们将moving_right设置为False。 最后,我们需要修改alien_invasion.py中的while循环,以便每次执行循环时都调用飞船的 方法update():

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

飞船的位置将在检测到键盘事件后(但在更新屏幕前)更新。这样,玩家输入时,飞船的位 置将更新,从而确保使用更新后的位置将飞船绘制到屏幕上。如果你现在运行alien_invasion.py并按住右箭头键,飞船将不断地向右移动,直到你松开为止。

12.6.3 左右移动

飞船能够不断地向右移动后,添加向左移动的逻辑很容易。我们将再次修改Ship类和函数 check_events()。下面显示了对Ship类的方法__init__()和update()所做的相关修改:

ship.py
python 复制代码
 def __init__(self, screen):
 --snip--
 # 移动标志
 self.moving_right = False
 self.moving_left = False
 def update(self):
 """根据移动标志调整飞船的位置"""
 if self.moving_right:
 self.rect.centerx += 1
 if self.moving_left:
 self.rect.centerx -= 1

在方法__init__()中,我们添加了标志self.moving_left;在方法update()中,我们添加了一 个if代码块而不是elif代码块,这样如果玩家同时按下了左右箭头键,将先增大飞船的 rect.centerx值,再降低这个值,即飞船的位置保持不变。如果使用一个elif代码块来处理向左 移动的情况,右箭头键将始终处于优先地位。从向左移动切换到向右移动时,玩家可能同时按住 左右箭头键,在这种情况下,前面的做法让移动更准确。 我们还需对check_events()作两方面的调整:

game_functions.py
python 复制代码
def check_events(ship):
 """响应按键和鼠标事件"""
 for event in pygame.event.get():
 --snip--
 elif event.type == pygame.KEYDOWN:
 if event.key == pygame.K_RIGHT:
 ship.moving_right = True
 elif event.key == pygame.K_LEFT:
 ship.moving_left = True
 elif event.type == pygame.KEYUP:
 if event.key == pygame.K_RIGHT:
 ship.moving_right = False
 elif event.key == pygame.K_LEFT:
 ship.moving_left = False 

如果因玩家按下K_LEFT键而触发了KEYDOWN事件,我们就将moving_left设置为True;如果因 玩家松开K_LEFT而触发了KEYUP事件,我们就将moving_left设置为False。这里之所以可以使用elif代码块,是因为每个事件都只与一个键相关联;如果玩家同时按下了左右箭头键,将检测到 两个不同的事件。 如果此时运行alien_invasion.py,将能够不断地左右移动飞船;如果你同时按左右箭头键,飞 船将纹丝不动。 下面来进一步优化飞船的移动方式:调整飞船的速度;限制飞船的移动距离,以免它移到屏 幕外面去。


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

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

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

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

相关推荐
培根芝士3 分钟前
使用Scripting API获取CS2游戏数据
python·游戏
阿杰同学5 分钟前
Java 设计模式 面试题及答案整理,最新面试题
java·开发语言·设计模式
这样の我5 分钟前
java 模拟chrome指纹 处理tls extension顺序
java·开发语言·chrome
yong99907 分钟前
基于MATLAB的雷达压制干扰仿真
开发语言·matlab
catchadmin18 分钟前
现代高效 PHP 开发的最佳实践
开发语言·后端·php
AnAnCode21 分钟前
【时间轮算法-实战】Java基于Netty的 `HashedWheelTimer`快速搭建时间轮算法系统
java·开发语言·算法·时间轮算法
CesareCheung23 分钟前
用python写一个websocket接口,并用jmeter压测websocket接口
python·websocket·jmeter
liu****31 分钟前
12.C语言内存相关函数
c语言·开发语言·数据结构·c++·算法
喜乐boy1 小时前
CV系列——Conda + PyTorch + CUDA + cuDNN + Python 环境无脑安装速查笔记[2025.12]
pytorch·python·conda·cuda·cv
@游子1 小时前
Python学习笔记-Day6
笔记·python·学习