如何處理遊戲中的控製器事件
訂閱 375
雖然本節所提到的內容與事件有關,但擷取事件的方法,請參考如何擷取處理遊戲事件?以及建立和引發自訂事件等問題一節。除了通過事件,你也可以使用joystick
模組來實作與控製器相關的功能,具體請檢視如何取得控製器的資訊和狀態(按鍵狀態,方向鍵狀態,軸狀態等)一節。
初始化 joystick 模組
要在 Pygame 中處理與控製器相關的事件,你需要首先對joystick
模組進行初始化,否則相關程式碼可能不會執行。此外,類似於按鍵按下和釋放,軸和軌跡球移動等事件,還需要建立和保持與控製器相關的JoystickType
物件。
控製器
關於初始化joystick
模組,你可以檢視初始化 joystick 模組一段。
連線和中斷連線事件
Pygame 處理控製器(手把)的連線和中斷連線事件影片示範 YouTube
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
物件從串列中移除。
# 匯入相關內容,建立遊戲視窗,初始化模組
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 處理控製器(手把)按鍵的按下和釋放事件影片示範 YouTube
pygame
模組擁有變數JOYBUTTONDOWN
和JOYBUTTONUP
,他們分別表示控製器按鍵被按下和釋放的事件,事件所對應Event
物件擁有以下變數。
- instance_id 變數
instance_id
變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。- button 變數
button
變數是一個整數,用於表示控製器上被按下或釋放的按鍵。
控製器按鍵被按下的事件不會被持續引發
一般情況下,控製器按鍵被按下的事件不會被持續引發,即便將某個控製器按鍵保持按下狀態,按鍵按下的事件也僅會引發一次。不過,某些型號的控製器可能會擁有自動連擊功能,如果開啟此功能並保持按鍵的按下狀態,那麽按鍵的按下事件和釋放事件會被持續引發。
方向鍵(十字鍵)事件
Pygame 處理控製器(手把)的方向鍵(十字鍵)事件影片示範 YouTube
pygame
模組擁有變數JOYHATMOTION
,他表示控製器方向鍵(十字鍵)被操作的事件(按下和釋放均會引發),該事件所對應Event
物件擁有以下變數。
- instance_id 變數
instance_id
變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。- hat 變數
hat
變數是表示方向鍵 ID 的整數,可用於指示引發事件的具體方向鍵,大部分情況下該變數為0
(擁有多個方向鍵的控製器非常罕見)。- value 變數
value
變數是一個形式為(x,y)
的整數元組。如果x
為1
,則表示右方向鍵被按下,為-1
,則表示左方向鍵被按下。如果y
為1
,則表示上方向鍵被按下,為-1
,則表示下方向鍵被按下。
控製器的方向鍵事件不會被持續引發
一般情況下,控製器的方向鍵事件不會被持續引發,即便將方向鍵保持按下狀態,因按下而引發的事件也僅會出現一次。
某些控製器的方向鍵不會引發方向鍵事件
並非所有控製器的方向鍵均會引發方向鍵事件,某些控製器的方向鍵會引發按鍵按下和按鍵釋放事件(JOYBUTTONDOWN
和JOYBUTTONUP
)。
在下面的範例中,我們根據事件物件的value
變數,取得方向鍵的按下狀態,以決定遊戲角色向哪個方向移動。
# 匯入並初始化相關模組,建立遊戲視窗
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 處理控製器(手把)的軸(搖桿、扳機鍵)移動事件影片示範 YouTube
遊戲控製器一般擁有一些軸裝置,最為常見的是搖桿和扳機鍵。pygame
模組的變數JOYAXISMOTION
,可用於表示軸的移動事件,該事件所對應Event
物件擁有以下變數。
- instance_id 變數
instance_id
變數是表示控製器執行個體 ID 的整數,他將指示引發事件的具體控製器。- axis 變數
axis
變數是表示軸 ID 的整數,可用於指示引發事件的具體軸。大部分的遊戲控製器均擁有左右兩個搖桿和左右兩個扳機鍵,當
axis
為0
或2
時,事件通常由左搖桿或右搖桿在水平方向上的移動引發,當axis
為1
或3
時,事件通常由左搖桿或右搖桿在垂直方向上的移動引發,當axis
為4
或5
時,事件通常由左扳機鍵或右扳機鍵引發。需要指出的是,不同型號的控製器,其類似的軸裝置的 ID 可能會不同,
axis
為3
並不表示事件一定由右搖桿在垂直方向上的移動引發。- value 變數
value
變數是一個浮點數,表示了軸(搖桿,扳機鍵)與中心之間的距離,其取值範圍從-1
至1
,等於0
表示軸(搖桿,扳機鍵)位於中心位置,等於(或接近於)-1
或1
表示軸(搖桿,扳機鍵)已到達邊緣最大位置。當axis
為0
或2
時,value
通常表示搖桿與中心之間的水平距離(-1
為左邊最大位置,1
為右邊最大位置)。當axis
為1
或3
時,value
通常表示搖桿與中心之間的垂直距離(-1
為上邊最大位置,1
為下邊最大位置)。對於搖桿而言,
value
變數的預設值理論上為0
,對於扳機鍵而言,value
變數的預設值理論上為-1
。
# 匯入並初始化相關模組,建立遊戲視窗
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
表示垂直移動距離。
原始碼
講解影片
Pygame 處理控製器(手把)的連線和中斷連線事件·YouTube
Pygame 處理控製器(手把)按鍵的按下和釋放事件·YouTube
Pygame 處理控製器(手把)的方向鍵(十字鍵)事件·YouTube
Pygame 處理控製器(手把)的軸(搖桿、扳機鍵)移動事件·YouTube