如何创建游戏窗口?以及获取和设置窗口与屏幕信息等问题
关注 1800
如何在 Pygame 中创建窗口,以及设置标题和切换全屏视频演示 YouTube如何在 Pygame 中创建窗口,以及设置标题和切换全屏视频演示 Bilibili
Pygame 中的 display 模块
Pygame 包的display模块,提供了与游戏窗口,屏幕相关的功能,当你导入pygame模块时,display模块会被pygame模块导入。
初始化 display 模块
与pygame模块一样,display模块拥有用于初始化的函数init,该函数会在pygame模块的init函数中被调用,这意味着一旦使用pygame模块进行初始化,调用display模块的init函数将是没有必要的。
init()
可以重复调用 init 函数
你可以反复调用init函数,这没有任何问题,即便在调用quit函数之后。
# 导入模块 display
from pygame import display
# 初始化
display.init()判断 display 模块是否已经初始化
与pygame模块一样,display模块拥有判断display模块是否已经初始化的函数get_init。
get_init()
- 返回值
如果
get_init函数返回True,那么表示display模块已经进行了初始化。
在调用 quit 函数之后,get_init 函数将返回 False
在调用quit函数之后,get_init函数将返回False,这表示再次调用init函数将产生实际效果,他会重新初始化display模块。
# …
print(f'display 已经初始化?{display.get_init()}')display 已经初始化?True取消初始化 display 模块
与pygame模块一样,display模块拥有用于取消初始化的函数quit,该函数会在pygame模块的quit函数中被调用,这意味着一旦使用pygame模块取消了初始化,调用display模块的quit函数将是没有必要的。
quit()
调用 quit 函数将导致游戏窗口被关闭
如果你已经向玩家展示了游戏窗口,那么调用quit函数将导致这些游戏窗口被关闭。
可以重复调用 quit 函数
和init函数一样,你可以反复调用quit函数,这没有任何的问题。
创建游戏窗口
display模块的set_mode函数,将根据给出的显示模式(可理解为参数的组合)创建游戏窗口和一个表示表面的Surface对象,根据参数的不同,游戏窗口将以不同的状态显示。set_mode函数会返回创建的Surface对象,并调用init函数,如果display模块尚未进行初始化。
如果游戏窗口已经被创建,那么再次调用display模块的set_mode函数,将改变游戏窗口的显示模式,比如表面的大小。
set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0)
- size 参数
size参数是一个 Python 数字序列对象(比如元组,列表),其第一个元素表示窗口表面的宽度,第二个元素表示窗口表面的高度,或一个 PygameVector2对象(对象的x变量对应表面宽度,对象的y变量对应表面高度)。如果
size参数所包含的宽度和高度为0,那么set_mode函数将创建一个表面大小和屏幕大小相同的窗口。- flags 参数
flags参数是一个整数,他决定了被创建的游戏窗口将以何种方式被显示。pygame模块提供了以下的变量,你可以使用或位运算符|来组合他们,并作为flags参数的值。FULLSCREEN(窗口将全屏显示),DOUBLEBUF(窗口将使用双缓冲,仅在采用 OpenGL 进行渲染时有效),OPENGL(窗口将采用 OpenGL 进行渲染),RESIZABLE(窗口可以被改变大小),NOFRAME(窗口将没有边框),SCALED(根据屏幕或窗口大小等比例缩放窗口表面,不会改变窗口对应的Surface对象的大小),SHOWN(默认值,窗口将被打开并显示),HIDDEN(窗口将被打开并隐藏)。- depth 参数
depth参数是一个表示颜色深度的整数,一般情况下,设置该参数是没有必要的,因为系统会自动选择最合适的颜色深度,除非你希望使用自己的像素格式。需要指出的是,随意设置
depth参数可能导致游戏运行缓慢。- display 参数
display参数是一个整数,用于表示窗口将显示在第几个屏幕中,如果为0(默认值),那么窗口将显示在默认的屏幕中,如果为1,那么窗口将显示在第二个屏幕中。- vsync 参数
vsync参数是一个整数,如果为1,那么窗口将尝试采用垂直同步,如果flags参数采用了OPENGL或SCALED的话。当然,是否能够采用垂直同步,还取决于计算机硬件以及显示驱动的配置。
- 返回值
set_mode函数的返回值是一个表示表面的Surface对象。
SDL 1.2.10 之前,如果set_mode函数的size参数所表示的宽度和高度为零,那么将导致异常。
在 Pygame 2 中,pygame模块的HWSURFACE变量已经被弃用,之前他可作为set_mode函数的flags参数的值,表示窗口将在全屏模式下启用硬件加速。
游戏窗口的表面大小可能与传递给 set_mode 函数的 size 参数的值不符
在全屏模式或允许改变窗口大小的情况下,游戏窗口的表面的大小(窗口对应的Surface对象的大小)可能与传递给set_mode函数的size参数的值不相符。比如,在调用set_mode函数时,将flags参数设置为FULLSCREEN,将size参数设置为(540,960),而目标屏幕的大小为 1920x1080,那么 Pygame 会自行调整窗口表面的大小,这可能会导致玩家看到不应该出现的内容。
表面
关于表面对象Surface,你可以查看如何使用 Surface 表面对象?以及表面(图像)的透明度,透明颜色键,颜色,大小等问题一节。
在下面的示例中,我们设置游戏窗口的表面大小为 600x400,并为全屏显示模式,最终,窗口的表面大小被设置为了 640x480。
由于没有编写游戏循环,以及检测游戏事件的代码,因此被创建的游戏窗口仅支持少量的用户操作。
# …
from pygame import RESIZABLE, FULLSCREEN
# 创建一个表面 700x500,可以改变大小的窗口
s = display.set_mode([700, 500], RESIZABLE)
print(f'表面大小:{s.get_size()}')
# 更改为全屏显示,表面大小 600x400
s = display.set_mode((600, 400), FULLSCREEN)
print(f'表面大小:{s.get_size()}')
# 等待 3 秒
import time
time.sleep(3)表面大小:(700, 500)
# 表面的大小发生了改变
表面大小:(640, 480)如何使用 set_mode 函数确保游戏窗口的表面大小不会发生改变?
要确保游戏窗口的表面大小不发生改变,你可以将pygame模块的SCALED变量加入set_mode函数的flags参数,虽然游戏窗口的表面将根据屏幕或窗口大小进行等比例缩放,但窗口对应的Surface对象的大小不会发生变化。
与之前的示例不同,当我们将SCALED加入flags参数之后,全屏显示的游戏窗口的表面大小并不会改变。
from pygame import display, FULLSCREEN, SCALED
# 全屏显示,表面大小 600x400,可缩放
s = display.set_mode((600, 400), FULLSCREEN | SCALED )
print(f'表面大小:{s.get_size()}')表面大小:(600, 400)不能使用 set_mode 函数随意修改显示模式
你可以使用display模块的set_mode函数来修改游戏窗口的显示模式,但一些参数组合可能会在反复修改显示模式的过程中导致异常,虽然最初采用这些组合时,不会产生任何的问题。
在某些情况下,如果第一次调用set_mode函数时没有采用SCALED,那么修改显示模式时也不能采用SCALED,否则可能会导致异常pygame.error: failed to create renderer。
from pygame import display, SCALED
# 最初没有采用 SCALED
display.set_mode([700, 500])
# 改为采用 SCALED 将导致异常
display.set_mode((600, 400), SCALED)pygame.error: failed to create renderer判断显示模式是否可用
display模块的mode_ok函数,可用于判断指定的显示模式是否可用,由于该函数的参数size,flags,depth,display,vsync的含义与set_mode函数类似,因此这里不再解释,你可以参考创建游戏窗口一段来了解他们。
mode_ok(size=(0, 0), flags=0, depth=0, display=0, vsync=0)
- 返回值
如果
mode_ok函数的返回值为0,那么表示由参数指定的显示模式不可用,否则mode_ok函数将返回该显示模式下的最佳颜色深度(整数类型)。
在下面的示例中,由于显示模式可用,因此mode_ok函数返回了该显示模式下的最佳颜色深度。
# 导入并初始化 display 模块
from pygame import display
display.init()
# 判断显示模式是否可用
print(display.mode_ok([1024, 768], depth=8, display=1))24获取显示模式所支持的窗口表面大小
display模块的list_modes函数,可用于获取指定显示模式所支持的窗口的表面大小,由于该函数的参数depth,flags,display的含义与set_mode函数类似,因此这里不再解释,你可以参考创建游戏窗口一段来了解他们。
list_modes(depth=0, flags=pygame.FULLSCREEN, display=0)
- 返回值
list_modes函数的返回值为-1或一个 Python 列表,如果为-1,那么表示任何表面大小均被显示模式支持,如果为空的 Python 列表,那么表示指定的显示模式不支持任何的表面大小(即显示模式不可用),否则 Python 列表中的每一个元组均对应一个窗口表面的大小,元组的形式为(x,y),其中x表示表面的宽度,y表示表面的高度。
在下面的示例中,我们没有为list_modes函数指定任何参数,因此该函数会返回全屏模式所支持的窗口表面大小。
# 导入并初始化 display 模块
from pygame import display
display.init()
# 列出全屏模式所支持的窗口表面大小
print(f'全屏模式支持的表面大小:{display.list_modes()}')全屏模式支持的表面大小:[(2560, 1440), (1920, 1440), (1920, 1200), (1920, 1080), (1680, 1050), (1600, 1200), (1600, 1024), (1600, 900), (1440, 1080), (1440, 900), (1366, 768), (1360, 768), (1280, 1024), (1280, 960), (1280, 800), (1280, 768), (1280, 720), (1176, 664), (1152, 864), (1024, 768), (800, 600), (720, 576), (720, 480), (640, 480)]获取和设置游戏窗口的标题
display模块的get_caption函数可用于获取游戏窗口的标题和图标标题。
get_caption()
- 返回值
get_caption函数的返回值是一个形式类似于(title,icontitle)的 Python 字符串元组,其中title表示窗口标题,icontitle表示窗口的图标标题。
在 Pygame 2 中,get_caption函数所获得的游戏窗口标题和游戏窗口的图标标题总是相同的。
display模块的set_caption函数可用于设置游戏窗口的标题和图标标题。
set_caption(title, icontitle=None)
- title 参数
title参数是一个表示游戏窗口标题的字符串。- icontitle 参数
icontitle参数是一个表示游戏窗口的图标标题的字符串。
在 Pygame 2 中,没有必要给出set_caption函数的icontitle参数,因为这没有任何效果。
get_caption,set_caption 函数对调用位置没有特殊要求
get_caption和set_caption函数,可以在display模块未被初始化或游戏窗口未被创建的情况下调用,这不会影响游戏窗口标题的显示。
什么是窗口的图标标题?
在一些操作系统中,窗口的图标标题是指窗口在最小化时所显示的标题。
下面,我们在调用set_mode函数之前,设置了游戏窗口的标题,这没有任何问题。
# …
# 设置游戏窗口的标题
display.set_caption('一个 Pygame 游戏')
print(display.get_caption())
# …('一个 Pygame 游戏', '一个 Pygame 游戏')设置游戏窗口的图标
display模块的set_icon函数可用于设置游戏窗口的图标,该函数可能会调用init函数,如果display模块尚未进行初始化。当然,调用set_icon函数不是必须的,因为游戏窗口拥有 Pygame 提供的默认图标。
set_icon(surface)
- surface 参数
surface参数是一个绘制了图标的Surface对象,该图标将作为游戏窗口的图标。
set_icon 函数应该在创建游戏窗口之前调用
如果你希望设置游戏窗口的图标,那么应该在创建游戏窗口之前调用set_icon函数,因为,一些操作系统可能不允许修改窗口的图标,在窗口被创建之后。
下面,我们在调用set_mode函数之前,设置了游戏窗口的图标。
# …
# 在运行脚本前,请将命令行跳转至 window.py 所在的目录
from pygame import image
# 设置游戏窗口的图标
display.set_icon(image.load('python.ico'))
# …最小化游戏窗口
display模块的iconify函数可将游戏窗口最小化(图标化),当然,并非所有的操作系统都支持窗口的最小化,iconify的返回值会说明游戏窗口的最小化是否成功。
iconify()
- 返回值
如果
iconify函数返回True,那么说明游戏窗口已经成功最小化。
from pygame import display
# 创建并最小化游戏窗口
display.set_mode([800, 600])
print(f'最小化成功?{display.iconify()}')最小化成功?True判断游戏窗口的表面是否处于活动状态
display模块的get_active函数,可用于判断游戏窗口的表面是否处于活动状态。如果处于活动状态,则表示游戏窗口的表面在屏幕上是活动的,但他对于玩家未必是可见的,比如,游戏窗口被其他窗口遮盖。如果通过iconify函数或玩家手动将游戏窗口最小化,那么表面将处于非活动状态。
get_active()
- 返回值
如果
get_active函数返回True,那么表示游戏窗口的表面处于活动状态。
游戏窗口的表面是否处于活动状态与窗口是否拥有焦点无关
需要指出,get_active函数依然可能返回True,即便当前的游戏窗口没有获得焦点。
from pygame import display
# 创建游戏窗口
display.set_mode((800, 600))
print(f'活动状态?{display.get_active()}')
# 最小化游戏窗口后,窗口处于非活动状态
display.iconify()
print(f'活动状态?{display.get_active()}')活动状态?True
活动状态?False获取游戏窗口的大小
display模块的get_window_size函数,可用于获取游戏窗口的显示区域的大小。
get_window_size()
- 返回值
get_window_size函数的返回值是一个形式类似于(width,height)的 Python 元组,其中width为窗口显示区域的宽度,height为窗口显示区域的高度。
游戏窗口的显示区域大小可能与游戏窗口的表面大小不同
如果你在调用set_mode函数时为flags参数传递了SCALED,那么get_window_size函数所返回的游戏窗口的显示区域大小,可能与游戏窗口的表面大小(set_mode函数的size参数)不同,因为游戏窗口的表面可能会被缩放。
在下面的示例中,我们创建了一个表面很小的窗口,由于屏幕较大并且采用了SCALED,因此 Pygame 将缩放窗口表面。
from pygame import display, SCALED
# 创建一个较小的窗口,SCALED 将缩放窗口的表面
s = display.set_mode([300, 200], SCALED)
print(f'显示区域大小:{display.get_window_size()}')
print(f'表面大小:{s.get_size()}')显示区域大小:(1800, 1200)
表面大小:(300, 200)获取桌面(屏幕)大小
display模块的get_desktop_sizes函数,可用于获取所有桌面(屏幕)的大小。
get_desktop_sizes()
- 返回值
get_desktop_sizes函数的返回值是一个包含元组的 Python 列表,每一个元组对应一个桌面(屏幕)的大小,其形式为(x,y),其中x表示桌面(屏幕)的宽度,y表示桌面(屏幕)的高度。
# 导入并初始化 display 模块
from pygame import display
display.init()
# 获取所有桌面的大小
print(f'所有桌面:{display.get_desktop_sizes()}')所有桌面:[(2560, 1440), (1920, 1080)]切换游戏窗口的全屏模式
display模块的toggle_fullscreen函数,可用于将游戏窗口在窗口模式和全屏模式之间切换。
toggle_fullscreen()
- 返回值
如果
toggle_fullscreen函数返回0,那么表示游戏窗口已成功切换至全屏模式或窗口模式。如果toggle_fullscreen函数返回-1,那么表示切换模式的过程中遇到了问题,游戏窗口可能会被重新创建。
toggle_fullscreen 函数可能无法切换游戏窗口的模式
在某些情况下,toggle_fullscreen函数并不能完成游戏窗口的模式切换,这可能是因为 Pygame 与显示驱动之间存在某些问题。此外,在 Windows 系统中,游戏窗口的表面大小需要在受支持的范围内,或set_mode函数的flags参数需要包含SCALED,否则将窗口切换至全屏模式可能会遇到问题。
关于如何判断游戏窗口的表面大小是否被支持,请参考获取显示模式所支持的窗口表面大小一段。
在下面的示例中,由于大小 700x600 并未被 Windows 系统支持,因此,第一次调用toggle_fullscreen函数返回了-1,游戏窗口被重新创建。
from pygame import display
# 创建游戏窗口并在全屏模式和窗口模式之间切换
display.set_mode((700, 600))
print(f'切换至全屏模式:{display.toggle_fullscreen()}')
print(f'切换至窗口模式:{display.toggle_fullscreen()}')Warning: re-creating window in toggle_fullscreen
print(f'切换至全屏模式:{display.toggle_fullscreen()}')
切换至全屏模式:-1
切换至窗口模式:0获取屏幕的个数
display模块的get_num_displays函数,可用于获取屏幕的个数。
get_num_displays()
- 返回值
get_num_displays函数的返回值是一个整数,表示屏幕的个数。如果display模块没有初始化,则返回值为0。
在 SDL 2 之前的版本中,get_num_displays函数总是返回1。
# …
# 获取屏幕个数
print(f'屏幕个数:{display.get_num_displays()}')屏幕个数:2获取和设置是否启用屏幕保护程序
display模块的get_allow_screensaver和set_allow_screensaver函数,可用于获取和设置是否允许屏幕保护程序在游戏运行时启动。
get_allow_screensaver()
- 返回值
如果
get_allow_screensaver函数返回True,那么表示允许屏幕保护程序在游戏运行时启动,不过该函数一般会返回False,因为 Pygame 默认不允许屏幕保护程序启动。
set_allow_screensaver(value=True)
- value 参数
value是一个布尔值,如果为True,则表示允许屏幕保护程序在游戏运行时启动。
set_allow_screensaver 函数可能不会达到预期效果
设置是否允许屏幕保护程序在游戏运行时启动,需要操作系统的支持,因此set_allow_screensaver函数可能无法达到预期效果。当系统未能成功设置屏幕保护程序时,你无法从set_allow_screensaver函数得知这一点,因为 Pygame 无法获得操作系统的反馈。
# 导入并初始化 display 模块
from pygame import display
display.init()
# 获取和设置是否允许屏幕保护程序在游戏运行时启动
print(f'允许屏幕保护程序启动?{display.get_allow_screensaver()}')
display.set_allow_screensaver()
print(f'允许屏幕保护程序启动?{display.get_allow_screensaver()}')允许屏幕保护程序启动?False
允许屏幕保护程序启动?True内容分类
源码
讲解视频
如何在 Pygame 中创建窗口,以及设置标题和切换全屏·YouTube如何在 Pygame 中创建窗口,以及设置标题和切换全屏·Bilibili