使用PySDL2捕获游戏手柄事件

3

我正在使用新的SDL2 Python封装库PySDL2,与手柄事件有关的事件似乎未能显示在事件队列中。按键事件没有问题,当我显式地轮询手柄时,可以正常获取轴状态(并观察到随着移动轴而相应改变)。以下是使用队列的代码:

import sdl2
import sdl2.ext
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK)
joystick = sdl2.SDL_JoystickOpen(0)
sdl2.ext.Window("test", size=(800,600),position=(0,0),flags=sdl2.SDL_WINDOW_SHOWN)
window.refresh()) 
while True:
    for event in sdl2.ext.get_events():
        if event.type==sdl2.SDL_KEYDOWN:
            print sdl2.SDL_GetKeyName(event.key.keysym.sym).lower()
        elif event.type==sdl2.SDL_JOYAXISMOTION:
            print [event.jaxis.axis,event.jaxis.value]

这段代码会将所有的按键事件打印出来,但是不会打印任何轴向运动事件。相比之下,下面是我用来显式轮询轴状态的代码:

import sdl2
import sdl2.ext
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK)
joystick = sdl2.SDL_JoystickOpen(0)

while True:
    sdl2.SDL_PumpEvents()
    print sdl2.SDL_JoystickGetAxis(joystick,0)

这个方法能够很好地工作,但如果状态没有改变,我不想浪费时间轮询状态,所以我更喜欢使用事件队列方法。有什么建议吗?

如果有影响的话,我正在Mac OS 10.9上运行Python 2.7.5。我尝试过罗技USB游戏手柄和Xbox 360有线游戏手柄(通过tattiebogle.net驱动程序启用)。上面我谈论了轴事件,因为那正是我需要的,但我已经检查过,没有一个游戏手柄事件会发布到事件队列中。


抱歉,我无法复制这个。首先,使用您现有的代码,您不会得到任何输出,因为您实际上还没有打开窗口。您是忘记了吗?如果您实际上打开一个窗口(使用SDL_CreateWindow(...)),会发生什么?我已经完全使用了您的代码(除了打开一个窗口),一切正常。我可以打印出轴事件。您使用的是什么类型的游戏手柄?您是否尝试启用DEBUG_JOYSTICK和DEBUG_INPUT_EVENTS来构建SDL? - Mark Hildreth
有趣。代码确实可以在没有窗口的情况下打印输出,添加窗口(通过window = sdl2.ext.Window("test", size=(800,600),position=(0,0),flags=sdl2.SDL_WINDOW_SHOWN); window.refresh())不会改变上述报告的行为。我没有自己编译SDL2,而是简单地安装了Mac框架。我将尝试按照您的建议获取源代码并进行调试构建。 - Mike Lawrence
实际上,虽然我熟悉“./configure; make; sudo make install”的过程,但我不确定如何添加调试标志... - Mike Lawrence
你应该能够在环境变量CFLAGS中定义它们。 - Mark Hildreth
@MarkHildreth 发现如果我从源代码构建SDL2而不是使用预构建的Mac框架,一切都可以正常工作。您愿意发布一个答案以获得您的帮助信用吗? - Mike Lawrence
可以自己发布答案,请确保包含您所使用的版本号。 - Mark Hildreth
2个回答

3

事实证明,使用源代码编译SDL2(版本2.0-1;通过PySDL2-0.7.0访问)可以生成一个构建版本,在该版本中,手柄事件确实会发布到事件队列中(但是您需要创建一个窗口)。看起来问题出在我使用的mac框架版本的SDL2上(从这里下载)。


2
import ctypes
import time
from sdl2 import *


class Joystick:
    def __init__(self):
        SDL_Init(SDL_INIT_JOYSTICK)
        self.axis = {}
        self.button = {}

    def update(self):
        event = SDL_Event()
        while SDL_PollEvent(ctypes.byref(event)) != 0:
            if event.type == SDL_JOYDEVICEADDED:
                self.device = SDL_JoystickOpen(event.jdevice.which)
            elif event.type == SDL_JOYAXISMOTION:
                self.axis[event.jaxis.axis] = event.jaxis.value
            elif event.type == SDL_JOYBUTTONDOWN:
                self.button[event.jbutton.button] = True
            elif event.type == SDL_JOYBUTTONUP:
                self.button[event.jbutton.button] = False


if __name__ == "__main__":
    joystick = Joystick()
    while True:
        joystick.update()
        time.sleep(0.1)
        print(joystick.axis)
        print(joystick.button)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接