URLhttps://learnscript.net/zh-hant/pygame/display/
    複製連結移至說明  範例

    如何建立遊戲視窗?以及取得和設定視窗與熒幕資訊等問題

    閱讀 25:17·字數 7589·發佈 
    Youtube 頻道
    訂閱 375

    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-hant/display·codebeatme/pygame·GitHub

    講解影片

    Pygame 建立視窗,以及設定標題和切換全熒幕,display 模組簡介·YouTube