Python应用实例(一)外星人入侵(一)
1.概述
前面我们基本上介绍了python的基本操作,我们现在来开发一个名为《外星人入侵》的游戏吧!为此将使用Pygame,这是一组功能强大而有趣的模块,可用于管理图形、动画乃至声音,让你能够更轻松地开发复杂的游戏。通过使用Pygame来处理在屏幕上绘制图像等任务,可将重点放在程序的高级逻辑上。
在开发这款游戏的过程中,我们还将学习如何管理包含多个文件的项目。我们将重构很多代码并管理文件的内容,以确保项目组织有序以及提高效率。
开发游戏是趣学语言的理想方式。看别人玩你编写的游戏能获得满足感,而编写简单的游戏有助于你我们明白专业级游戏是怎么编写出来的。在阅读本章的过程中,请动手输入并运行代码,以明白各个代码块对整个游戏所做的贡献,并且尝试不同的值和设置,以对如何改进游戏的交互性有更深入的认识。
2.规划项目
开发大型项目时,制定好规划后再动手编写代码很重要。规划可确保你不偏离轨道,从而提高项目成功的可能性。
开发大型项目时,制定好规划后再动手编写代码很重要。规划可确保你不偏离轨道,从而提高项目成功的可能性。
游戏规则:
在游戏《外星人入侵》中,玩家控制一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船,还可使用空格键射击。游戏开始时,一群外星人出现在天空中,并向屏幕下方移动。玩家的任务是射杀这些外星人。玩家将所有外星人都消灭干净后,将出现一群新的外星人,其移动速度更快。只要有外星人撞到玩家的飞船或到达屏幕底部,玩家就损失一艘飞船。玩家损失三艘飞船后,游戏结束。
开发的第一个阶段将创建一艘飞船,它可左右移动,并且能在用户按空格键时开火。设置好这种行为后,就可以创建外星人并提高游戏的可玩性了。
3.安装Pygame
开始编码前,先来安装Pygame。可使用pip模块来帮助下载并安装Python包。要安装Pygame,在终端提示符下执行如下命令:
$ python -m pip install --user pygame
这个命令让Python运行pip模块,将pygame包添加到当前用户的Python安装中。如果你运行程序或启动终端会话时使用的命令不是python,而是python3,请执行如下命令来安装Pygame:
$ python3 -m pip install --user pygame
注意 如果该命令在macOS系统中不管用,请尝试在不指定标志–user的情况下再次执行。
4.开始游戏项目
开始开发游戏《外星人入侵》吧。首先要创建一个空的Pygame窗口,供之后用来绘制游戏元素,如飞船和外星人。我们还将让这个游戏响应用户输入,设置背景色,以及加载飞船图像。
4.1 创建Pygame窗口及响应用户输入
下面创建一个表示游戏的类,以创建空的Pygame窗口。为此,在文本编辑器中新建一个文件,将其保存为alien_invasion.py,再在其中输入如下代码:
import sys
import pygame
class AlienInvasion:
"""管理游戏资源和行为的类"""
def __init__(self):
"""初始化游戏并创建游戏资源。"""
❶ pygame.init()
❷ self.screen = pygame.display.set_mode((1200, 800))
pygame.display.set_caption("Alien Invasion")
def run_game(self):
"""开始游戏的主循环"""
❸ while True:
# 监视键盘和鼠标事件。
❹ for event in pygame.event.get():
❺ if event.type == pygame.QUIT:
sys.exit()
# 让最近绘制的屏幕可见。
❻ pygame.display.flip()
if __name__ == '__main__':
# 创建游戏实例并运行游戏。
ai = AlienInvasion()
ai.run_game()
首先,导入模块sys和pygame。模块pygame包含开发游戏所需的功能。玩家退出时,我们将使用模块sys中的工具来退出游戏。
为开发游戏《外星人入侵》,我们创建了一个表示它的类,名为AlienInvasion。在这个类的方法__init__()中,调用函数pygame.init()来初始化背景设置,让Pygame能够正确地工作(见❶)。在❷处,调用pygame.display.set_mode()来创建一个显示窗口,游戏的所有图形元素都将在其中绘制。实参(1200,800)是一个元组,指定了游戏窗口的尺寸——宽1200像素、高800像素(你可以根据自己的显示器尺寸调整这些值)。将这个显示窗口赋给属性self.screen,让这个类中的所有方法都能够使用它。
赋给属性self.screen的对象是一个surface。在Pygame中,surface是屏幕的一部分,用于显示游戏元素。在这个游戏中,每个元素(如外星人或飞船)都是一个surface。display.set_mode()返回的surface表示整个游戏窗口。激活游戏的动画循环后,每经过一次循环都将自动重绘这个surface,将用户输入触发的所有变化都反映出来。
这个游戏由方法run_game()控制。该方法包含一个不断运行的while循环(见❸),而这个循环包含一个事件循环以及管理屏幕更新的代码。事件是用户玩游戏时执行的操作,如按键或移动鼠标。为程序响应事件,可编写一个事件循环,以侦听事件并根据发生的事件类型执行合适的任务。❹处的for循环就是一个事件循环。
这个游戏由方法run_game()控制。该方法包含一个不断运行的while循环(见❸),而这个循环包含一个事件循环以及管理屏幕更新的代码。事件是用户玩游戏时执行的操作,如按键或移动鼠标。为程序响应事件,可编写一个事件循环,以侦听事件并根据发生的事件类型执行合适的任务。❹处的for循环就是一个事件循环。
这个游戏由方法run_game()控制。该方法包含一个不断运行的while循环(见❸),而这个循环包含一个事件循环以及管理屏幕更新的代码。事件是用户玩游戏时执行的操作,如按键或移动鼠标。为程序响应事件,可编写一个事件循环,以侦听事件并根据发生的事件类型执行合适的任务。❹处的for循环就是一个事件循环。
在这个文件末尾,创建一个游戏实例并调用run_game()。这些代码放在一个if代码块中,仅当直接运行该文件时,它们才会执行。如果此时运行alien_invasion.py,将看到一个空的Pygame窗口。
4.2 设置背景色
Pygame默认创建一个黑色屏幕,这太乏味了。下面来将背景设置为另一种颜色,这是在方法__init__()末尾进行的:
def __init__(self):
--snip--
pygame.display.set_caption("Alien Invasion")
# 设置背景色。
❶ self.bg_color = (230, 230, 230)
def run_game(self):
--snip--
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# 每次循环时都重绘屏幕。
❷ self.screen.fill(self.bg_color)
# 让最近绘制的屏幕可见。
pygame.display.flip()
在Pygame中,颜色是以RGB值指定的。这种颜色由红色、绿色和蓝色值组成,其中每个值的可能取值范围都是0~255。颜色值(255, 0, 0)表示红色,(0, 255, 0)表示绿色,而(0, 0, 255)表示蓝色。通过组合不同的RGB值,可创建1600万种颜色。在颜色值(230, 230, 230)中,红色、绿色和蓝色的量相同,它生成一种浅灰色。我们将这种颜色赋给了self.bg_color(见❶)。
在❷处,调用方法fill()用这种背景色填充屏幕。方法fill()用于处理surface,只接受一个实参:一种颜色。
4.3 创建设置类
每次给游戏添加新功能时,通常也将引入一些新设置。下面来编写一个名为settings的模块,在其中包含一个名为Settings的类,用于将所有设置都存储在一个地方,以免在代码中到处添加设置。这样,每当需要访问设置时,只需使用一个设置对象。另外,在项目增大时,这使得修改游戏的外观和行为更容易:要修改游戏,只需修改(接下来将创建的)settings.py中的一些值,而无须查找散布在项目中的各种设置。
在文件夹alien_invasion中,新建一个名为settings.py的文件,并在其中添加如下Settings类:
class Settings:
"""存储游戏《外星人入侵》中所有设置的类"""
def __init__(self):
"""初始化游戏的设置。"""
# 屏幕设置
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
为在项目中创建Settings实例并用它来访问设置,需要将alien_invasion.py修改成下面这样:
--snip--
import pygame
from settings import Settings
class AlienInvasion:
"""管理游戏资源和行为的类"""
def __init__(self):
"""初始化游戏并创建游戏资源。"""
pygame.init()
❶ self.settings = Settings()
❷ self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
def run_game(self):
--snip--
# 每次循环时都重绘屏幕。
❸ self.screen.fill(self.settings.bg_color)
# 让最近绘制的屏幕可见。
pygame.display.flip()
--snip--
在主程序文件中,导入Settings类,调用pygame.init(),再创建一个Settings实例并将其赋给self.settings(见❶)。创建屏幕时(见❷),使用了self.settings的属性screen_width和screen_height。接下来填充屏幕时,也使用了self.settings来访问背景色(见❸)。
如果此时运行alien_invasion.py,结果不会有任何不同,因为我们只是将设置移到了不同的地方。现在可以在屏幕上添加新元素了。