如何处理游戏中的控制器事件
关注 1800
虽然本节所提到的内容与事件有关,但捕获事件的方法,请参考如何捕获处理游戏事件?以及创建和引发自定义事件等问题一节。除了通过事件,你也可以使用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