如何创建游戏窗口?以及获取和设置窗口与屏幕信息等问题
关注 1260
如何在 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