赞
踩
转载于:http://c.biancheng.net/pygame/
Python Pygame 是一款专门为开发和设计 2D 电子游戏而生的软件包,它支 Windows、Linux、Mac OS 等操作系统,具有良好的跨平台性。Pygame 由 Pete Shinners 于 2000 年开发而成,是一款免费、开源的的软件包,因此您可以放心地使用它来开发游戏,不用担心有任何费用产生。
Pygame 在 SDL(Simple DirectMedia Layer,使用 C语言编写的多媒体开发库) 的基础上开发而成,它提供了诸多操作模块,比如图像模块(image)、声音模块(mixer)、输入/输出(鼠标、键盘、显示屏)模块等。相比于开发 3D 游戏而言,Pygame 更擅长开发 2D 游戏,比如于飞机大战、贪吃蛇、扫雷等游戏。
当然 Python 也提供了开发 3D 游戏的软件包,比如 Pyglet、Panda3D、PyOgre 等。
这套 Pygame 教程适合想要了解 Python 游戏开发的人员学习,如果您刚刚接触游戏开发,那么这套教程非常适合您。
通过本套教程的学习,您将了解到使用 Pygame 开发游戏过程中,应用到的基础知识,比如游戏主循环、Surface 对象、Event 事件、Rect 区域等,通过对这些知识的学习,您将掌握如何使用 Pygame 完成相应功能的开发。本套教程采用了“知识点+示例”相结合的方式来编写,让您“学一点,透一点”,使整个阅读过程变得简单、有趣。
本套 Pygame 教程适合有一定 Python 编程基础的人员学习,如果您已经掌握 Python 基础知识,那可以直接阅读本教程,否则建议您提前阅读《Python基础教程》。当然,如果您了解其他的 Python 开发的游戏软件包,那将再好不过了,比如 Pyglet 等。
Python 是当下最为火热,且功能最为全面的一门编程语言。Python 之所以深受大家喜爱, 除了可以被应用到“人工智能”领域之外,还可以延伸到数据分析、Web 开发、自动化测试、自然语言处理、游戏开发等各个领域。这一切的实现得益于 Python 有一个强大的第三方库(网址:https://pypi.org/),这个第三方库相当于一个手机软件市场,允许我们随意下载各式各样的软件包,并且开箱即用,这大大提高了 Python 语言的编程效率和实用性。
“如果说我比其他人看的更远,那是因为我站在巨人的肩膀上。”第三方库就相当于巨人,它为程序开发者们提供了众多现成的模块。
接下来,我们要讲的 Pygame 就是第三库中非常有趣、实用的一个模块。
顾名思义,Pygame 是一个专门用来开发游戏的 Python 模块,主要为开发、设计 2D 电子游戏而生,它是一个免费、开源的第三方软件包,支持多种操作系统,具有良好的跨平台性(比如 Windows、Linux、Mac 等)。Pygame 是 Pete Shinners 在 SDL(Simple DirectMedia Layer,一套开源的跨平台多媒体开发库)基础上开发而来,其目的是取代 PySDL。
图1:Pygame
截止到 2020 年 10 月 28 日,Pygame 已经诞生 20 周年。
SDL 是一套开放源代码的跨平台多媒体开发库,使用 C语言编写,它提供了多种控制图像、声音、输入/输出的函数,Pygame 可以看做是对 SDL 的封装,在 SDL 库基础上提供了各种 Python 的 API接口。目前 SDL 主要用于多媒体领域,比如开发游戏、模拟器、媒体播放器等。
图2:SDL
通过 Pygame 我们能够创建各种各样的游戏和多媒体程序,但相比于开发大型 3D 游戏来说,它更擅长与开发 2D 游戏,比如扫雷、纸牌游戏、贪吃蛇、超级马里奥、飞机大战等,如果是 3D 游戏,可以选择一些功能更为全面的 Python 游戏开发库,比如 Panda3D(迪士尼开发的3D游戏引擎),PyOgre(Ogre 3D渲染引擎)等。
Python 作为一门解释型语言并不适合开发大型的 3D 游戏,但 Python 通过对其他语言的接口封装,使自身具备了开发大型 3D 游戏的能力,例如 Panda3D 的底层是用 C++ 语言编写的。一些较为知名的 3D 游戏,比如魔兽世界、文明帝国4、战地风云2,这些游戏都是使用 Python 语言开发的,而国内较为知名的“阴阳师”手游,也是由 Python 语言开发而成。
“俗话说,术业有专攻”,每一种语言都有自己擅长的一方面,不能因为某种语言不适合某一领域,就认为它是劣质语言。
Pygame 官方网站(https://www.pygame.org/tags/all)提供许多丰富的游戏案例,它们全部使用 Pygame 开发,如下所示:
图3:Pygame官方案例
通过官网可以很方便地找到并下载这些游戏。—> 点击前往。这些项目案例能为您开发自己的游戏提供一些思路和帮助。
假如您从来没有接触过游戏开发,那么学习 Pygame 是一个不错的选择,它非常适合初学者学习,您可以把它当做进入游戏开发世界的“敲门砖”,通过对 Pygame 的学习,您将了解到更为广阔的世界。
如果您想做专业的游戏开发工程师,建议学习 C/C++、C# 语言,这些语言虽然语法略显复杂,但是其性能相比于 Python 来说要好的多。就当下而言,市面上最为流行的游戏开发平台(即游戏引擎)分别是 Unity 和 UE4,这两个平台的侧重点不同,前者适合于移动端游戏的开发(支持 C# 语言),而后者更偏向于 PC 端游戏的开发(支持 C++ 语言),此处不做深入探讨,如果您对它们感兴趣的话,可以自行研究。
图4:游戏开发引擎
UE4 和 Uinty 开发了许多优秀的游戏,比如 UE4 开发了《绝地求生:刺激战场》,而 Unity 开发了《使命召唤手游版》。
Pygame 的下载非常简单,可分为两种方式:一是通过 Python 的包管理器 pip 来安装;二是下载二进制安装包进行安装。其中使用 pip 包管理器安装是最简单、最轻量级的方法,下面以 Windows 系统为例对上述两种方式进行讲解。
图1:可爱的Pygame
这是最为轻便的一种安装方式,推荐大家使用。首先确定的您的电脑已经安装了 Python(推荐使用 3.7 以上版本),然后打开 cmd 命令行工具,输入以下命令即可成功安装:
pip install pygame
上述安装方法同样适用于 Linux 和 Mac 操作系统。
Python 第三方库官网 PyPI(点击前往下载)提供了不同操作平台的 Pygame 安装包,如下所示:
图2:Pygame下载
这里我们选择 Windows 版本进行下载。下载完成后,打开一个 cmd 命令窗口,切换到该安装程序所在的文件夹,并执行以下命令进行安装:
Python - m pip install --user pygame-2.0.2-cp27m-win_amd64.whl
无论采用上述哪种方式都可以安装 Pygame,不过我们强烈建议您使用第一种方式来安装。
最后使用以下命令检查 Pygame 版本,从而验证是否安装成功。
python -m pygame --version
或者您也可以在 Python 解释器的交互界面导入 Pygame 包,如果显示如下,则证明已经安装成功:
图3:Pyagme验证安装
Pygame 作为一个入门级的游戏开发库,其实并不难学,只要掌握 Python 编程的相关知识就能很轻松地掌握它。
Pygame 语法简单、明了,秉持了 Python 语言一贯的风格。同时,它作为一个游戏开发库来说,具有图形编程的基本特点,如果您对于图形编程从未了解过,即使您有 Python 编程基础,也会略感迷茫。因此,在接下来的学习中会详细介绍 Pygame 的常用模块,以及图形编程中的相关概念,帮助您快速掌握 Pygame 的使用。
下面是一个简单的 Pygame 程序,如下所示:
#导入所需的模块
import sys
import pygame
# 使用pygame之前必须初始化
pygame.init()
# 设置主屏窗口
screen = pygame.display.set_mode((400,400))
# 设置窗口的标题,即游戏名称
pygame.display.set_caption('hello world')
# 引入字体类型
f = pygame.font.Font('C:/Windows/Fonts/simhei.ttf',50)
# 生成文本信息,第一个参数文本内容;第二个参数,字体是否平滑;
# 第三个参数,RGB模式的字体颜色;第四个参数,RGB模式字体背景颜色;
text = f.render("C语言中文网",True,(255,0,0),(0,0,0))
#获得显示对象的rect区域坐标
textRect =text.get_rect()
# 设置显示对象居中
textRect.center = (200,200)
# 将准备好的文本信息,绘制到主屏幕 Screen 上。
screen.blit(text,textRect)
# 固定代码段,实现点击"X"号退出界面的功能,几乎所有的pygame都会使用该段代码
while True:
# 循环获取事件,监听事件状态
for event in pygame.event.get():
# 判断用户是否点了"X"关闭按钮,并执行if代码段
if event.type == pygame.QUIT:
#卸载所有模块
pygame.quit()
#终止程序,确保退出程序
sys.exit()
pygame.display.flip() #更新屏幕内容
运行结果如下所示:
图1:第一个 Pygame 程序
如果您熟悉 Python 编程的基础知识,那么在注释的帮助下,应该能很容易地理解上述代码。假如不能也没有关系,因为接下来,我们会对上述代码进行细致的分析。常言道:“授人以鱼不如授人以渔”,分析代码的逻辑,有助于我们理解和编写 Pygame 程序,而至于代码中涉及的模块、方法等,会在后续内容做详细介绍。
在使用 Pygame 编写程序前,要做的第一个步骤是“初始化程序”,代码如下所示:
pygame.init()
这是整个程序中的第一句代码,它的作用是自动检测 Pygame 软件包是否正常可用,并检查电脑的硬件调用接口、基础功能是否存在问题,比如音频、光驱、声卡驱动等设备。同时,它会完成 Pygame 中所有模块的初始化操作,比如 display(显示模块)、font(字体模块)、mixer(声音控制模块)、cursors(光标控制模块)等。
由此可见,初始化程序的重要性,因此上述代码,在编写程序时候千万不能“漏掉”。
想要掌握 Pygame 的编程逻辑,首先就要理解 surface 对象的概念,它是 Pygame 中最重要的组成部分。
Surface 翻译为表面、表层、外观,在 Pygame 中,您可以把 surface 对象理解成一张“白纸”,通过这张纸可以做许多的事情,比如在纸上添加文字、填充颜色、添加图片以及绘制任意形状的图形等。既然是“纸”就有规格尺寸,Pygame 允许您创建任意大小的纸。
那么我们应该如何创建 Surface 对象呢?Pygame 提供了多种创建 Surface 对象的方法,这里先介绍以下几种方法。
上述示例,使用如下方式创建了一个 surface 对象:
#也叫screen对象,本质上是一个Surface,大小400*400
screen = pygame.display.set_mode((400,400))
screen 的本质上就是一个 Surface 对象,它是游戏的主窗口,也就是整个游戏中尺寸最大的“纸”,任何其他的 Surface 对象都需要附着在这张最大的“纸”上,比如创建一个包含文本的 Surface 对象,通过以下方法将它绘制在主屏幕上:
#创建一个包含文字的Surface对象
text = f.render("C语言中文网",True,(255,0,0),(0,0,0))
#通过blit方法将其绘制在主屏幕上,这里的textRect表示位置坐标
screen.blit(text,textRect)
如果想创建一个包含图像的 surface 对象可以使用如下方法:
surface_image =pygame.image.load("图片路径")
游戏,在我们日常生活中经常接触到,无论是手游、还是电脑端游戏,已经成了信息社会中,不可或缺的一部分。
游戏大致来讲是由动画和人机交互的体验两部分构成,其中动画则是由一系列连续静止的图片,经过一定频率的刷新构成的,这个频率被称为 FPS,如果频率值越大则画面越流畅;如果频率值越小则画面会出现卡顿的感,在游戏过程中一般人能接受的最低 FPS 约为 30Hz,如果想要画面流畅则 FPS 要大于 60 Hz。
FPS 越高,细节越好,体验也越好,但是文件容量也越高
动画保证了玩家的视觉体验,而人机交互则是操作上的体验。通过移动和点击鼠标、按下键盘上的技能键,或是滑动手机屏幕等操作来实现人机交互,这些与游戏程序交互的操作被称为事件(Event)。
如果您接触过 JavaScript,那么您对于“事件”这一名词,一定不会陌生。
Pygame 作为一个游戏开发库,同样具有设置和监听事件的功能。它提供了一个 enevt 事件模块,这个模块中包含了所有常用到游戏事件。下面是退出游戏的代码示例(其他事件类型,后续会做介绍):
# 循环获取事件,监听事件状态,使用get()获取事件
for event in pygame.event.get():
# 判断事件类型,用户是否点了"X"关闭按钮
# pygame.QUIT 指点击右上角窗口的"X"号
if event.type == pygame.QUIT:
#点击后,卸载所有pygame模块
pygame.quit()
当打我们游戏时可能会触发游戏中的各种事件,比如鼠标事件、键盘按键事件、摄像拍照事件等等,因此游戏程序需要一直循环监听玩家的操作,只有当用户点击了游戏“关闭”按钮时,监听才会结束。如果想要达到“循环监听”目的,此时就需要设置一个游戏循环(Game Loop)也称为游戏的主循环,这样才能保证人机交互的体验感。代码示例如下:
#游戏主循环(游戏循环)
while True:
# 循环获取事件,监听事件
for event in pygame.event.get():
# 判断用户是否点了关闭按钮
if event.type == pygame.QUIT:
# 当用户关闭游戏窗口时执行以下操作
# 这里必须调用quit()方法,退出游戏
pygame.quit()
#终止系统
sys.exit()
#更新并绘制屏幕内容
pygame.display.flip()
游戏主循环是每个 Pygame 游戏程序中必不可少的一部分,它主要承担着以下三个重要任务:
图2:主循环示意图
游戏画面和游戏操作状态会因为动画效果和玩家的操作而改变,因此需要以循环的方式实时地更新主屏幕(screen)的显示内容。把下列代码放入游戏主循环中即可实现实时更新和绘制屏幕内容,如下所示:
#刷新界面显示pygame.display.flip()
除了上述方法外,Pygame 还提供了另一个方法。如下所示:
pygame.display.update()
这两个方法的主要区别是:后者可以根据选定的区域来更新部分内容,而前者则是更新整个待显示的内容。如果后者没有提供区域位置参数时,其作用和 display.flip() 相同。
通过上述学习,我们对 Pygame 程序有了基本的认识。下面对 Pygame 模块中的方法、属性做更加细致的讲解。
Pygame 使用pygame.display
显示模块中的方法创建游戏的主窗口:
screen = pygame.display.set_mode(size=(),flags=0)
上述函数有两个参数常用参数:
标志位 | 功能 |
---|---|
pygame.FULLSCREEN | 创建一个全屏窗口。 |
pygame.HWSURFACE | 创建一个硬件加速窗口,必须和 FULLSCREEN 同时使用。 |
pygame.OPENGL | 创建一个 OPENGL 渲染窗口。 |
pygame.RESIZABLE | 创建一个可以改变大小的窗口。 |
pygame.DOUBLEBUF | 创建一个双缓冲区窗口,建议在 HWSURFACE 或者 OPENGL 时使用。 |
pygame.NOFRAME | 创建一个没有边框的窗口。 |
体验过电脑游戏的朋友们都知道,当运行程序后会在电脑桌面上出现一个游戏的主窗口,这个主窗口的本质是一个 surface 对象,把理解为画布、画板、白纸在合适不过了,它相当于一个载体,用于承载一切游戏所用到的元素。假如您需要将一段文本方放置到主窗口中,那么您需要先创建一个包含文本的 surface 对象,之后再将它附加到主窗口上。简单的理解,就是将一张图 A 粘贴到另一张图 B 上。
主窗口(screen)相当于游戏程序中尺寸最大的 Surface 对象,在这个最大的“画布”中,我们还可以添加其他“小”的 Surface 对象,这些对象以矩形的形式存在于主窗口中,它们共同组成了一个游戏程序。通过下列方法可以将一个 Surface 对象粘贴至主窗口上:
scrren.blit(source, dest, area=None, special_flags = 0)
下面对上述参数做简单的介绍:
除了创建游戏的主窗口之外,display 模块还提供了许多的和“显示”相关的方法,比如设置游戏窗口的名称,如下表所示
import sys
import pygame
#使用pygame之前必须初始化
pygame.init()
#设置主屏窗口
screen = pygame.display.set_mode((400,400))
#填充主窗口的背景颜色,参数值RGB(颜色元组)
screen.fill((156,156,156))
#设置窗口标题
pygame.display.set_caption('c语言中文网')
# 如果没有下列主循环代码,运行结果会一闪而过
while True:
# 循环获取事件,监听事件
for event in pygame.event.get():
# 判断用户是否点了关闭按钮
if event.type == pygame.QUIT:
#卸载所有模块
pygame.quit()
#终止程序
sys.exit()
#更新屏幕内容
pygame.display.flip()
程序的运行结果如下所示:
图1:Pygame程序运行结果
pygame.display 模块还提供了一些和“显示”相关的其他方法,如下表所示:
方法名称 | 说明 |
---|---|
pygame.display.get_surface() | 获取当前显示的 Surface 对象。 |
pygame.display.flip() | 更新整个待显示的 Surface 对象到屏幕上。 |
pygame.display.update() | 更新部分软件界面显示。 |
pygame.display.Info() | 产生一个 VideoInfo 对象,包含了显示界面的相关信息。 |
pygame.display.set_icon() | 设置左上角的游戏图标,图标尺寸大小为 32*32。 |
pygame.display.iconify() | 将显示的主窗口即 Surface 对象最小化,或者隐藏。 |
pygame.display.get_active() | 当前显示界面显示在屏幕上时返回 True,如果窗口被隐藏和最小化则返回 False。 |
通过前面内容的介绍,我们对 Surface 对象有了大体上的认识。Pygame 针对文本、图像、颜色提供了不同模块来生成它们各自的 Surface 对象。Surface 模块是Pygame 中专门用来新建图像的,通过该模块可以创建一个 Surface 对象,语法格式如下:
Surface=pygame.Surface(size=(width,height),flags,depth)
参数函数如下:
下面看一组简单的使用示例,如下所示:
import sys
import pygame
#使用pygame之前必须初始化
pygame.init()
#设置主屏窗口 ;设置全屏格式:flags=pygame.FULLSCREEN
screen = pygame.display.set_mode((400,400))
#设置窗口标题
pygame.display.set_caption('c语言中文网')
screen.fill('white')
#创建一个 50*50 的图像,并优化显示
face = pygame.Surface((50,50),flags=pygame.HWSURFACE)
#填充颜色
face.fill(color='pink')
while True:
# 循环获取事件,监听事件
for event in pygame.event.get():
# 判断用户是否点了关闭按钮
if event.type == pygame.QUIT:
#卸载所有模块
pygame.quit()
#终止程序
sys.exit()
# 将绘制的图像添加到主屏幕上,(100,100)是位置坐标,显示屏的左上角为坐标系的(0,0)原点
screen.blit(face, (100, 100))
pygame.display.flip() #更新屏幕内容
最终的显示结果如下:
图1:程序运行结果
从上述运行结果可以看出,通过 Surface 模块,我们成功的在主屏幕上绘制一个 50 * 50 的矩形区域。注意,如果不设置尺寸,Surface 默认创建一个和主游戏屏幕同样大小的区域。
Surface 模块还提供了处理图像的其他方法,下表对它们做了简单的介绍。
方法 | 说明 |
---|---|
pygame.Surface.blit() | 将一个图像(Surface 对象)绘制到另一个图像上 |
pygame.Surface.convert() | 修改图像(Surface 对象)的像素格式 |
pygame.Surface.fill() | 使用纯色填充 Surface 对象 |
pygame.Surface.scroll() | 复制并移动 Surface 对象 |
pygame.Surface.set_alpha() | 设置整个图像的透明度 |
pygame.Surface.get_at() | 获取一个像素的颜色值 |
pygame.Surface.set_at() | 设置一个像素的颜色值 |
pygame.Surface.get_palette() | 获取 Surface 对象 8 位索引的调色板 |
pygame.Surface.map_rgb() | 将一个 RGBA 颜色转换为映射的颜色值 |
pygame.Surface.set_clip() | 设置该 Surface 对象的当前剪切区域 |
pygame.Surface.subsurface() | 根据父对象创建一个新的子 Surface 对象 |
pygame.Surface.get_offset() | 获取子 Surface 对象在父对象中的偏移位置 |
pygame.Surface.get_size() | 获取 Surface 对象的尺寸 |
除了使用 Surface 模块新建图像外,我们还可以使用另外一种方法从外部加载图像,如下所示:
pygame.image.load("图片路径").convert()
上述方法将被加载的图像作为 Surface 对象来使用,因此它可以调用上述表格中所有方法。注意,此处之所以使用 convert()来转换被加载图片的像素格式,是为了提升 Pygame 对图片的处理速度,该操作能够保证图像的像素格式与图片的显示格式是相同的。
通过 image.load() 方法可以加载游戏的背景图,或者游戏中使用的其他元素,比如的人物、道具等等。
下面看一组简单的示例:
import pygame
#引入pygame中所有常量,比如 QUIT
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((500,250))
pygame.display.set_caption('c语言中文网')
#加载一张图片
image_surface = pygame.image.load("C:/Users/Administrator/Desktop/c-net.png").convert()
# rect(left,top,width,height)指定图片上某个区域
# special_flags功能标志位,指定颜色混合模式,默认为 0 表示用纯色填充
image_surface.fill((0,0,255),rect=(100,100,100,50),special_flags=0)
# 200,100 表示图像在水平、垂直方向上的偏移量,以左上角为坐标原点
image_surface.scroll(100,50)
# 无限循环,让窗口停留
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
# 将图像放置在主屏幕上
screen.blit(image_surface,(0,0))
pygame.display.update()
程序运行结果如下所示:
图2:程序运行结果
pygame.transform 模块允许您对加载、创建后的图像进行一系列操作,比如调整图像大小、旋转图片等操作,常用方法如下所示:
方法 | 说明 |
---|---|
pygame.transform.scale() | 将图片缩放至指定的大小,并返回一个新的 Surface 对象。 |
pygame.transform.rotate() | 将图片旋转至指定的角度。 |
pygame.transform.rotozoom() | 以角度旋转图像,同时将图像缩小或放大至指定的倍数。 |
下面看一组简单的演示示例:
import pygame
#引入pygame中所有常量,比如 QUIT
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((500,250))
pygame.display.set_caption('c语言中文网')
#加载一张图片(455*191)
image_surface = pygame.image.load("C:/Users/Administrator/Desktop/c-net.png").convert()
image_new = pygame.transform.scale(image_surface,(300,300))
# 查看新生成的图片的对象类型
#print(type(image_new))
# 对新生成的图像进行旋转至45度
image_1 =pygame.transform.rotate(image_new,45)
# 使用rotozoom() 旋转 0 度,将图像缩小0.5倍
image_2 = pygame.transform.rotozoom(image_1,0,0.5)
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
# 将最后生成的image_2添加到显示屏幕上
screen.blit(image_2,(0,0))
pygame.display.update()
程序的运行结果如下:
图1:程序运行结果
pygame.time 时间控制模块,是 Pygame 中使用频率较高的模块,其主要功能是管理时间和游戏帧数率(即 FPS)。
时间在游戏开发中承担着非常重要的作用,比如释放某个技能所消耗的时间,或者播放动画、声音的持续时间,这些都需要时间来管理。time 模块另外一个重要作用是控制游戏帧数率(即 FPS),它是评价游戏画面是否流畅的关键指标。在一般情况下,计算机的 FPS 都能达到 60帧/s 的速度,这足够我们使用,如果当帧数小于 30 的时候,游戏画面就会变得卡顿。
注意,在 Pygame 中时间以毫秒为单位(1秒=1000毫秒),这样会使游戏的设计更为精细。
Pygame.time 模块提供了以下常用方法,如下表所示:
方法 | 说明 |
---|---|
pygame.time.get_ticks() | 以毫秒为单位获取时间 |
pygame.time.wait() | 使程序暂停一段时间 |
pygame.time.set_timer() | 创建一个定时器,即每隔一段时间,去执行一些动作 |
pygame.time.Clock() | 创建一个时钟对象来帮我们确定游戏要以多大的帧数运行 |
下面看一组简单的示例:
import pygame
pygame.init()
screen = pygame.display.set_mode((500,500))
pygame.display.set_caption('c语言中文网')
# 获取以毫秒为单位的时间
t = pygame.time.get_ticks() #该时间指的从pygame初始化后开始计算,到调用该函数为止
t1 =pygame.time.wait(3000) #暂停游戏3000毫秒
print(t1)
#暂停t1时间后,加载图片
image_surface = pygame.image.load("C:/Users/Administrator/Desktop/c-net.png")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
screen.blit(image_surface,(0,0))
pygame.display.update()
上述程序在暂停 3 秒后才会加载图片,运行结果如下:
图1:程序运行结果
若想设置游戏的帧数率(FPS)可以通过 Clock() 方法来实现,该对象提供了以下常用方法:
方法 | 说明 |
---|---|
pygame.time.Clock.tick() | 更新clock对象 |
pygame.time.Clock.get_time() | 获取上一个tick中的时间 |
pygame.time.Clock.get_fps() | 计算clock对象的帧率 |
下面看一组简单的应用示例:
import pygame
pygame.init()
screen = pygame.display.set_mode((500,300))
pygame.display.set_caption('c语言中文网')
# 获取以毫秒为单位的时间
t = pygame.time.get_ticks() #该时间指的从pygame初始化后开始计算,到调用该函数为止
t1 =pygame.time.delay(3000) #暂停游戏3000毫秒
print(t1)
#暂停t1时间后,加载图片
image_surface = pygame.image.load("C:/Users/Administrator/Desktop/c-net.png")
#创建时钟对象(控制游戏的FPS)
clock = pygame.time.Clock()
while True:
#通过时钟对象,指定循环频率,每秒循环60次
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
screen.blit(image_surface,(0,0))
pygame.display.update()
注意:FPS(游戏帧率)影响效果只有在动态图时才能显现出来,不过无论静态图还是动态图,它们的使用规则都是一样的。
Rect(rectangle)指的是矩形,或者长方形,在 Pygame 中我们使用 Rect() 方法来创建一个指定位置,大小的矩形区域。函数的语法格式如下:
rect =pygame.Rect(left,top,width,height)
Rect 表示的区域必须位于一个 Surface 对象之上,比如游戏的主窗口(screen)。上述方法由四个关键参数值构成,分别是 left、top、width、height,为了方便大家理解这些距离的含义,下面给出了一张示意图:
注意:在 Pygame 中以游戏主窗口的左上角为坐标原点。
下面看一组简单的使用示例,如下所示:
import pygame
pygame.init()
screen = pygame.display.set_mode((500,300))
pygame.display.set_caption('c语言中文网')
image_surface = pygame.image.load("C:/Users/Administrator/Desktop/c-net.png")
rect1 = pygame.Rect(50,50,100,100)
# 在原图的基础上创建一个新的子图(surface对象)
image_child= image_surface.subsurface(rect1)
rect2 = image_child.get_rect()
#输出的矩形大小为 100*100
print(rect2)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
#在屏幕上显示子图的区域
screen.blit(image_child,rect1)
pygame.display.update()
程序的运行结果如下:
图1:程序运行结果
从上述运行结果可以看出,我们在图片上截取了一个和 rect1 同样大小的矩形区域(100*100)。
Rect(矩形区域)对象还提供了一些常用方法。如下表所示:
方法 | 说明 |
---|---|
pygame.Rect.copy() | 复制矩形 |
pygame.Rect.move() | 移动矩形区域,接受一个列表参数 |
pygame.Rect.move_ip() | 移动矩形(无返回) |
pygame.Rect.inflate() | 增大或缩小矩形大小 |
pygame.Rect.clamp() | 将矩形移到另一个矩形内 |
pygame.Rect.union() | 返回一个两个矩形合并后的矩形。 |
pygame.Rect.fit() | 按纵横比调整矩形的大小或移动矩形。 |
pygame.Rect.contains() | 测试一个矩形是否在另一个矩形内 |
pygame.Rect.collidepoint() | 测试点是否在矩形内 |
pygame.Rect.colliderect() | 测试两个矩形是否重叠 |
同时 Rect 对象也提供了一些关于矩形大小的常用的属性,如下所示:
x,y 表示矩形距离 x、y 轴的距离
top, left, bottom, right #在坐标系内描述矩形的大小
topleft, bottomleft, topright, bottomright #返回一个描述矩形大小的元组
midtop, midleft, midbottom, midright #返回一个描述矩形大小的元组
center, centerx, centery #(centerx,centery)表示矩形中央坐标(x,y)的值
size, width, height
w,h #用于描述矩形的width、height
下面看一组简单的示例演示,如下所示:
import pygame
# 对应left/top/width/height
rect1 = pygame.Rect(0,0,100,100)
print('x的值是{};y的值是{}'.format(rect1.x,rect1.y))
print('bottom的值是{};right的值是{}'.format(rect1.bottom,rect1.right))
# 设置居中的距离
print(rect1.center,rect1.centerx,rect1.centery)
# 返回值为 (centerx,top)
print(rect1.midtop)
# 返回值为 (right,centery)的元组
print(rect1.midright)
# 返回值为(left,bottom)
print(rect1.bottomleft)
# 返回矩形区域大小,元组格式
print(rect1.size)
输出结果如下:
x的值是0;y的值是0
bottom的值是100;right的值是100
#设置中心努力
(50, 50) 50 50
(50, 0)
#midright
(100, 50)
#bottomleft
(0, 100)
#size
(100, 100)
我们还可以通过属性对来设置,或者者更改矩形区域的大小,如下所示:
rect1.left = 30
rect1.center = (70,70)
除了通过 Rect 对象来构造一个矩形区域之外,我们还可以使用rect
属性来构建一个矩形区域。在 Pygame 中有许多函数都提供了rect
属性,比如有下列函数:
surface.fill((0,0,255),rect=(100,100,100,50))
上述代码会在 surface 对象的区域内选定一个 rect 区域,并将该区域填充为蓝色(RGB(0,0,255))。
事件(Event)是 Pygame 的重要模块之一,它是构建整个游戏程序的核心,比如鼠标点击、键盘敲击、游戏窗口移动、调整窗口大小、触发特定的情节、退出游戏等等,这些都可以看做是“事件”,Pygame 会接受用户产生的各种操作(或事件),这些操作随时产生,并且操作量可大可小,那么 Pygame 是如何处理这些事件的呢?
Pygame 定义了一个专门用来处理事件的结构,即事件队列,该结构遵循遵循队列“先到先处理”的基本原则,通过事件队列,我们可以有序的、逐一的处理用户的操作(触发事件)。下述表格列出了 Pygame 中常用的游戏事件:
事件类型 | 描述 | 成员属性 |
---|---|---|
QUIT | 用户按下窗口的关闭按钮 | none |
ATIVEEVENT | Pygame被激活或者隐藏 | gain,state |
KEYDOWN | 键盘按下 | unicode、key、mod |
KEYUP | 键盘放开 | key、mod |
MOUSEMOTION | 鼠标移动 | pos, rel, buttons |
MOUSEBUTTONDOWN | 鼠标按下 | pos, button |
MOUSEBUTTONUP | 鼠标放开 | pos, button |
JOYAXISMOTION | 游戏手柄(Joystick or pad) 移动 | joy, axis, value |
JOYBALLMOTION | 游戏球(Joy ball) 移动 | joy, axis, value |
JOYHATMOTION | 游戏手柄(Joystick) 移动 | joy, axis, value |
JOYBUTTONDOWN | 游戏手柄按下 | joy, button |
JOYBUTTONUP | 游戏手柄放开 | joy, button |
VIDEORESIZE | Pygame窗口缩放 | size, w, h |
VIDEOEXPOSE | Pygame窗口部分公开(expose) | none |
USEREVENT | 触发一个用户事件 | 事件代码 |
注意,当使用 Pygame 做游戏开发时,上述事件并非都会应用的到,因此在学习的过程中,我们要懂得触类旁通、举一反三。
Pygame.event 模块提供了处理事件队列的常用方法,如下表所示:
方法 | 说明 |
---|---|
pygame.event.get() | 从事件队列中获取一个事件,并从队列中删除该事件 |
pygame.event.wait() | 阻塞直至事件发生才会继续执行,若没有事件发生将一直处于阻塞状态 |
pygame.event.set_blocked() | 控制哪些事件禁止进入队列,如果参数值为None,则表示禁止所有事件进入 |
pygame.event.set_allowed() | 控制哪些事件允许进入队列 |
pygame.event.pump() | 调用该方法后,Pygame 会自动处理事件队列 |
pygame.event.poll() | 会根据实际情形返回一个真实的事件,或者一个None |
pygame.event.peek() | 检测某类型事件是否在队列中 |
pygame.event.clear() | 从队列中清除所有的事件 |
pygame.event.get_blocked() | 检测某一类型的事件是否被禁止进入队列 |
pygame.event.post() | 放置一个新的事件到队列中 |
pygame.event.Event() | 创建一个用户自定义的新事件 |
当我们使用 Pygame 处理事件时,逻辑一般都是相似的。首先是判断事件的类型,然后根据不同的事件操作,执行不同的游戏操作。因此这种情况非常适合使用 if … else 语句。如下所示:
while True:
#等待事件发生
event = pygame.event.wait()
if event.type == pygame.QUIT:
exit()
if event.type == pygame.MOUSEBUTTONDOWN:
print('鼠标按下',event.pos)
if event.type == pygame.MOUSEBUTTONUP:
print('鼠标弹起')
if event.type == pygame.MOUSEMOTION:
print('鼠标移动')
# 键盘事件
if event.type ==pygame.KEYDOWN:
# 打印按键的英文字符
print('键盘按下',chr(event.key))
if event.type == pygame.KEYUP:
print('键盘弹起')
....
下面应用上述方法对鼠标事件和键盘事件分别做简单的介绍。
键盘事件会涉及到大量的按键操作,比如游戏中的上下左右,或者人物的前进、后退等操作,这些都需要键盘来配合实现。
键盘事件提供了一个 key 属性,通过该属性可以获取键盘的按键。Pygame 将键盘上的字母键、数字键、组合键等按键以常量的方式进行了定义,下表列出了部分常用按键的常量:
常量名 | 描述 |
---|---|
K_BACKSPACE | 退格键(Backspace) |
K_TAB | 制表键(Tab) |
K_CLEAR | 清除键(Clear) |
K_RETURN | 回车键(Enter) |
K_PAUSE | 暂停键(Pause) |
K_ESCAPE | 退出键(Escape) |
K_SPACE | 空格键(Space) |
K_0…K_9 | 0…9 |
K_a…Kz | a…z |
K_DELETE | 删除键(delete) |
K_KP0…K_KP9 | 0(小键盘)…9(小键盘) |
K_F1…K_F15 | F1…F15 |
K_UP | 向上箭头(up arrow) |
K_DOWN | 向下箭头(down arrow) |
K_RIGHT | 向右箭头(right arrow) |
K_LEFT | 向左箭头(left arrow) |
KMOD_ALT | 同时按下Alt键 |
想要了解更多按键常量可参考官方文档,这里有您想要的更多知识 ———> 点击前往。
下面通过“图片移动”示例来了解键盘事件的处理过程,如下所示:
import pygame
import sys
# 初始化pygame
pygame.init()
# 定义变量
size = width, height = 600, 400
bg = (255, 255, 255)
# 加载logo图
img = pygame.image.load("C:/Users/Administrator/Desktop/logo.jpg")
# 获取图像的位置
position = img.get_rect()
# 创建一个主窗口
screen = pygame.display.set_mode(size)
# 标题
pygame.display.set_caption("C语言中文网")
# 创建游戏主循环
while True:
# 设置初始值
site = [0, 0]
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# 图像移动 KEYDOWN 键盘按下事件
# 通过 key 属性对应按键
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
site[1] -= 8
if event.key == pygame.K_DOWN:
site[1] += 8
if event.key == pygame.K_LEFT:
site[0] -= 8
if event.key == pygame.K_RIGHT:
site[0] += 8
# 移动图像
position = position.move(site)
# 填充背景
screen.fill(bg)
# 放置图片
screen.blit(img, position)
# 更新显示界面
pygame.display.flip()
程序运行结果如下:
图1:Pygame键盘事件——图像移动
鼠标是计算机最重要外接设备之一,同时它也是游戏玩家必不可少的工具之一。
Pygame 提供了三个鼠标事件,分别是鼠标移动(MOUSEMOTION)、鼠标按下(MOUSEBUTTONDOWN)、鼠标释放(MOUSEBUTTONUP),不同事件类型对应着不同的成员属性。如下所示:
pygame.event.MOUSEMOTION鼠标移动事件
event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
event.rel 鼠标相对运动距离(X,Y),相对于上次事件
event.buttons 鼠标按钮初始状态(0,0,0),分别对应(左键,滑轮,右键),移动过程中点击那个键,相应位置变会为1
pygame.event.MOUSEBUTTONUP鼠标键释放事件
event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
event.button 鼠标释放键编号(整数)左键为1,按下滚动轮2、右键为3
pygame.event.MOUSEBUTTONDOWN 鼠标键按下事件
event.pos 相对于窗口左上角,鼠标的当前坐标值(x,y)
event.button 鼠标按下键编号(整数),左键为1,按下滚动轮2、右键为3,向前滚动滑轮4、向后滚动滑轮5
通过一组简单的示例对鼠标事件进行演示,示例代码如下:
import pygame
from random import randint
# 初始化程序
pygame.init()
screen = pygame.display.set_mode((450,400))
pygame.display.set_caption("c语言中文网")
# 更新显示
pygame.display.flip()
while True:
#等待事件发生
event = pygame.event.wait()
if event.type == pygame.QUIT:
exit("成功退出")
if event.type == pygame.MOUSEBUTTONDOWN:
# pos 获取鼠标当前位置
print('鼠标按下',event.pos)
mx,my = event.pos
# 调用 pygame.draw 模块画圆
pygame.draw.circle(screen,(255,255,0),(mx,my),50)
# 处理完,更新显示
pygame.display.update()
if event.type == pygame.MOUSEBUTTONUP:
print('鼠标弹起')
pass
if event.type == pygame.MOUSEMOTION:
print('鼠标移动')
mx, my = event.pos
# 随机生成 RGB 颜色值
r = randint(0,255)
g = randint(0,255)
b = randint(0,255)
pygame.draw.circle(screen, (r,g,b,),(mx, my), 50)
# 处理完,更新显示
pygame.display.update()
程序运行结果如下:
图2:Pygame鼠标事件——鼠标移动
Pygame 中提供了一个draw
模块用来绘制一些简单的图形状,比如矩形、多边形、圆形、直线、弧线等。
pygame.draw
模块的常用方法如下表所示:
方法 | 说明 |
---|---|
pygame.draw.rect() | 绘制矩形 |
pygame.draw.polygon() | 绘制多边形 |
pygame.draw.circle() | 根据圆心和半径绘制圆形 |
pygame.draw.ellipse() | 绘制一个椭圆形 |
pygame.draw.arc() | 绘制弧线(挥着椭圆的一部分) |
pygame.draw.line() | 绘制线段(直线) |
pygame.draw.lines() | 绘制多条连续的线段 |
pygame.draw.aaline() | 绘制一条平滑的线段(抗锯齿) |
pygame.draw.aalines() | 绘制多条连续的线段 |
表格中的函数使用方法大同小异,它们都可以在 Surface 对象上绘制一些简单的形状,返回值是一个 Rect 对象,表示实际绘制图形的矩形区域。上述绘图函数都提供了一个 color 参数,我们可以通过以下三种方式来传递 color 参数值:
下面通对上述一些方法的参数进行详细说明:
绘制矩形的语法格式如下:
pygame.draw.rect(surface, color, rect, width)
参数说明如下:
注意,当 width > 0 时,表示线框的宽度;而 width < 0 时,此时不会绘制任何图形。
pygame.draw.polygon(surface, color, points, width)
其中 points 一个列表参数,它表示组成多边形顶点的 3 或者多个 (x,y) 坐标,通过元组或者列表来表示这些多边形顶点。其余参数与上述函数相同。
pygame.circle(surface, color, pos, radius, width=0)
上述参数的含义如下:
pygame.draw.ellipse(surface, color, Rect, width=0)
绘制椭圆形的过程,其实就是在矩形区域内部(Rect)绘制一个内接椭圆形,其余参数与上述参数意思相同。
当需要绘制圆弧的曲线时,使用以下函数,语法格式如下:
pygame.draw.arc(Surface, color, Rect, start_angle, stop_angle, width=1)
与 ellipse 函数相比,该函数多了两个参数:
这两个都是用弧度制来表示的,而原点就是矩形 Rect 的中心位置。
Draw 模块提供了两类绘制直线的方法,即是否消除直线的锯齿,并且根据实际情况,我们还可以选择绘制一条或者多条直线。
pygame.draw.line(surface, color, start_pos, end_pos, width=1)
参数说明:
如果是绘制一条消除锯齿的平滑线,此时则使用 blend = 1 参数,如下所示:
pygame.aaline(surface, color, startpos, endpos, blend=1)
blend 参数表示通过绘制混合背景的阴影来实现抗锯齿功能。
当需要绘制多条直线的时候,我们可以使用以下方法:
pygame.lines(surface, color, closed, pointlist, width=1)
其中 pointlist 与 closed 含义如下:
如果绘制抗锯齿直线,使用以下方法:
pygame.draw.aalines(surface, color, closed, pointlist, blend=1)
除了指定了 blend = 1 之外,其余参数含义与上述函数相同。
下面通过一组简单的示例对上述绘图方法进行演示:
import pygame
from math import pi
#初始化
pygame.init()
# 设置主屏幕大小
size = (500, 450)
screen = pygame.display.set_mode(size)
#设置标题
pygame.display.set_caption("C语言中文网")
# 设置一个控制主循环的变量
done = False
#创建时钟对象
clock = pygame.time.Clock()
while not done:
# 设置游戏的fps
clock.tick(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True # 若检测到关闭窗口,则将done置为True
# 绘制一条宽度为 3 的红色对角线
pygame.draw.line(screen, (0, 255, 0), [0, 0], (500, 450), 3)
# 绘制多条蓝色的直线(连续直线,非抗锯齿),False 表示首尾不相连
pygame.draw.lines(screen, (0, 0, 255), False, [[0, 80], [50, 90], [200, 80], [220, 30]], 1)
# 绘制一个灰色的矩形区域,以灰色填充区域
pygame.draw.rect(screen, (155, 155, 155), (75, 10, 50, 20), 0)
# 绘制一个线框宽度为2的矩形区域
pygame.draw.rect(screen, (0, 0, 0), [150, 10, 50, 20],2)
# 绘制一个椭圆形,其线宽为2
pygame.draw.ellipse(screen, (255, 0, 0), (225, 10, 50, 20), 2)
# 绘制一个实心的红色椭圆形
pygame.draw.ellipse(screen, (255, 0, 0), (300, 10, 50, 20))
# 绘制一个绿色边框(宽度为2)三角形
pygame.draw.polygon(screen, (100, 200, 45), [[100, 100], [0, 200], [200, 200]], 2)
# 绘制一个蓝色实心的圆形,其中[60,250]表示圆心的位置,40为半径,width默认为0
pygame.draw.circle(screen, (0, 0, 255), [60, 250], 40)
# 绘制一个圆弧,其中0表示弧线的开始位置,pi/2表示弧线的结束位置,2表示线宽
pygame.draw.arc(screen, (255, 10, 0), (210, 75, 150, 125), 0, pi / 2, 2)
# 刷新显示屏幕
pygame.display.flip()
# 点击关闭,退出pygame程序
pygame.quit()
程序的运行结果如下所示:
图1:Pygame绘图函数用法
文本是任何一款游戏中不可或缺的重要要素之一,Pygame 通过pygame.font
模块来创建一个字体对象,从而实现绘制文本的目的。该模块的常用方法如下所示:
方法 | 说明 |
---|---|
pygame.font.init() | 初始化字体模块 |
pygame.font.quit() | 取消初始化字体模块 |
pygame.font.get_init() | 检查字体模块是否被初始化,返回一个布尔值。 |
pygame.font.get_default_font() | 获得默认字体的文件名。返回系统中字体的文件名 |
pygame.font.get_fonts() | 获取所有可使用的字体,返回值是所有可用的字体列表 |
pygame.font.match_font() | 从系统的字体库中匹配字体文件,返回值是完整的字体文件路径 |
pygame.font.SysFont() | 从系统的字体库中创建一个 Font 对象 |
pygame.font.Font() | 从一个字体文件创建一个 Font 对象 |
Font 模块提供了两种创建字体(Font)对象的方法,分别是:
下面对这两种方法分分别进行介绍:
直接从系统中加载字体使用如下方法:
pygame.font.SysFont(name, size, bold=False, italic=False)
name:列表参数值,表示要从系统中加载的字体名称,它会按照列表中的元素顺序依次搜索,如果系统中没有列表中的字体,将使用 Pygame 默认的字体。
使用示例如下:
print("获取系统中所有可用字体",pygame.font.get_fonts())
my_font = pygame.font.SysFont(['方正粗黑宋简体','microsoftsansserif'],50)
上述方法将优先使用“方正粗黑宋简体”。
注意,如果要显示中文,那么一定要使用中文字体文件,比如“方正粗黑宋简体”,否则会出现文字乱码的现象(编程帮三个字无法显示)。如下所示:
图1:显示中文乱码
当我们想要在游戏中引入比较炫酷的字体,而系统中又不存在时,我们可以使用另外一种方法,从外部加载字体文件来绘制文本。其语法格式如下:
my_font = pygame.font.Font(filename, size)
参数说明如下:
使用示例如下:
f = pygame.font.Font('C:/Users/Administrator/Desktop/willhar_.ttf',50)
从桌面加载了一个字体文件来创建字体对象,并设置字体大小为 50。注意,上述字体文件是在网上下载的,您也可以任意下载(点击网址前往),或者使用系统库中的字体文件。
Pygame 为处理字体对象提供了一些常用方法,如下所示:
方法 | 说明 |
---|---|
pygame.font.Font.render() | 该函数创建一个渲染了文本的 Surface 对象 |
pygame.font.Font.size() | 该函数返回渲染文本所需的尺寸大小,返回值是一个一元组 (width,height) |
pygame.font.Font.set_underline() | 是否为文本内容绘制下划线 |
pygame.font.Font.get_underline() | 检查文本是否绘制了下划线 |
pygame.font.Font.set_bold() | 启动粗体字渲染 |
pygame.font.Font.get_bold() | 检查文本是否使用粗体渲染 |
pygame.font.Font.set_italic() | 启动斜体字渲染 |
pygame.font.Font.metrics() | 获取字符串中每一个字符的详细参数 |
pygame.font.Font.get_italic() | 检查文本是否使用斜体渲染 |
pygame.font.Font.get_linesize() | 获取字体文本的行高 |
pygame.font.Font.get_height() | 获取字体的高度 |
pygame.font.Font.get_ascent() | 获取字体顶端到基准线的距离 |
pygame.font.Font.get_descent() | 获取字体底端到基准线的距离 |
使用上述方法,我们可以非常方便地对字体进行渲染,或者获取字体的相关信息,比如字体的高度、是否是粗体、斜体等信息。
上述方法中使用最多要数第一个方法,它是绘制文本内容的关键方法,其语法格式如下:
render(text, antialias, color, background=None)
参数说明如下所示:
下面看一组简单的示例:
import sys
import pygame
# 初始化
pygame.init()
screen = pygame.display.set_mode((600,400))
#填充主窗口的背景颜色
screen.fill((20,90,50))
#设置窗口标题
pygame.display.set_caption('c语言中文网')
# 字体文件路径 C:/Windows/Fonts/simhei.ttf
f = pygame.font.Font('C:/Windows/Fonts/simhei.ttf',50)
# render(text, antialias, color, background=None) -> Surface
text = f.render("网址:c.biancheng.net",True,(255,0,0),(255,255,255))
#获得显示对象的 rect区域大小
textRect =text.get_rect()
#设置显示对象居中
textRect.center = (300,200)
screen.blit(text,textRect)
while True:
# 循环获取事件,监听事件
for event in pygame.event.get():
# 判断用户是否点了关闭按钮
if event.type == pygame.QUIT:
#卸载所有pygame模块
pygame.quit()
#终止程序
sys.exit()
pygame.display.flip() #更新屏幕内容
程序运行结果如下所示:
图2:显示文本内容
除了使用上述方法之外,Pygame 为了增强字体模块的功能,在新的版本中又加入了另外一个字体模块,它就是 Freetype 模块。该模块属于 Pygame 的高级模块, 它能够完全可以取代 Font 模块,并且在 Font 模块的基础上又添加了许多新功能,比如调整字符间距离,字体垂直模式以及逆时针旋转文本等(详情可阅读官方文档)。
如果想 Freetype 模块,必须使用以下方式导包:
import pygame.freetype
下面使用 Freetype 模块来绘制文本内容,代码如下:
import sys,pygame
import pygame.freetype
pygame.init()
# 设置位置变量
pos=[180,50]
# 设置颜色变量
GOLD=255,251,0
BLACK=0,0,0
screen=pygame.display.set_mode((600,400))
pygame.display.set_caption("c语言中文网")
f1=pygame.freetype.Font("C:/Users/Administrator/Desktop/willhar_.ttf",45)
# 注意,这里使用render_to() 来绘制文本内容,与render 相比,该方法无返回值
# 参数说明:
# pos 绘制文本开始的位置,fgcolor表示前景色,bgcolor表示背景色,rotation表示文本旋转的角度
freeRect = f1.render_to(screen, pos,"I love c.biancheng.net",fgcolor = GOLD,bgcolor = BLACK, rotation=35)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
pygame.display.update()
程序运行结果如下:
图3:绘制文本内容
在开始学习相关知识点之前,我们有必要先学习精灵和碰撞检测的含义。
精灵(英文译为 Sprite),其实在一个游戏程序中,精灵本质指的是一张张小尺寸的图片,比如游戏中的各种道具、人物、场景装饰等,它们都可以看做成一张张小的“精灵”图。除此之外,人物的移动也可以看做是一系列小精灵图构成的序列(按帧组成的序列),如下图所示:
图1:动作逐帧分解图
如果将逐帧分解后的动作,按照一定的频率播放,那么就形成了动画精灵,您将会看到雄鹰展翅高飞、人在策马奔腾、运动员奋力跳远。
精灵有个特点就是允许精灵之间进行交互,也称之为碰撞,而碰撞检测,指的就是检测两个精灵之间是否发生了碰撞。比如在贪吃蛇游戏中蛇的头部是否与食物发生了碰撞,或者飞机大战游戏中子弹是否击中了外星人等等。当检测到碰撞发生后,接下来会触发某些事件,比如子弹击中外星人,外星人就会消失,玩家的得分也会随之增加,并且在游戏屏幕上又会出现一个外星人。
Pygame 专门提供了一个处理精灵的模块,也就是 sprite(pygame.sprite)模块。通常情况下,我们使用该模块的基类 Sprite 来创建一个子类,从而达到处理精灵的目的,该子类提供了操作精灵的常用属性和方法,如下所示:
属性&方法 | 说明 |
---|---|
self.image | 加载要显示的精灵图片,控制图片大小和填充色 |
self.rect | 精灵图片显示在哪个位置 |
Sprite.update() | 刷新精灵图,使其相应效果生效 |
Sprite.add() | 添加精灵图到精灵组中(groups) |
Sprite.remove() | 从精灵组中删除选中的精灵图 |
Sprite.kill() | 删除精灵组中全部的精灵 |
Sprite.alive() | 判断某个精灵是否属于精灵组 |
注意,当游戏中有大量的精灵时,操作它们将变得复杂,此时通过构建精灵容器(group 类)也就是精灵组来统一管理这些精灵。构建方法如下:
# 创建精灵组
group = pygame.sprite.Group()
# 向组内添加一个精灵
group.add(sprite_one)
于此同时pygame.sprite
模块也提供了多种检测精灵是否碰撞的方法,如下所示:
方法 | 说明 |
---|---|
pygame.sprite.collide_rect() | 两个精灵之间的矩形检测,即矩形区域是否有交汇,返回一个布尔值。 |
pygame.sprite.collide_circle() | 两个精灵之间的圆形检测,即圆形区域是否有交汇,返回一个布尔值。 |
pygame.sprite.collide_mask() | 两个精灵之间的像素蒙版检测,更为精准的一种检测方式。 |
pygame.sprite.spritecollide() | 精灵和精灵组之间的矩形碰撞检测,一个组内的所有精灵会逐一地对另外一个单个精灵进行碰撞检测,返回值是一个列表,包含了发生碰撞的所有精灵。 |
pygame.sprite.spritecollideany() | 精灵和精灵组之间的矩形碰撞检测,上述函数的变体,当发生碰撞时,返回组内的一个精灵,无碰撞发生时,返回 None。 |
pygame.sprite.groupcollide() | 检测在两个组之间发生碰撞的所有精灵,它返回值是一个字典,将第一组中发生碰撞的精灵作为键,第二个组中发生碰撞的精灵作为值。 |
下面看一组简单的示例,代码如下所示:
import pygame
class Snake(pygame.sprite.Sprite):
#定义构造函数
def __init__(self,filename,location):
# 调父类来初始化子类
pygame.sprite.Sprite.__init__(self)
# 加载图片
self.image = pygame.image.load(filename)
# 获取图片rect区域
self.rect = self.image.get_rect()
# 设置位置
self.rect.topleft=location
# 初始化pygame
pygame.init()
screen = pygame.display.set_mode((500,400))
pygame.display.set_caption('C语言中文网')
# 填充为白色屏幕
screen.fill((255,255,255))
filename ="C:/Users/Administrator/Desktop/snake.png"
location =(100,150)
snake1 = Snake(filename,location)
# 碰撞检测,必须有两个精灵,因此再创建一个精灵,并使用location来控制第二个精灵的位置
location_2 = (100,80)
snake2 = Snake('C:/Users/Administrator/Desktop/logo.png',location_2)
# 调用 collide_rect()进行矩形区域检测,返回一个布尔值,碰撞返回True,否则返回False
crash_result = pygame.sprite.collide_rect(snake1,snake2)
if crash_result:
print("精灵碰撞了!")
pass
else:
print('精灵没碰撞')
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# 绘制精灵到屏幕上
screen.blit(snake1.image,snake1.rect)
screen.blit(snake2.image,snake2.rect)
# 刷新显示屏幕
pygame.display.update()
当精灵没有发生碰撞时,程序的运行结果如下:
图2:运行结果
接下来,我们将 snake2 的location_2
参数变为 (100,140),然后再次运行程序,这时两个精灵就会发生碰撞,运行结果如下:
图3:运行结果
除上述内容外,Pygame 还提供许多其他模块,比如 mixer(声音)、movie(播放视频)、music(播放音频)、sndarray(操作声音数据)等模块,由于这些模块使用起来较为简单,因此这里不再逐一介绍,感兴趣的朋友可以阅读 Pygame 官方文档 —>点击前往!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。