如何处理游戏中的控制器事件
关注 1421
虽然本节所提到的内容与事件有关,但捕获事件的方法,请参考如何捕获处理游戏事件?以及创建和引发自定义事件等问题一节。除了通过事件,你也可以使用joystick
模块来实现与控制器相关的功能,具体请查看如何获取控制器的信息和状态(按键状态,方向键状态,轴状态等)一节。
初始化 joystick 模块
要在 Pygame 中处理与控制器相关的事件,你需要首先对joystick
模块进行初始化,否则相关代码可能不会执行。此外,类似于按键按下和释放,轴和轨迹球移动等事件,还需要创建和保持与控制器相关的JoystickType
对象。
控制器
关于初始化joystick
模块,你可以查看初始化 joystick 模块一段。
连接和中断连接事件
如何在 Pygame 中处理控制器的连接和中断事件视频演示 YouTube如何在 Pygame 中处理控制器的连接和中断事件视频演示 Bilibili
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 中处理控制器的按键事件视频演示 Bilibili
pygame
模块拥有变量JOYBUTTONDOWN
和JOYBUTTONUP
,他们分别表示控制器按键被按下和释放的事件,事件所对应Event
对象拥有以下变量。
- instance_id 变量
instance_id
变量是表示控制器实例 ID 的整数,他将指示引发事件的具体控制器。- button 变量
button
变量是一个整数,用于表示控制器上被按下或释放的按键。
控制器按键被按下的事件不会被连续引发
一般情况下,控制器按键被按下的事件不会被连续引发,即便将某个控制器按键保持按下状态,按键按下的事件也仅会引发一次。不过,某些型号的控制器可能会拥有自动连发功能,如果开启此功能并保持按键的按下状态,那么按键的按下事件和释放事件会被连续引发。
方向键(十字键)事件
如何在 Pygame 中处理控制器的方向键事件视频演示 YouTube如何在 Pygame 中处理控制器的方向键事件视频演示 Bilibili
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 中处理控制器的摇杆移动事件视频演示 Bilibili
游戏控制器一般拥有一些轴装置,最为常见的是摇杆和扳机键。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 中处理控制器的连接和中断事件·Bilibili
如何在 Pygame 中处理控制器的按键事件·YouTube如何在 Pygame 中处理控制器的按键事件·Bilibili
如何在 Pygame 中处理控制器的方向键事件·YouTube如何在 Pygame 中处理控制器的方向键事件·Bilibili
如何在 Pygame 中处理控制器的摇杆移动事件·YouTube如何在 Pygame 中处理控制器的摇杆移动事件·Bilibili