URLhttps://learnscript.net/zh/pygame/joystick/
    复制链接转到说明  示例

    如何获取控制器的信息和状态(按键状态,方向键状态,轴状态等)

    我被代码海扁署名-非商业-禁演绎
    阅读 19:25·字数 5826·发布 

    本节内容不涉及控制器事件的讲解,要了解如何处理控制器事件,请查看如何处理游戏中的控制器事件一节。

    Pygame 中的 joystick 模块

    Pygame 包的joystick模块,包含了与游戏控制器相关的函数,以及表示控制器的JoystickType类。

    初始化 joystick 模块

    pygame模块一样,joystick模块拥有用于初始化的函数init,该函数会在pygame模块的init函数中被调用,这意味着一旦使用pygame模块进行初始化,调用joystick模块的init函数将是没有必要的。

    joystick模块尚未初始化之前,调用与游戏控制器相关的函数可能不会产生实际效果,与控制器相关的事件也不会被引发。

    init()

    请确保 joystick 模块在 display 模块之后初始化

    如果单独初始化 Pygame 中的模块,那么请确保在display模块初始化之后,再调用joystick模块的init函数。

    可以重复调用 init 函数

    你可以反复调用init函数,这没有任何问题,即便在调用quit函数之后。

    joystick.py
    # 导入模块 joystick
    from pygame import joystick
    
    # 初始化 joystick.init()

    判断 joystick 模块是否已经初始化

    pygame模块一样,joystick模块拥有判断joystick模块是否已经初始化的函数get_init

    get_init()

    返回值

    如果get_init函数返回True,那么表示joystick模块已经进行了初始化。

    在调用 quit 函数之后,get_init 函数将返回 False

    在调用quit函数之后,get_init函数将返回False,这表示再次调用init函数将产生实际效果,他会重新初始化joystick模块。

    joystick.py
    # …
    print(f'joystick 已经初始化?{joystick.get_init()}')
    joystick 已经初始化?True

    取消初始化 joystick 模块

    pygame模块一样,joystick模块拥有用于取消初始化的函数quit,该函数会在pygame模块的quit函数中被调用,这意味着一旦使用pygame模块取消了初始化,调用joystick模块的quit函数将是没有必要的。

    quit()

    可以重复调用 quit 函数

    init函数一样,你可以反复调用quit函数,这没有任何的问题。

    获取控制器的个数

    joystick模块的get_count函数,可用于获取已经连接的游戏控制器的个数。

    get_count()

    返回值

    get_count函数返回表示控制器个数的整数。

    joystick.py
    # …
    print(f'控制器个数:{joystick.get_count()}')

    Pygame 中的 JoystickType 对象

    joystick模块拥有一个名称为Joystick的函数,通过该函数可以创建表示具体游戏控制器的JoystickType对象。

    Joystick(id)

    id 参数

    id参数是一个整数,该整数需要大于等于0,并小于get_count函数的返回值。

    在控制器的连接事件中,你可以将Event对象的device_index变量作为id参数的值,来创建表示新连接控制器的JoystickType对象。但在连接事件之外,device_index变量所对应的整数可能会失去准确性,当有其他控制器连接或中断连接时。

    请尽量在控制器连接事件中创建 JoystickType 对象

    虽然,Pygame 并不限制创建JoystickType对象的时间点,但如果是在游戏开始时,而非控制器连接事件中,创建控制器对象,那么这些对象的某些方法可能会失效,比如,你可能无法通过get_button方法获取按键的按下状态(虽然,按下状态依然可通过控制器的按键按下事件获得)。

    当被创建时,JoystickType对象会自动完成初始化,当被销毁时,JoystickType对象会自动取消初始化。因此,在创建控制器对应的JoystickType对象之后,你应该保持该对象(至少保持一个该控制器对应的JoystickType对象),否则,相应的控制器事件不会被引发。

    JoystickType对象的initquit方法,可分别用于初始化和取消初始化游戏控制器,但由于初始化和取消初始化可以自动完成,因此并没有调用以上两个方法的必要。

    init()
    quit()

    Pygame 官方称将在 Pygame 2.1 中移除JoystickTypeinit方法,但在之后的版本中该方法似乎依然存在。

    JoystickType对象的get_init,可用于判断游戏控制器是否已经进行了初始化。

    get_init()

    返回值

    如果get_init方法返回True,那么表示控制器已经被初始化。

    控制器事件

    关于游戏控制的连接事件,请查看连接和中断连接事件一段。

    在下面的示例中,我们在游戏开始时,获取所有已经连接的游戏控制器,如果希望获取在游戏过程中连接的控制器,那么需要处理控制器连接事件。

    事实上,你应该尽可能的在控制器连接事件中获取控制器,而不是像示例中所展示的,以确保JoystickType对象的相关方法能够发挥作用。

    create.py
    # 导入相关内容,并创建游戏窗口
    from pygame import joystick, display, event, QUIT, JOYBUTTONDOWN
    display.set_mode([800, 600])
    
    # 初始化 joystick 模块 joystick.init()
    js = [] # 获取所有已经连接的控制器 for i in range(joystick.get_count()): j = joystick.Joystick(i) js.append(j)
    print(f'控制器 {i} 已经初始化?{j.get_init()}')
    # 处理退出事件,控制器按键的按下事件 running = True while running: for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYBUTTONDOWN: print(e)

    获取控制器按键的信息和状态

    JoystickType对象的get_numbuttons方法,可获取游戏控制器上的按键的个数。

    get_numbuttons()

    返回值

    get_numbuttons方法返回表示控制器按键个数的整数。

    JoystickType对象的get_button方法,可获取游戏控制器按键的按下状态。

    get_button(button)

    button 参数

    button参数是一个整数,对应了控制器上的某个按键,其值大于等于0,并小于get_numbuttons方法的返回值。

    需要指出的是,不同型号的控制器,其类似按键对应的整数可能不同。

    返回值

    如果get_button方法返回True,那么表示按键处于按下状态。

    下面,我们在控制器连接事件中,创建了与控制器相关的JoystickType对象,并判断每一个控制器的第一个按键是否被按下,如果被按下,则显示对应角色的攻击信息。

    status.py
    # 导入并初始化相关模块,创建游戏窗口
    from pygame import joystick, display, event, JOYDEVICEADDED, QUIT
    display.set_mode((800, 600))
    joystick.init()
    
    # 保存控制器对象的列表 js = []
    running = True while running: # 处理控制器连接事件,退出事件 for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYDEVICEADDED: j = joystick.Joystick(e.device_index) js.append(j)
    # 角色索引 pi = 0
    # 遍历所有的控制器 for j in js: pi += 1
    # 如果按下第一个按键,则视为攻击命令 if j.get_numbuttons() > 0 and j.get_button(0): print(f'角色 {pi} 攻击')

    获取控制器方向键(十字键)的信息和状态

    JoystickType对象的get_numhats方法,可获取游戏控制器上的方向键的个数,大部分情况下,控制器只拥有一个方向键。

    get_numhats()

    返回值

    get_numhats方法返回表示控制器方向键个数的整数。

    JoystickType对象的get_hat方法,可获取游戏控制器方向键的按下状态。

    get_hat(hat_number)

    hat_number 参数

    hat_number参数是一个整数,对应了控制器上的某个方向键,其值大于等于0,并小于get_numhats方法的返回值。

    需要指出的是,不同型号的控制器,其类似方向键对应的整数可能不同。

    返回值

    get_hat方法返回形式为(x,y)的整数元组(部分文档将其解释为浮点数元组是不准确的)。其中,x1表示右方向键处于按下状态,为-1表示左方向键处于按下状态,y1表示上方向键处于按下状态,为-1表示下方向键处于按下状态。

    某些控制器的方向键被定义为按键

    对于一些控制器,其拥有的方向键被定义为了按键,因此,在 Pygame 中不会引发方向键事件,也不能通过get_hat方法获取状态。

    下面,我们为之前的示例增加代码,根据方向键的按下状态,显示不同的方向信息。

    status.py
    # …
    # 根据第一个方向键来移动角色
    if j.get_numhats() > 0:
    	(x, y) = j.get_hat(0)
    	
    	if x == -1:
    		print(f'角色 {pi} 向左')
    	elif x == 1:
    		print(f'角色 {pi} 向右')
    
    if y == -1: print(f'角色 {pi} 向下') elif y == 1: print(f'角色 {pi} 向上')

    获取控制器轴(摇杆,扳机键)的信息和状态

    JoystickType对象的get_numaxes方法,可获取游戏控制器上的轴装置的个数,比如,摇杆,扳机键。

    get_numaxes()

    返回值

    get_numaxes方法返回表示控制器轴装置个数的整数。

    JoystickType对象的get_axis方法,可获取游戏控制器轴装置(摇杆,扳机键)与中心之间的距离。

    get_axis(axis_number)

    axis_number 参数

    axis_number参数是一个整数,对应了控制器上的某个轴装置,其值大于等于0,并小于get_numaxes方法的返回值。对于摇杆而言,0通常指左摇杆的水平轴,2通常指右摇杆的水平轴,1通常指左摇杆的垂直轴,3通常指右摇杆的垂直轴,4通常指左扳机键,5通常指右扳机键。

    需要指出的是,不同型号的控制器,其类似轴装置对应的整数可能不同。

    返回值

    get_axis方法的返回值是一个浮点数,表示了轴装置(摇杆,扳机键)与中心之间的距离,一般情况下,其取值范围从-11,等于0表示轴装置位于中心位置,等于(或接近于)-11表示轴装置已到达边缘最大位置。

    对于摇杆而言,-1通常表示左边最大位置或上边最大位置,1通常表示右边最大位置或下边最大位置。对于扳机键而言,如果没有被按下,那么get_axis方法理论上返回-1

    下面,我们为之前的示例增加代码,如果玩家按下右扳机键到一定程度,那么显示角色跳跃的信息。

    status.py
    # …
    # 根据右扳机键判断是否跳跃,假设 5 对应了右扳机键
    if j.get_numaxes() > 5 and j.get_axis(5) > 0.2:
    	print(f'角色 {pi} 跳跃')

    获取控制器轨迹球的信息和状态

    JoystickType对象的get_numballs方法,可获取游戏控制器上的轨迹球的个数。

    get_numballs()

    返回值

    get_numballs方法返回表示控制器轨迹球个数的整数。

    JoystickType对象的get_ball方法,可获取游戏控制器轨迹球的移动距离。

    get_ball(ball_number)

    ball_number 参数

    ball_number参数是一个整数,对应了控制器上的某个轨迹球,其值大于等于0,并小于get_numballs方法的返回值。

    需要指出的是,不同型号的控制器,其类似轨迹球对应的整数可能不同。

    返回值

    get_ball方法的返回值是一个形式类似于(x,y)的整数元组(部分文档将其解释为浮点数元组是不准确的),表示与上一次事件相比,轨迹球的移动距离,其中x表示水平移动距离,y表示垂直移动距离。

    启动和停止控制器的震动回馈

    JoystickType对象的rumble方法,可用于启动游戏控制器的震动回馈。

    rumble(low_frequency, high_frequency, duration)

    low_frequency 参数

    low_frequency参数是表示控制器低频震动强度的浮点数,取值范围从010表示没有震动,1表示最大强度。

    high_frequency 参数

    high_frequency参数是表示控制器高频震动强度的浮点数,取值范围从010表示没有震动,1表示最大强度。

    duration 参数

    duration参数是表示震动回馈持续时间的整数,以毫秒为单位。如果设置为0,则表示震动回馈一直持续,直到调用stop_rumble方法,或再次调用rumble方法启动新的震动回馈。

    返回值

    如果rumble方法返回True,则表示已成功启动震动回馈,否则表示启动失败。

    JoystickType对象的stop_rumble方法,可用于停止游戏控制器的震动回馈。

    stop_rumble()

    在下面的示例中,我们尝试使新连接的游戏控制器产生5秒的震动回馈(但1秒后就被停止了)。

    rumble.py
    # 导入并初始化相关模块,创建游戏窗口
    from pygame import joystick, display, event, JOYDEVICEADDED, QUIT
    import time
    display.set_mode((800, 600))
    joystick.init()
    
    # 保存控制器对象的列表 js = []
    running = True while running: # 处理控制器连接事件,退出事件 for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYDEVICEADDED: j = joystick.Joystick(e.device_index) js.append(j)
    # 尝试在连接控制器后,启动其震动回馈 print('成功启动震动回馈?', j, j.rumble(0.1, 0.9, 5000)) time.sleep(1) j.stop_rumble() print('停止震动回馈', j)

    获取控制器的实例 ID

    JoystickType对象的get_instance_id方法,可获取游戏控制器的实例 ID(用于唯一标识控制器),他与控制器事件的Event对象的instance_id变量一致。

    get_instance_id()

    返回值

    get_instance_id方法返回表示控制器实例 ID 的整数。

    info.py
    # 导入并初始化相关模块,创建游戏窗口
    from pygame import joystick, display, event, JOYDEVICEADDED, QUIT
    display.set_mode((800, 600))
    joystick.init()
    
    # 保存控制器对象的列表 js = []
    running = True while running: for e in event.get(): if e.type == QUIT: running = False elif e.type == JOYDEVICEADDED: # 控制器连接事件 j = joystick.Joystick(e.device_index) js.append(j) print(f'控制器实例 ID:{j.get_instance_id()}')

    获取控制器的名称

    JoystickType对象的get_name方法,可获取游戏控制器在操作系统中的名称。

    get_name()

    返回值

    get_name方法返回表示控制器名称的字符串。

    info.py
    # …
    print(f'控制器名称:{j.get_name()}')

    获取控制器的剩余电量

    JoystickType对象的get_power_level方法,可获取游戏控制器的当前电量。

    get_power_level()

    返回值

    get_power_level方法返回表示控制器当前电量的字符串,根据电量的不同,其值可能是'empty''low''medium''full''wired''max'。如果无法得知电量或控制器没有电池,则get_power_level方法理论上应返回'unknown'

    info.py
    # …
    print(f'控制器电量:{j.get_power_level()}')

    获取控制器的 GUID

    JoystickType对象的get_guid方法,可获取游戏控制器的 GUID(用于表示控制器的型号),他与控制器连接事件的Event对象的guid变量一致。

    get_guid()

    返回值

    get_guid方法返回表示控制器 GUID 的字符串。

    info.py
    # …
    print(f'控制器 GUID:{j.get_guid()}')

    源码

    src/zh/joystick·codebeatme/pygame·GitHub

    讲解视频

    如何在 Pygame 中处理连接与中断的控制器,以及获取相关信息·YouTube如何在 Pygame 中处理连接与中断的控制器,以及获取相关信息·Bilibili
    如何在 Pygame 中获取控制器按键、摇杆状态·YouTube如何在 Pygame 中获取控制器按键、摇杆状态·Bilibili
    如何在 Pygame 中启动和停止控制器的震动回馈·YouTube如何在 Pygame 中启动和停止控制器的震动回馈·Bilibili