当前位置:   article > 正文

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

pygame模块详解

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

一、pygame介绍

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

二、pygame库的安装

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

pip install pygame
  • 1

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

三、pygame库的导入

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

import pygame
  • 1

四、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))
  • 1
  • 2
  • 3
  • 4

六、创建游戏主窗口

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 pygame

pygame.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 fullscreen
                if fullscreen:
                    screen = pygame.display.set_mode((1440, 900), pygame.FULLSCREEN)
                else:
                    screen = pygame.display.set_mode((960, 600), 0)
    pygame.display.update() #更新窗口
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

案例:窗口RESIZABLE变换

import pygame

pygame.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)
            pass
    pygame.display.update()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

(二)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()
    # 将背景图像绘制于窗口表面windowSurface
    windowSurface.blit(bgSurface, (0, 0))
    # 绘制结束,刷新界面
    pygame.display.update()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

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

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

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

相关代码如下:

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:
    # 将背景图像绘制于窗口表面windowSurface
    for event in pygame.event.get():
        # 处理退出事件
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    windowSurface.blit(bgSurface, (0, 0))
    # 绘制结束,刷新界面
    pygame.display.update()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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

(二)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:
    # 将背景图像绘制于窗口表面windowSurface
    for 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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

八、时钟对象

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

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

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

clock = pygame.time.Clock()
i = 0
# 游戏循环
while True:
    # 设置屏幕刷新帧率
    clock.tick(60)
    print(i)
    i += 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

事件 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

下表是一个常用事件集:

事件说明
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(二)监听键盘操作

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                move_x = -1
            elif event.key == K_RIGHT:
                move_x = 1
            elif event.key == K_UP:
                move_y = -1
            elif event.key == K_DOWN:
                move_y = 1
        elif event.type == KEYUP:
            move_x = 0
            move_y = 0

    x += move_x
    y += move_y

    screen.fill((0, 0, 0))
    screen.blit(img, (x, y))
    # 在新的位置上画图
    pygame.display.update()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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 code

    pygame.display.update()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

十、一个完整的pygame主程序

import pygame
import sys

pygame.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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/98368
推荐阅读
相关标签
  

闽ICP备14008679号