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

    如何處理遊戲中的控製器事件

    閱讀 13:02·字數 3914·更新 
    Youtube 頻道
    訂閱 375

    雖然本節所提到的內容與事件有關,但擷取事件的方法,請參考如何擷取處理遊戲事件?以及建立和引發自訂事件等問題一節。除了通過事件,你也可以使用joystick模組來實作與控製器相關的功能,具體請檢視如何取得控製器的資訊和狀態(按鍵狀態,方向鍵狀態,軸狀態等)一節。

    初始化 joystick 模組

    要在 Pygame 中處理與控製器相關的事件,你需要首先對joystick模組進行初始化,否則相關程式碼可能不會執行。此外,類似於按鍵按下和釋放,軸和軌跡球移動等事件,還需要建立和保持與控製器相關的JoystickType物件。

    控製器

    關於初始化joystick模組,你可以檢視初始化 joystick 模組一段。

    連線和中斷連線事件

    pygame模組擁有變數JOYDEVICEADDED,表示遊戲控製器的連線事件,該事件可能在遊戲中接入新的控製器時引發,也可能在遊戲啟動時引發(如果已經在啟動前連線了控製器),其對應的Event物件擁有以下變數。

    device_index 變數

    device_index變數是一個整數,其含義為控製器的裝置索引,通常用於建立JoystickType物件。裝置索引可被理解為控製器的順序,同一個控製器的裝置索引可能會發生改變,當連線了新的控製器或原有控製器中斷連線時。因此,device_index變數僅在控製器連線事件中保證其準確性。

    guid 變數

    guid變數是一個 GUID 字串,用於識別某種控製器型號。由於該字串只是針對型號,因此,他不能用於識別每一個遊戲控製器,當你連結同一品牌的同種型號的兩個控製器時,他們將擁有相同的 GUID。

    pygame模組擁有變數JOYDEVICEREMOVED,表示遊戲控製器的中斷連線事件,此事件對應的Event物件擁有以下變數。

    instance_id 變數

    instance_id變數是一個表示執行個體 ID 的整數,執行個體 ID 可用於唯一的識別控製器。

    遊戲控製器的執行個體 ID 與建立 JoystickType 物件無關

    對於每一個新連線的控製器,Pygame 都會為其分配一個執行個體 ID,該執行個體 ID 與是否建立JoystickType物件或建立多少個JoystickType物件無關。這意味著,對於同一個控製器,建立與其相關的多個JoystickType物件,並不會改變該控製器的執行個體 ID。

    重新連線遊戲控製器,其執行個體 ID 可能會發生變化

    對於同一個控製器,如果在中斷連線後重新連線,那麽其對應的執行個體 ID 可能會發生變化。

    在下面的範例中,我們通過一個串列來保持通過裝置索引建立的JoystickType物件,並根據執行個體 ID 將無用的JoystickType物件從串列中移除。

    connection.py
    # 匯入相關內容,建立遊戲視窗,初始化模組
    from pygame import display, event, joystick, QUIT
    display.set_mode((800, 600))
    joystick.init()
    
    # 匯入與控製器事件相關的變數 from pygame import JOYDEVICEADDED, JOYDEVICEREMOVED # 儲存 JoystickType 物件的串列 jss = []
    running = True while running: for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYDEVICEADDED: # 根據裝置索引建立 JoystickType 物件,並新增至 jss js = joystick.Joystick(e.device_index) jss.append(js)
    print('新增控製器', e.device_index) elif e.type == JOYDEVICEREMOVED: # 根據執行個體 ID,將 JoystickType 物件從 jss 移除 for js in jss: if js.get_instance_id() == e.instance_id: jss.remove(js) print('移除控製器', e.instance_id) break

    按鍵的按下和釋放事件

    pygame模組擁有變數JOYBUTTONDOWNJOYBUTTONUP,他們分別表示控製器按鍵被按下和釋放的事件,事件所對應Event物件擁有以下變數。

    instance_id 變數

    instance_id變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。

    button 變數

    button變數是一個整數,用於表示控製器上被按下或釋放的按鍵。

    控製器按鍵被按下的事件不會被持續引發

    一般情況下,控製器按鍵被按下的事件不會被持續引發,即便將某個控製器按鍵保持按下狀態,按鍵按下的事件也僅會引發一次。不過,某些型號的控製器可能會擁有自動連擊功能,如果開啟此功能並保持按鍵的按下狀態,那麽按鍵的按下事件和釋放事件會被持續引發。

    在下面的範例中,我們通過字典來保持JoystickType物件,字典的鍵為控製器的執行個體 ID。在控製器的按鍵按下事件中,可根據事件傳遞的執行個體 ID 在字典中找到玩家索引。

    button.py
    # 匯入並初始化相關模組,建立遊戲視窗
    from pygame import display, event, joystick, JOYDEVICEADDED
    display.set_mode((800, 600))
    joystick.init()
    
    # 匯入與控製器事件相關的變數 from pygame import JOYBUTTONDOWN, JOYBUTTONUP # 儲存控製器資訊的字典 cs = {} # 玩家索引 playerIndex = 0
    running = True while running: for e in event.get(): if e.type == JOYDEVICEADDED: js = joystick.Joystick(e.device_index)
    # 將 JoystickType 物件與玩家索引新增至字典,執行個體 ID 為鍵 playerIndex += 1 cs[js.get_instance_id()] = [js, playerIndex] elif e.type == JOYBUTTONDOWN: # 根據執行個體 ID 取得字典中的控製器資訊,顯示玩家索引 c = cs[e.instance_id]
    print(f'玩家 {c[1]} 按下了 {e.button}') elif e.type == JOYBUTTONUP: # 如果釋放了開始鍵,則遊戲結束 if e.button == 7: running = False

    方向鍵(十字鍵)事件

    pygame模組擁有變數JOYHATMOTION,他表示控製器方向鍵(十字鍵)被操作的事件(按下和釋放均會引發),該事件所對應Event物件擁有以下變數。

    instance_id 變數

    instance_id變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。

    hat 變數

    hat變數是表示方向鍵 ID 的整數,可用於指示引發事件的具體方向鍵,大部分情況下該變數為0(擁有多個方向鍵的控製器非常罕見)。

    value 變數

    value變數是一個形式為(x,y)的整數元組。如果x1,則表示右方向鍵被按下,為-1,則表示左方向鍵被按下。如果y1,則表示上方向鍵被按下,為-1,則表示下方向鍵被按下。

    控製器的方向鍵事件不會被持續引發

    一般情況下,控製器的方向鍵事件不會被持續引發,即便將方向鍵保持按下狀態,因按下而引發的事件也僅會出現一次。

    某些控製器的方向鍵不會引發方向鍵事件

    並非所有控製器的方向鍵均會引發方向鍵事件,某些控製器的方向鍵會引發按鍵按下和按鍵釋放事件(JOYBUTTONDOWNJOYBUTTONUP)。

    在下面的範例中,我們根據事件物件的value變數,取得方向鍵的按下狀態,以決定遊戲角色向哪個方向移動。

    hat.py
    # 匯入並初始化相關模組,建立遊戲視窗
    from pygame import display, event, joystick, JOYDEVICEADDED, QUIT
    display.set_mode((800, 600))
    joystick.init()
    
    # 匯入與控製器事件相關的變數 from pygame import JOYHATMOTION # 儲存 JoystickType 物件的串列 jss = [] # 表示水平和垂直的移動方向 h = 0 v = 0
    running = True while running: for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYDEVICEADDED: jss.append(joystick.Joystick(e.device_index)) elif e.type == JOYHATMOTION: # 取得十字鍵的按下狀態 (x, y) = e.value
    # 根據十字鍵的按下狀態,設定遊戲角色的移動方向 if x == 1: h = 1 print('開始向右移動') elif x == -1: h = -1 print('開始向左移動') elif h != 0: h = 0 print('取消水平移動')
    if y == 1: v = 1 print('開始向上移動') elif y == -1: v = -1 print('開始向下移動') elif v != 0: v = 0 print('取消垂直移動')

    軸(搖桿,扳機鍵)移動事件

    遊戲控製器一般擁有一些軸裝置,最為常見的是搖桿和扳機鍵。pygame模組的變數JOYAXISMOTION,可用於表示軸的移動事件,該事件所對應Event物件擁有以下變數。

    instance_id 變數

    instance_id變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。

    axis 變數

    axis變數是表示軸 ID 的整數,可用於指示引發事件的具體軸。

    大部分的遊戲控製器均擁有左右兩個搖桿和左右兩個扳機鍵,當axis02時,事件通常由左搖桿或右搖桿在水平方向上的移動引發,當axis13時,事件通常由左搖桿或右搖桿在垂直方向上的移動引發,當axis45時,事件通常由左扳機鍵或右扳機鍵引發。

    需要指出的是,不同型號的控製器,其類似的軸裝置的 ID 可能會不同,axis3並不表示事件一定由右搖桿在垂直方向上的移動引發。

    value 變數

    value變數是一個浮點數,表示了軸(搖桿,扳機鍵)與中心之間的距離,其取值範圍從-11,等於0表示軸(搖桿,扳機鍵)位於中心位置,等於(或接近於)-11表示軸(搖桿,扳機鍵)已到達邊緣最大位置。當axis02時,value通常表示搖桿與中心之間的水平距離(-1為左邊最大位置,1為右邊最大位置)。當axis13時,value通常表示搖桿與中心之間的垂直距離(-1為上邊最大位置,1為下邊最大位置)。

    對於搖桿而言,value變數的預設值理論上為0,對於扳機鍵而言,value變數的預設值理論上為-1

    axis.py
    # 匯入並初始化相關模組,建立遊戲視窗
    from pygame import display, event, joystick, JOYDEVICEADDED, QUIT
    display.set_mode((800, 600))
    joystick.init()
    
    # 匯入與控製器事件相關的變數 from pygame import JOYAXISMOTION # 儲存 JoystickType 物件的串列 jss = []
    running = True while running: for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYDEVICEADDED: jss.append(joystick.Joystick(e.device_index)) elif e.type == JOYAXISMOTION: # 判斷觸發事件的軸裝置是否為右扳機鍵 if e.axis == 5: # 判斷右扳機鍵的移動程度,是否足以發動攻擊 if e.value > -0.3: print('攻擊') else: print('停止攻擊')

    軌跡球捲動事件

    針對射擊遊戲,一些遊戲控製器可能會設計軌跡球,其操作效果類似於滑鼠。pygame模組的變數JOYBALLMOTION,可用於表示軌跡球的捲動事件,該事件所對應Event物件擁有以下變數。

    instance_id 變數

    instance_id變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。

    ball 變數

    ball變數是表示軌跡球 ID 的整數,可用於指示引發事件的具體軌跡球。

    rel 變數

    rel變數是一個形式類似於(x,y)的 Python 整數元組,表示與上一次事件相比,軌跡球的移動距離,其中x表示水平移動距離,y表示垂直移動距離。

    原始碼

    src/zh-hant/event/controller·codebeatme/pygame·GitHub

    講解影片

    Pygame 處理控製器(手把)的連線和中斷連線事件·YouTube
    Pygame 處理控製器(手把)按鍵的按下和釋放事件·YouTube
    Pygame 處理控製器(手把)的方向鍵(十字鍵)事件·YouTube
    Pygame 處理控製器(手把)的軸(搖桿、扳機鍵)移動事件·YouTube