URLhttps://learnscript.net/zh/pygame/display/
    复制链接转到说明  示例

    如何创建游戏窗口?以及获取和设置窗口与屏幕信息等问题

    我被代码海扁署名-非商业-禁演绎
    阅读 25:18·字数 7590·发布 

    Pygame 中的 display 模块

    Pygame 包的display模块,提供了与游戏窗口,屏幕相关的功能,当你导入pygame模块时,display模块会被pygame模块导入。

    初始化 display 模块

    pygame模块一样,display模块拥有用于初始化的函数init,该函数会在pygame模块的init函数中被调用,这意味着一旦使用pygame模块进行初始化,调用display模块的init函数将是没有必要的。

    init()

    可以重复调用 init 函数

    你可以反复调用init函数,这没有任何问题,即便在调用quit函数之后。

    window.py
    # 导入模块 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模块。

    window.py
    # …
    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参数采用了OPENGLSCALED的话。

    当然,是否能够采用垂直同步,还取决于计算机硬件以及显示驱动的配置。

    返回值

    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 会自行调整窗口表面的大小,这可能会导致玩家看到不应该出现的内容。

    在下面的示例中,我们设置游戏窗口的表面大小为 600x400,并为全屏显示模式,最终,窗口的表面大小被设置为了 640x480。

    由于没有编写游戏循环,以及检测游戏事件的代码,因此被创建的游戏窗口仅支持少量的用户操作。

    window.py
    # …
    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参数之后,全屏显示的游戏窗口的表面大小并不会改变。

    scaled.py
    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

    wrong.py
    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函数,可用于判断指定的显示模式是否可用,由于该函数的参数sizeflagsdepthdisplayvsync的含义与set_mode函数类似,因此这里不再解释,你可以参考创建游戏窗口一段来了解他们。

    mode_ok(size=(0, 0), flags=0, depth=0, display=0, vsync=0)

    返回值

    如果mode_ok函数的返回值为0,那么表示由参数指定的显示模式不可用,否则mode_ok函数将返回该显示模式下的最佳颜色深度(整数类型)。

    在下面的示例中,由于显示模式可用,因此mode_ok函数返回了该显示模式下的最佳颜色深度。

    mode_ok.py
    # 导入并初始化 display 模块
    from pygame import display
    display.init()
    
    # 判断显示模式是否可用 print(display.mode_ok([1024, 768], depth=8, display=1))
    24

    获取显示模式所支持的窗口表面大小

    display模块的list_modes函数,可用于获取指定显示模式所支持的窗口的表面大小,由于该函数的参数depthflagsdisplay的含义与set_mode函数类似,因此这里不再解释,你可以参考创建游戏窗口一段来了解他们。

    list_modes(depth=0, flags=pygame.FULLSCREEN, display=0)

    返回值

    list_modes函数的返回值为-1或一个 Python 列表,如果为-1,那么表示任何表面大小均被显示模式支持,如果为空的 Python 列表,那么表示指定的显示模式不支持任何的表面大小(即显示模式不可用),否则 Python 列表中的每一个元组均对应一个窗口表面的大小,元组的形式为(x,y),其中x表示表面的宽度,y表示表面的高度。

    在下面的示例中,我们没有为list_modes函数指定任何参数,因此该函数会返回全屏模式所支持的窗口表面大小。

    list_modes.py
    # 导入并初始化 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_captionset_caption函数,可以在display模块未被初始化或游戏窗口未被创建的情况下调用,这不会影响游戏窗口标题的显示。

    什么是窗口的图标标题?

    在一些操作系统中,窗口的图标标题是指窗口在最小化时所显示的标题。

    下面,我们在调用set_mode函数之前,设置了游戏窗口的标题,这没有任何问题。

    window.py
    # …
    # 设置游戏窗口的标题
    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
    # …
    # 在运行脚本前,请将命令行跳转至 window.py 所在的目录
    from pygame import image
    # 设置游戏窗口的图标
    display.set_icon(image.load('python.ico'))
    # …

    最小化游戏窗口

    display模块的iconify函数可将游戏窗口最小化(图标化),当然,并非所有的操作系统都支持窗口的最小化,iconify的返回值会说明游戏窗口的最小化是否成功。

    iconify()

    返回值

    如果iconify函数返回True,那么说明游戏窗口已经成功最小化。

    iconify.py
    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,即便当前的游戏窗口没有获得焦点。

    active.py
    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 将缩放窗口表面。

    window_size.py
    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表示桌面(屏幕)的高度。

    desktop.py
    # 导入并初始化 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,游戏窗口被重新创建。

    fullscreen.py
    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

    desktop.py
    # …
    # 获取屏幕个数
    print(f'屏幕个数:{display.get_num_displays()}')
    屏幕个数:2

    获取和设置是否启用屏幕保护程序

    display模块的get_allow_screensaverset_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 无法获得操作系统的反馈。

    screensaver.py
    # 导入并初始化 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

    内容分类

    源码

    src/zh/display·codebeatme/pygame·GitHub

    讲解视频

    如何在 Pygame 中创建窗口,以及设置标题和切换全屏·YouTube如何在 Pygame 中创建窗口,以及设置标题和切换全屏·Bilibili