pygame的基础知识详解(主窗口创建、图像绘制、时钟对象和事件响应等知识点),请惠存

各位好,很久没更新博客了,最近较为深入研究pygame库,有些心得体会,想分享给各位,准备做成一个系列知识。欢迎各位查阅。
这篇作为一个基础知识的宣贯,想和各位深入分享一下pygame的基础知识,深入理解函数的使用。

一、pygame介绍

pygame是一个非常非常火的游戏库,那么作为游戏,我相信大家第一印象就是包括:游戏的主界面、游戏里面酷炫的动态效果。

二、pygame库的安装

这个相信大家都懂了,就不深入介绍了。

pip install pygame

如果下载很慢,可以搜索一下国内的pip源下载。

三、pygame库的导入

在python代码中,需要使用到该库时,需要进行导入。

import pygame

四、pygame库的初始化和退出

要使用 pygame 提供的所有功能之前,需要调用 init 方法,在游戏结束前需要调用一下 quit 方法

(一)pygame.init()

导入并初始化所有 pygame 模块,使用其他模块之前,必须先调用 init 方法

(二)pygame.quit()

卸载所有 pygame 模块,在游戏结束之前调用!

五、pygame界面的坐标系

pygame 专门提供了一个类 pygame.Rect 用于描述 矩形区域Rect(x, y, width, height) -> Rect

所有可见的元素 都是以 矩形区域 来描述位置的,要描述一个矩形区域有四个要素:原点 在 左上角 (0, 0),其中:x 轴水平方向向右,逐渐增加;y 轴 垂直方向向 下,逐渐增加。

示例代码如下:

import pygame
pygame.init()
myrect = pygame.Rect(300, 500, 200, 256)
print("myrect坐标原点:%d %d 大小:%d %d" % (myrect.x, myrect.y,myrect.width, myrect.height))

六、创建游戏主窗口

pygame 专门提供了一个 模块 pygame.display 用于创建、管理 游戏窗口

方法 说明
pygame.display.set_mode() 初始化显示窗口
pygame.display.update() 更新部分内容显示到屏幕上,如果没有参数,则与flip功能相同
pygame.display.flip() 更新整个待显示的Surface对象到屏幕上

(一)set_mode函数

set_mode(resolution=(0,0), flags=0, depth=0) -> Surface
第一个参数为元祖,代表分 辨率(必须);
第二个参数是一个标志位,如果不用什么特性,就指定0;
第三个参数为色深。

参数 说明
resolution 指定屏幕的 宽 和 高,默认创建的窗口大小和屏幕大小一致
flags 参数指定屏幕的附加选项,例如是否全屏等等,默认不需要传递
depth 参数表示颜色的位数,默认自动匹配

返回值:Surface对象(可以理解为:游戏的屏幕),游戏的元素 都需要被绘制到游戏的屏幕上,后续所有的图像绘制都基于这个返回结果

  • 附上flags标识位
flags标识位 功能
FULLSCREEN 创建一个全屏窗口
DOUBLEBUF 创建一个“双缓冲“窗口,建议在HWSURFACE或OPENGL时使用
HWSURFACE 创建一个硬件加速窗口,必须和FULLSCREEN同时使用
OPENGL 创建一个OPENGL渲染的窗口
RESIZABLE 创建一个可以改变大小的窗口
NOFRAME 创建一个没有边框的窗口

案例:创建一个全屏窗口并F2切换

import pygamepygame.init()  #游戏初始化的设置,他应该在游戏代码编写的最前边
screen = pygame.display.set_mode((960, 600))  #创建窗口以进行显示;screen定义了一个游戏的屏幕,后续游戏场景中的游戏对象,都要在这个screen上绘制
pygame.display.set_caption("全屏窗口切换")    #设置当前游戏窗口的标题
fullscreen = False
while True:screen.fill((0, 255, 255))for event in pygame.event.get():  #pygame.event.get()  游戏中的事件if event.type == pygame.QUIT:  #如果事件类型是退出exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_F2:fullscreen = not fullscreenif fullscreen:screen = pygame.display.set_mode((1440, 900), pygame.FULLSCREEN)else:screen = pygame.display.set_mode((960, 600), 0)pygame.display.update() #更新窗口

案例:窗口RESIZABLE变换

import pygamepygame.init()
SCREEN_SIZE = (640, 480)
screen = pygame.display.set_mode(SCREEN_SIZE,pygame.RESIZABLE)pygame.display.set_caption("窗口RESIZABLE变换")
fullscreen = False
while True:screen.fill((0, 255, 255))for event in pygame.event.get():if event.type == pygame.QUIT:exit()if event.type == pygame.VIDEORESIZE:   #如果窗口大小发生了变化SCREEN_SIZE=event.size   #返回当前窗口大小--元组(宽,高)print(event.size)screen = pygame.display.set_mode(SCREEN_SIZE, pygame.RESIZABLE)passpygame.display.update()

(二)update函数

显示屏幕的更新部分,在调用了绘制函数以便让显示Surface对象看上去是你想要的方式之后,必须调用pygame.display.update()让显示Surface真正地出现在用户的显示器上。

属性:
update(rectangle=None) -> None
update(rectangle_list) -> None

此函数类似于用于软件显示的pygame.display.flip()的优化版本。它只允许更新屏幕的一部分,而不是整个区域。如果没有传递参数,它将更新整个表面积,如pygame.display.flip()。
可以向函数传递单个矩形或一系列矩形。一次传递多个矩形比使用单个或部分矩形列表多次调用update更有效。如果传递了一个不包含任何值矩形序列,则会被跳过。

(三)flip函数

将整个显示 Surface 更新到屏幕

属性:flip() -> None

这将更新整个显示的内容。如果set_mode函数中设置了显示模式使用的flags是 pygame.HWSURFACEpygame.DOUBLEBUF,则将等待垂直回溯并交换曲面。如果使用的是不同类型的显示模式,则只需更新窗口的全部内容。

(四)update和flip的区别

flip函数将重新绘制整个屏幕对应的窗口。
update函数仅仅重新绘制窗口中有变化的区域。
如果仅仅是几个物体在移动,那么他只重绘其中移动的部分,没有变化的部分,并不进行重绘。update比flip速度更快。

在一般的游戏中,如果不是场景变化非常频繁的时候,我们建议使用update函数,而不是flip函数。但是,当使用OpenGL的时候,不能使用pygame.display.update()来更新窗口,需要使用pygame.display.flip()来更新

七、图像绘制

在游戏中,能够看到的 游戏元素 大多都是 图像
图像文件 初始是保存在磁盘上的,如果需要使用,第一步 就需要 被加载到内存,要在屏幕上 看到某一个图像的内容,需要按照三个步骤:

1、 使用 pygame.image.load() 加载图像的数据 使用 游戏屏幕 对象,
2、使用convert函数是将图像数据都转化为Surface对象,每次加载完图像以后就应该做这件事件(如果你不写pygame也会帮你做);convert_alpha相比convert,保留了Alpha通道信息。
3、调用 blit 方法 将图像绘制到指定位置

(一)load和convert函数

使用 pygame.image.load() 加载图像的数据 使用 游戏屏幕 对象。

import pygame
import sys
# 全局初始化
pygame.init()
# 设置窗口的分辨率和标题
resolution = width,height = 480,700 #设置窗口大小和标题
windowSurface = pygame.display.set_mode(resolution) #设置分辨率并得到全局的【绘图表面】
pygame.display.set_caption("风景如画")#设置标题
#加载背景图,返回的表面可以用于绘制其它对象于其上
bgSurface = pygame.image.load("temp.jpg").convert()
while True:for event in pygame.event.get():# 处理退出事件if event.type == pygame.QUIT:pygame.quit()sys.exit()# 将背景图像绘制于窗口表面windowSurfacewindowSurface.blit(bgSurface, (0, 0))# 绘制结束,刷新界面pygame.display.update()

可以在 screen 对象完成 所有 blit 方法之后,统一调用一次 display.update 方法,同样可以在屏幕上 看到最终的绘制结果。display.update() 会将 画布 的 最终结果 绘制在屏幕上,这样可以 提高屏幕绘制效率,增加游戏的流畅度。

效果图:
在这里插入图片描述
原图:
在这里插入图片描述
可以发现原图和效果图对比,明显显示不全。那么我们如何可以显示全呢?
这里就使用了另外的一个函数pygame.transform.scale,通过该函数调整文件的大小,适配整个屏幕。

picture = pygame.transform.scale(pygame.image.load("image/cc.png"), (480,700))
# (480,700)标识图片的大小信息。

相关代码如下:

import pygame
import sys# 全局初始化
pygame.init()# 设置窗口的分辨率和标题
resolution = width,height = 480,700 #设置窗口大小和标题
windowSurface = pygame.display.set_mode(resolution) #设置分辨率并得到全局的【绘图表面】
pygame.display.set_caption("风景如画")#设置标题#加载背景图,返回的表面可以用于绘制其它对象于其上
bgSurface = pygame.transform.scale(pygame.image.load("temp.jpg"), (480, 700)).convert()
while True:# 将背景图像绘制于窗口表面windowSurfacefor event in pygame.event.get():# 处理退出事件if event.type == pygame.QUIT:pygame.quit()sys.exit()windowSurface.blit(bgSurface, (0, 0))# 绘制结束,刷新界面pygame.display.update()

效果图:
在这里插入图片描述
可以看到,显示是完整了,但是图片明显是别压缩过。

(二)blit函数

surface.blit(image,(x,y),rect)

那么,我们可以尝试一下让图片动起来。

import pygame
import sys# 全局初始化
pygame.init()# 设置窗口的分辨率和标题
resolution = width,height = 480,700 #设置窗口大小和标题
windowSurface = pygame.display.set_mode(resolution) #设置分辨率并得到全局的【绘图表面】
pygame.display.set_caption("风景如画")#设置标题#加载背景图,返回的表面可以用于绘制其它对象于其上
bgSurface = pygame.image.load("temp.jpg").convert()
frameRect = bgSurface.get_rect()
clock = pygame.time.Clock()
while True:# 将背景图像绘制于窗口表面windowSurfacefor event in pygame.event.get():# 处理退出事件if event.type == pygame.QUIT:pygame.quit()sys.exit()windowSurface.blit(bgSurface, (0, 0),frameRect)frameRect.x += 1# 绘制结束,刷新界面pygame.display.flip()# 时钟停留一帧的时长clock.tick(60)

效果图:
在这里插入图片描述

八、时钟对象

pygame 专门提供了一个类 pygame.time.Clock 可以非常方便的设置屏幕绘制速度 —— 刷新帧率,要使用 时钟对象 需要两步:

1)在 游戏初始化 创建一个 时钟对象
2)在 游戏循环 中让时钟对象调用 tick(帧率) 方法

tick 方法会根据 上次被调用的时间,自动设置 游戏循环 中的延时:

clock = pygame.time.Clock()
i = 0
# 游戏循环
while True:# 设置屏幕刷新帧率clock.tick(60)print(i)i += 1

九、在游戏循环中 监听 事件

事件 event:
就是游戏启动后,用户针对游戏所做的操作
例如:点击关闭按钮,点击鼠标,按下键盘…

在 游戏循环 中,判断用户 具体的操作,只有 捕获 到用户具体的操作,才能有针对性的做出响应pygame 中通过 pygame.event.get() 可以获得 用户当前所做动作 的 事件列表

#初始化时钟对象
clock = pygame.time.Clock()
#游戏循环
while True:# 设置屏幕刷新帧率clock.tick(60)# 事件监听for event in pygame.event.get():# 判断用户是否点击了关闭按钮if event.type == pygame.QUIT:print("退出游戏...")pygame.quit()

下表是一个常用事件集:

事件 说明
QUIT 用户按下关闭按钮
KEYDOWN 键盘被按下
KEYUP 键盘被放开
MOUSEMOTION 鼠标移动
MOUSEBUTTONDOWN 鼠标按下
MOUSEBUTTONUP 鼠标放开
VIDEORESIZE 窗口缩放

(一)监听鼠标操作

while True:for event in pygame.event.get():if event.type == QUIT:# 接收到退出时间后退出程序exit()# 获得鼠标位置x, y = pygame.mouse.get_pos()# 将光标画上去screen.blit(img, (x, y))# 刷新画面pygame.display.update()

(二)监听键盘操作

while True:for event in pygame.event.get():if event.type == QUIT:exit()if event.type == KEYDOWN:if event.key == K_LEFT:move_x = -1elif event.key == K_RIGHT:move_x = 1elif event.key == K_UP:move_y = -1elif event.key == K_DOWN:move_y = 1elif event.type == KEYUP:move_x = 0move_y = 0x += move_xy += move_yscreen.fill((0, 0, 0))screen.blit(img, (x, y))# 在新的位置上画图pygame.display.update()

KEYDOWN和KEYUP的参数说明:

  • key- 按下或者放开的键值,是一个数字,估计地球上很少有人可以记住,所以Pygame中你可以使用K_xxx来表示,比如字母a就是K_a,还有K_SPACE和K_RETURN等。
  • mod -包含了组合键信息,如果mod & KMOD_CTRL是真值,表示用户同时按下了Ctrl键。类似的还有KMOD_SHIFT,KMOD_ALT。

(三)监听窗口缩放

使用VIDEORESIZE进行事件监听。

while True:event = pygame.event.wait()if event.type == VIDEORESIZE:add user codepygame.display.update()

十、一个完整的pygame主程序

import pygame
import syspygame.init()resolution = width,height = 800,600 #设置窗口大小和标题
windowSurface = pygame.display.set_mode(resolution) #设置分辨率并得到全局的【绘图表面】
pygame.display.set_caption("风景如画")#设置标题bgSurface = pygame.image.load("temp.jpg").convert()# 创建时钟对象
clock = pygame.time.Clock()if __name__ == '__main__':while True:# 处理用户输入for event in pygame.event.get():# 处理退出事件if event.type == pygame.QUIT:pygame.quit()sys.exit()windowSurface.blit(bgSurface, (0, 0))# 绘制结束,刷新界面pygame.display.flip()# 时钟停留一帧的时长clock.tick(60)

运行效果如下:
在这里插入图片描述

好的,其实,这篇博文只是想跟大家介绍一下pygame库中的主要函数、实现流程及相关的主要对象,让大家有一个粗略的、较为概念性的认识,后面将会有更多的实战案例和细节分享给大家

欢迎大家持续关注,感谢支持!

Published by

风君子

独自遨游何稽首 揭天掀地慰生平