Pygame 外星人入侵(1)

2022-07-31,,

Pygame外星人入侵(1)

我是目录

  • Pygame外星人入侵(1)
    • 一、安装pygame
    • 二、开始游戏项目
      • 1、导入所需的包/模块
      • 2、创建 Pygame 窗口
      • 3、设置窗口的标题
      • 4、事件循环
      • 4、显示屏幕
      • 5、填充背景色
      • 6、代码整合
    • 三、运行并调试
    • 四、封装设置
    • 五、小结

引言:最近从零开始学习python,在看了一些视频后,认识到了看书的重要性,于是选择了基本口碑很不错的Python书籍,目前正在阅读的就是《Python编程:从入门到实践》这本,目前第一部分(基础知识)已经阅读完了,现在要进行第二部分中第一个项目的编写(共3个项目),那就外星人入侵。
写这个博文的目的是记录自己学习pygame的一些过程。

一、安装pygame

Pygame是我们编写游戏所需的包,书中给出了不同操作系统下的安装方法,这里我个人没有按照书上的方法来安装,而是在 https://pypi.org/ 下进行安装的。

具体安装方法是:
1、打开 https://pypi.org/ ,在搜索栏中输入 pygame 后回车,搜索结果中的第一个便是我们要使用的 pygame 包;单机pygame 1.9.6后,我们需要复制安装指令。

2、在电脑上按下 Win + R 键,再输入 cmd ,按回车;打开命令行窗口。
直接在光标处按右键,可以粘贴我们刚才复制下来的安装指令。等待 pip 自动帮我们安装即可。

3、安装完成后,我们可以这样来验证安装是否成功:
同样是在命令行窗口下,输入 python 后回车,打开python环境。
然后输入 import pygame 尝试导入 pygame 包,成功安装会有相应的提示。
至此,我们安装了 pygame 包 作为游戏开发的重要工具。

二、开始游戏项目

新建项目后,我们开始对游戏进行开发,这里整理了书中提到的这个阶段需要做到的事情。

1、导入所需的包/模块

我们这里需要导入刚才安装的 pygame 包 和 sys 包。

首先,pygame包不用多说,游戏的主要功能都需要依靠它来完成。
其次,sys 包可以帮助我们退出游戏,关闭游戏。

import sys
import pygame

2、创建 Pygame 窗口

首先,我们所有游戏的内容,都是在一个游戏窗口上进行的,这里的“游戏窗口”,就是我们大家所熟知的游戏窗口,比如DNF会占电脑屏幕的一部分来游戏,而LOL会在屏幕上全屏显示。

我们的游戏,需要通过 pygame 中的 display 模块来创建窗口。

其次,我们要注意,使用 pygame 包的功能前,除了导入 pygame 包本身外,要需要初始化 pygame 包,才可以正常使用它。
也就是说,要想在程序中使用 pygame 的模块和类,需要两个步骤:
1、导入 pygame 包 或相应的模块
2、初始化 pygame

最后,我们通过 pygame.display.set_mode() 函数创建窗口,其中必须要传入的参数只有一个 size 参数,需要传入一个元组,表示窗口的分辨率,即窗口的大小。set_mode() 的其他参数,暂时不传。

pygame.init()
screen = pygame.display.set_mode(size=(500, 700))

注意:pygame 开发游戏中有一个重要概念,就是 Surface ,这是 pygame 中的一个类,用于表示图片,这是官方文档对于 Surface 的定义:

A pygame Surface is used to represent any image

那么这里为什么要提到 Surface 呢?是因为我们创建的游戏窗口其实就是一个 Surface 对象,我们对于游戏窗口的处理,可以像对一个正常 Surface 对象一个进行处理。换句话说,我们可以把整个游戏窗口,都看作是一张图片来处理。
而且一般来说,一个程序只有一个 display Surface ,所以 pygame.display 模块中的方法,都会自动作用于当前唯一的这个 display Surface 上。也就是说,display 模块的其他方法,都会自动作用于我们创建的游戏窗口。

3、设置窗口的标题

如果我们直接使用刚才创建的pygame窗口来使用,那么你会发现窗口的标题是默认的信息。现在我们想让这个窗口能一眼就让玩家知道,自己是在玩《外星人入侵》这款游戏,那么就可以通过 display 模块的 set_caption 方法来设置窗口的标题。

pygame.display.set_caption('外星人入侵')

4、事件循环

到这里为止,我们已经创建好了 Pygame 窗口并为其修改了标题,使之能显示”外星人入侵“这样的信息。

接下来我们要做的,是为游戏加入一个”事件循环“。
所谓”事件“,也就是 event ,是指所有鼠标、键盘的指令,我们可以通过一个循环来获取鼠标和键盘的指令,也就是我们希望”做出什么样的动作“。

pygame 有一个 event 模块,专门处理事件有关的操作。现在我们可以通过这个模块,来实现当用户点击窗口右上角的关闭按钮时,游戏关闭,窗口消失的效果。

for event in pygame.event.get():
	if event.type == pygame.QUIT:
		sys.exit()

4、显示屏幕

实现了基本的游戏窗口以后,我们需要将这个窗口显示出来,让我们可以在屏幕上看到。

这里同样是使用 display 模块来实现窗口的显示。

pygame.display.flip()

5、填充背景色

如果按照上一小节的方法显示了游戏窗口,那么你会发现,这个游戏窗口的底色是全黑的,这是因为 pygame 默认的游戏窗口就是全黑的,给人一种很压抑的感觉,现在我们想修改游戏窗口的底色,也就是背景色。

首先,需要知道我们到底想设置一个怎么样的颜色作为背景色,也就是设置一个背景色变量,采用(R, G, B)格式的一个元组。(R、G、B的值在0~255之间)。这里我用的是(230, 230, 230)代表一个浅灰色。

其次,我们可以通过 Surface 对象的 fill() 方法来实现对图片进行填充颜色的操作,这个方法可以在一张图片上填充我们指定的颜色,正如之前所说,我们创建的游戏窗口本身就是一个 Surface 对象,因此可以通过 fill() 方法来对其进行填充。

badkground_color = (230, 230, 230)
screen.fill(badkground_color)

6、代码整合

现在,我们需要将上面实现的4部分代码进行一个简单的整合,即封装到一个函数中去。

这里我们将其封装到 run_game()函数中:

def run_game():
    # 初始化 pygame。使其可以绘制屏幕
    pygame.init()

    # 绘制游戏窗口 screen,所有的游戏元素都在这个窗口里运动交互
    screen = pygame.display.set_mode(size=(500, 700))
	
	# 设置游戏窗口背景色 参数
    badkground_color = (230, 230, 230)
    
    # 修改游戏窗口的标题,这里当然是‘外星人入侵’
    pygame.display.set_caption('外星人入侵')

	# 事件检测循环,持续检测来自鼠标、键盘的请求,并作出相应的相应
 	for event in pygame.event.get():
		# 当玩家点击关闭按钮时,退出游戏
 		if event.type == pygame.QUIT:
			sys.exit()
	
	# 为纯黑的游戏屏幕填充上不一样的颜色
    screen.fill(badkground_color)
        
	# 显示屏幕,使得绘制在窗口中的事物能够被观察到
    pygame.display.flip()

至此,我们尝试自己实现书中所提到的内容,并封装成一个函数。

三、运行并调试

现在我们尝试运行刚才写好的函数,看看能否达到我们的预期。

结果是不行的。

游戏窗口确实可以显示出来,但是一瞬间就会消失,所以连截图展示都做不到。那么到底为什么会这样的?

原因是由于我们运行这个函数时,只会刷新一次屏幕,刷新完以后,程序就结束了,那么窗口自然就消失了。

如果需要一直显示游戏窗口,那么就需要将 ‘显示屏幕’ 的代码放到一个循环中,不断地重复刷新屏幕,达到窗口一直显示的预期结果。

但是如果在一个死循环中不断绘制屏幕,那么什么时候才可以退出来呢?

这里我们就想到了之前所做的 ‘事件循环’ 了,在事件循环中,我们可以在用户点击关闭按钮时退出游戏,关闭程序。那么将事件循环的代码,和 显示屏幕 的代码放到同一个死循环中去,就可以达到不断显示屏幕且在用户想退出时,点击关闭按钮即可退出的效果。

此处我们对代码做了如下修改
1、创建一个死循环,达到不断刷新屏幕的效果。
2、在死循环中加入可以退出循环的语句,基于事件。
3、基于上述的描述,为代码加上基本的注释

import sys
import pygame


# 游戏的主逻辑都在 run_game()函数中运行
def run_game():
    # 初始化 pygame。使其可以绘制屏幕
    pygame.init()

    # 绘制游戏窗口 screen,所有的游戏元素都在这个窗口里运动交互
    screen = pygame.display.set_mode(size=(500, 700))

    # 设置游戏窗口背景色 参数
    badkground_color = (230, 230, 230)

    # 修改游戏窗口的标题,这里当然是‘外星人入侵’
    pygame.display.set_caption('外星人入侵')

    # 游戏主循环,使得循环中的代码可以不断循环执行
    while True:
        # 事件检测循环,持续检测来自鼠标、键盘的请求,并作出相应的相应
        for event in pygame.event.get():
            # 当玩家点击关闭按钮时,退出游戏
            if event.type == pygame.QUIT:
                sys.exit()

        # 为纯黑的游戏屏幕填充上不一样的颜色
        screen.fill(badkground_color)

        # 刷新屏幕,使得元素能够不断刷新位置
        pygame.display.flip()


# 运行游戏主逻辑
run_game()

此时,再运行这段代码,就会得到如下结果:

至此,就达到我们编写代码的预期了。

四、封装设置

我们通过代码实现了简单的 Pygame 窗口的创建,标题的修改,背景色的修改等功能,并将这些代码封装到了一个函数中运行。

但是也存在一些问题,就是我们在写代码过程中,用到了很多参数,比如屏幕的分辨率、标题内容的字符串、背景色的元组 等,在之后可能会用到更多的参数,如果哪天我们需要修改其中的一个参数,那么只能从代码中去找位置,然后修改,这样显然是很不便于维护的。

基于这种考虑,我们可以将所有用到的设置,都保存到一个专门的模块中去,并定义一个设置类,该类的属性即为我们需要用到的参数。

这样处理以后,我们只需要在 run_game() 方法中实例化这个设置类,就可以使用其中的所有属性,即设置的参数了。

动手实践,创建一个 settings.py 模块,在其中定义 Settings 类:

class Settings(object):
    # 设置一系列属性,作为我们游戏中需要用到的参数,
    # 初始化设置类后即可使用.
    def __init__(self):
        # 1、Pygame游戏屏幕的尺寸size
        self.screen_width = 500
        self.screen_height = 700

        # 2、Pygame游戏屏幕上方的标题字符串
        self.screen_title = '外星人入侵'

        # 3、Pygame游戏屏幕的背景色元组(R,G,B)
        self.background_color = (230, 230, 230)

定义完设置类后,游戏主模块的代码就可以做相应的缩减了。
这里我们主要对主模块做了如下修改:
1、从 settings 模块中导入设置类
2、初始化 pygame 时,也初始化 Settings 对象 my_setting 以供使用
3、删除定义背景色的代码
4、将原来代码中所有用到设置参数的位置,都改成从 my_setting 对象中获取参数。

import sys
import pygame
# 导入设置类,存放着我们要用到的所有设置参数
from settings import Settings


# 游戏的主逻辑都在 run_game()函数中运行
def run_game():
    # 初始化 pygame。使其可以绘制屏幕
    pygame.init()

    # 初始化设置类,得到所有我们要用到的设置参数值
    my_setting = Settings()

    # 绘制游戏窗口 screen,所有的游戏元素都在这个窗口里运动交互
    screen = pygame.display.set_mode(size=(my_setting.screen_width, my_setting.screen_height))

    # 修改游戏窗口的标题,这里当然是‘外星人入侵’
    pygame.display.set_caption(my_setting.screen_title)

    # 游戏主循环,使得循环中的代码可以不断循环执行
    while True:
        # 事件检测循环,持续检测来自鼠标、键盘的请求,并作出相应的相应
        for event in pygame.event.get():
            # 当玩家点击关闭按钮时,退出游戏
            if event.type == pygame.QUIT:
                sys.exit()

        # 为纯黑的游戏屏幕填充上不一样的颜色
        screen.fill(my_setting.background_color)

        # 刷新屏幕,使得元素能够不断刷新位置
        pygame.display.flip()


# 运行游戏主逻辑
run_game()

这样处理以后,当我们想修改游戏的设置参数值时,只需要在 settings 模块下进行修改即可,不需要对主模块进行修改。

需要注意的是,为了让我们能更加轻松地维护游戏,需要对Settings类中的属性标记上明确的注释,不能有参数意义上的歧义存在。

五、小结

虽然这篇博文中实现的功能很少、很简单、很基础,但是是在脱离书本以后,自己尝试对所学进行输出而得。毕竟学习一些知识以后,检验知识的最好方法就是实践,即输出。在输出的过程中,也遇到了一些问题(三、处的问题),说明自己对于游戏开发的流程还不是很熟悉。而且书中对于代码封装和参数封装的处理思想,我觉得是很值得拿出来记录并分享的,在大型的项目中,这两种思想都很值得借鉴。

本文地址:https://blog.csdn.net/qq_32740521/article/details/107626753

《Pygame 外星人入侵(1).doc》

下载本文的Word格式文档,以方便收藏与打印。