robotengine.input

input 是 robotengine 中用于处理输入的模块。

在引擎初始化时,会根据 input_devices 参数创建 Input 实例,并将其传递给所有节点。

注意:在传递 input_devices 非空时,必须提前连接好相应的设备,否则程序会自动终止。

在节点的构造中,可以使用 _input(event: InputEvent) 来以回调的方式处理输入事件,也可以使用 self.input 来显式的访问 Input 实例。

  1"""
  2
  3input 是 robotengine 中用于处理输入的模块。
  4
  5在引擎初始化时,会根据 input_devices 参数创建 Input 实例,并将其传递给所有节点。
  6
  7注意:在传递 input_devices 非空时,必须提前连接好相应的设备,否则程序会自动终止。
  8
  9在节点的构造中,可以使用 _input(event: InputEvent) 来以回调的方式处理输入事件,也可以使用 self.input 来显式的访问 Input 实例。
 10
 11"""
 12
 13
 14from enum import Enum
 15import inputs
 16from robotengine.tools import error, warning
 17
 18# 定义 JoyButton 和 JoyAxis 枚举
 19class JoyButton(Enum):
 20    """ 手柄按钮枚举,以下以 Xbox 手柄为例 """
 21    JOY_BUTTON_INVALID = -1
 22    """ 无效按钮 """
 23    JOY_BUTTON_A = 0
 24    """ A 按钮 """
 25    JOY_BUTTON_B = 1
 26    """ B 按钮 """
 27    JOY_BUTTON_X = 2
 28    """ X 按钮 """
 29    JOY_BUTTON_Y = 3
 30    """ Y 按钮 """
 31    JOY_BUTTON_BACK = 4
 32    """ BACK 按钮 """
 33    JOY_BUTTON_START = 5
 34    """ START 按钮 """
 35    JOY_BUTTON_LEFT_STICK = 6
 36    """ 左摇杆按钮 """
 37    JOY_BUTTON_RIGHT_STICK = 7
 38    """ 右摇杆按钮 """
 39    JOY_BUTTON_LEFT_SHOULDER = 8
 40    """ 左扳机按钮 """
 41    JOY_BUTTON_RIGHT_SHOULDER = 9
 42    """ 右扳机按钮 """
 43
 44class JoyAxis(Enum):
 45    """ 手柄轴枚举,以下以 Xbox 手柄为例 """
 46    JOY_AXIS_INVALID = -1
 47    """ 无效轴 """
 48    JOY_AXIS_LEFT_X = 0
 49    """ 左摇杆 X 轴 """
 50    JOY_AXIS_LEFT_Y = 1
 51    """ 左摇杆 Y 轴 """
 52    JOY_AXIS_RIGHT_X = 2
 53    """ 右摇杆 X 轴 """
 54    JOY_AXIS_RIGHT_Y = 3
 55    """ 右摇杆 Y 轴 """
 56    JOY_AXIS_TRIGGER_LEFT = 4
 57    """ 左扳机轴 """
 58    JOY_AXIS_TRIGGER_RIGHT = 5
 59    """ 右扳机轴 """
 60    JOY_AXIS_DPAD_X = 6
 61    """ D-Pad X 轴 """
 62    JOY_AXIS_DPAD_Y = 7
 63    """ D-Pad Y 轴 """
 64
 65JOY_MAPPING = {
 66    "A": JoyButton.JOY_BUTTON_A,
 67    "B": JoyButton.JOY_BUTTON_B,
 68    "X": JoyButton.JOY_BUTTON_X,
 69    "Y": JoyButton.JOY_BUTTON_Y,
 70    "BACK": JoyButton.JOY_BUTTON_BACK,
 71    "START": JoyButton.JOY_BUTTON_START,
 72    "LEFT_STICK": JoyButton.JOY_BUTTON_LEFT_STICK,
 73    "RIGHT_STICK": JoyButton.JOY_BUTTON_RIGHT_STICK,
 74    "LEFT_SHOULDER": JoyButton.JOY_BUTTON_LEFT_SHOULDER,
 75    "RIGHT_SHOULDER": JoyButton.JOY_BUTTON_RIGHT_SHOULDER,
 76
 77    "LEFT_X": JoyAxis.JOY_AXIS_LEFT_X,
 78    "LEFT_Y": JoyAxis.JOY_AXIS_LEFT_Y,
 79    "RIGHT_X": JoyAxis.JOY_AXIS_RIGHT_X,
 80    "RIGHT_Y": JoyAxis.JOY_AXIS_RIGHT_Y,
 81    "TRIGGER_LEFT": JoyAxis.JOY_AXIS_TRIGGER_LEFT,
 82    "TRIGGER_RIGHT": JoyAxis.JOY_AXIS_TRIGGER_RIGHT,
 83    "DPAD_X": JoyAxis.JOY_AXIS_DPAD_X,
 84    "DPAD_Y": JoyAxis.JOY_AXIS_DPAD_Y
 85}
 86
 87
 88INPUTS_BUTTON_MAPPING = {
 89    "BTN_SOUTH": JoyButton.JOY_BUTTON_A,
 90    "BTN_EAST": JoyButton.JOY_BUTTON_B,
 91    "BTN_WEST": JoyButton.JOY_BUTTON_X,
 92    "BTN_NORTH": JoyButton.JOY_BUTTON_Y,
 93    "BTN_START": JoyButton.JOY_BUTTON_BACK,
 94    "BTN_SELECT": JoyButton.JOY_BUTTON_START,
 95    
 96    "BTN_THUMBL": JoyButton.JOY_BUTTON_LEFT_STICK,
 97    "BTN_THUMBR": JoyButton.JOY_BUTTON_RIGHT_STICK,
 98    "BTN_TL": JoyButton.JOY_BUTTON_LEFT_SHOULDER,
 99    "BTN_TR": JoyButton.JOY_BUTTON_RIGHT_SHOULDER,
100}
101
102INPUTS_AXIS_MAPPING = {
103    "ABS_X": JoyAxis.JOY_AXIS_LEFT_X,
104    "ABS_Y": JoyAxis.JOY_AXIS_LEFT_Y,
105    "ABS_RX": JoyAxis.JOY_AXIS_RIGHT_X,
106    "ABS_RY": JoyAxis.JOY_AXIS_RIGHT_Y,
107
108    "ABS_Z": JoyAxis.JOY_AXIS_TRIGGER_LEFT,
109    "ABS_RZ": JoyAxis.JOY_AXIS_TRIGGER_RIGHT,
110
111    "ABS_HAT0X": JoyAxis.JOY_AXIS_DPAD_X,
112    "ABS_HAT0Y": JoyAxis.JOY_AXIS_DPAD_Y
113}
114
115INPUTS_AXIS_VALUE_MAPPING = {
116    "ABS_X": 32767.0,
117    "ABS_Y": 32767.0,
118    "ABS_RX": 32767.0,
119    "ABS_RY": 32767.0,
120
121    "ABS_Z": 255.0,
122    "ABS_RZ": 255.0,
123
124    "ABS_HAT0X": 1.0,
125    "ABS_HAT0Y": 1.0
126}
127
128# 定义 InputEvent 类以及子类
129class InputEvent:
130    """ 输入事件基类 """
131    def __init__(self):
132        pass
133
134    def get_action_strength(self, action: str) -> float:
135        """ 返回某个动作的强度 """
136        pass
137
138    def is_action_pressed(self, action: str) -> bool:
139        """ 检查某个动作是否被按下 """
140        pass
141
142    def is_action_released(self, action: str) -> bool:
143        """ 检查某个动作是否被释放 """
144        pass
145
146class InputEventJoypadButton(InputEvent):
147    """手柄按钮事件"""
148    def __init__(self, button_index: JoyButton, pressed: bool):
149        """ 初始化手柄按键事件 """
150        self.button_index: JoyButton = button_index
151        """ 当前按键索引 """
152        self.pressed: bool = pressed
153        """ 当前按键是否被按下 """
154
155    def is_action_pressed(self, action: str) -> bool:
156        """ 检查当前事件是否是某个手柄按键被按下 """
157        if JOY_MAPPING.get(action) == self.button_index and self.pressed:
158            return True
159        return False
160
161    def is_action_released(self, action: str) -> bool:
162        """ 检查当前事件是否是某个手柄按键被释放 """
163        if JOY_MAPPING.get(action) == self.button_index and not self.pressed:
164            return True
165        return False
166    
167    def __repr__(self):
168        return f"JoypadButton({self.button_index}, {self.pressed})"
169
170class InputEventJoypadAxis(InputEvent):
171    """手柄轴事件"""
172    def __init__(self, axis: JoyAxis, axis_value: float):
173        """ 初始化手柄轴事件 """
174        self.axis: JoyAxis = axis
175        """ 当前轴索引 """
176        self.axis_value: float = axis_value
177        """ 当前轴值 """
178
179    def get_action_strength(self, action: str) -> float:
180        """ 检查当前事件的某个轴值 """
181        if JOY_MAPPING.get(action) == self.axis:
182            return self.axis_value
183        return 0.0
184    
185    def __repr__(self):
186        return f"JoypadAxis({self.axis}, {self.axis_value})"
187
188class GamepadListener():
189    def __init__(self):
190        self.devices = inputs.devices.gamepads
191        if not self.devices:
192            error("您开启了 Gamepad 输入检测,但是未检测到 Gamepad 设备,请连接 Gamepad 设备后重试")
193        else:
194            warning(f"您开启了 Gamepad 输入检测,检测到 {len(self.devices)} 个 Gamepad 设备, 将使用第一个设备 {self.devices[0].name} 进行输入检测")
195
196    def listen(self) -> InputEvent: # type: ignore
197        """监听手柄输入并生成事件"""
198        _events = inputs.get_gamepad()
199        for _event in _events:
200            if _event.ev_type == 'Key':
201                # 假设是按键事件
202                button_index = JoyButton(INPUTS_BUTTON_MAPPING.get(_event.code))  # 获取按键代码
203                pressed = _event.state == 1
204                input_event = InputEventJoypadButton(button_index, pressed)
205                yield input_event
206            elif _event.ev_type == 'Absolute':
207                # 假设是轴向事件
208                axis = JoyAxis(INPUTS_AXIS_MAPPING.get(_event.code))  # 获取轴向代码
209                axis_value = _event.state / INPUTS_AXIS_VALUE_MAPPING.get(_event.code)
210                input_event = InputEventJoypadAxis(axis, axis_value)
211                yield input_event
212
213class Input:
214    def __init__(self):
215        self._button_states = {
216            'A': False,
217            'B': False,
218            'X': False,
219            'Y': False,
220            'BACK': False,
221            'START': False,
222            'LEFT_STICK': False,
223            'RIGHT_STICK': False,
224            'LEFT_SHOULDER': False,
225            'RIGHT_SHOULDER': False,
226        }
227
228        self._axis_states = {
229            'LEFT_X': 0.0,
230            'LEFT_Y': 0.0,
231            'RIGHT_X': 0.0,
232            'RIGHT_Y': 0.0,
233            'TRIGGER_LEFT': 0.0,
234            'TRIGGER_RIGHT': 0.0,
235            'DPAD_X': 0.0,
236            'DPAD_Y': 0.0
237        }
238
239
240    def get_key_from_value(self, mapping, value):
241        for key, val in mapping.items():
242            if val == value:
243                return key
244        return None
245
246    def update(self, event: InputEvent):
247        if isinstance(event, InputEventJoypadButton):
248            self._button_states[self.get_key_from_value(JOY_MAPPING, event.button_index)] = event.pressed
249        elif isinstance(event, InputEventJoypadAxis):
250            self._axis_states[self.get_key_from_value(JOY_MAPPING, event.axis)] = event.axis_value
251
252    def get_axis(self, negative_action: str, positive_action: str) -> float:
253        if negative_action not in self.axis_states or positive_action not in self.axis_states:
254            raise ValueError(f"无效的 axis 动作: {negative_action}, {positive_action}")
255        negative = self._axis_states[negative_action]
256        positive = self._axis_states[positive_action]
257
258        return positive - negative
259    
260    def get_action_strength(self, action: str) -> bool:
261        if action in self._axis_states:
262            return self._axis_states[action]
263        else:
264            raise ValueError(f"无效的动作: {action}")
265    
266    def is_action_pressed(self, action: str) -> bool:
267        if action in self._button_states:
268            return self._button_states[action]
269        else:
270            raise ValueError(f"无效的动作: {action}")
271        
272    def is_action_released(self, action: str) -> bool:
273        if action in self._button_states:
274            return not self._button_states[action]
275        else:
276            raise ValueError(f"无效的动作: {action}")
277    
278    def is_anything_pressed(self) -> bool:
279        for value in self._button_states.values():
280            if value:
281                return True
282        return False
class JoyButton(enum.Enum):
20class JoyButton(Enum):
21    """ 手柄按钮枚举,以下以 Xbox 手柄为例 """
22    JOY_BUTTON_INVALID = -1
23    """ 无效按钮 """
24    JOY_BUTTON_A = 0
25    """ A 按钮 """
26    JOY_BUTTON_B = 1
27    """ B 按钮 """
28    JOY_BUTTON_X = 2
29    """ X 按钮 """
30    JOY_BUTTON_Y = 3
31    """ Y 按钮 """
32    JOY_BUTTON_BACK = 4
33    """ BACK 按钮 """
34    JOY_BUTTON_START = 5
35    """ START 按钮 """
36    JOY_BUTTON_LEFT_STICK = 6
37    """ 左摇杆按钮 """
38    JOY_BUTTON_RIGHT_STICK = 7
39    """ 右摇杆按钮 """
40    JOY_BUTTON_LEFT_SHOULDER = 8
41    """ 左扳机按钮 """
42    JOY_BUTTON_RIGHT_SHOULDER = 9
43    """ 右扳机按钮 """

手柄按钮枚举,以下以 Xbox 手柄为例

JOY_BUTTON_INVALID = <JoyButton.JOY_BUTTON_INVALID: -1>

无效按钮

JOY_BUTTON_A = <JoyButton.JOY_BUTTON_A: 0>

A 按钮

JOY_BUTTON_B = <JoyButton.JOY_BUTTON_B: 1>

B 按钮

JOY_BUTTON_X = <JoyButton.JOY_BUTTON_X: 2>

X 按钮

JOY_BUTTON_Y = <JoyButton.JOY_BUTTON_Y: 3>

Y 按钮

JOY_BUTTON_BACK = <JoyButton.JOY_BUTTON_BACK: 4>

BACK 按钮

JOY_BUTTON_START = <JoyButton.JOY_BUTTON_START: 5>

START 按钮

JOY_BUTTON_LEFT_STICK = <JoyButton.JOY_BUTTON_LEFT_STICK: 6>

左摇杆按钮

JOY_BUTTON_RIGHT_STICK = <JoyButton.JOY_BUTTON_RIGHT_STICK: 7>

右摇杆按钮

JOY_BUTTON_LEFT_SHOULDER = <JoyButton.JOY_BUTTON_LEFT_SHOULDER: 8>

左扳机按钮

JOY_BUTTON_RIGHT_SHOULDER = <JoyButton.JOY_BUTTON_RIGHT_SHOULDER: 9>

右扳机按钮

Inherited Members
enum.Enum
name
value
class JoyAxis(enum.Enum):
45class JoyAxis(Enum):
46    """ 手柄轴枚举,以下以 Xbox 手柄为例 """
47    JOY_AXIS_INVALID = -1
48    """ 无效轴 """
49    JOY_AXIS_LEFT_X = 0
50    """ 左摇杆 X 轴 """
51    JOY_AXIS_LEFT_Y = 1
52    """ 左摇杆 Y 轴 """
53    JOY_AXIS_RIGHT_X = 2
54    """ 右摇杆 X 轴 """
55    JOY_AXIS_RIGHT_Y = 3
56    """ 右摇杆 Y 轴 """
57    JOY_AXIS_TRIGGER_LEFT = 4
58    """ 左扳机轴 """
59    JOY_AXIS_TRIGGER_RIGHT = 5
60    """ 右扳机轴 """
61    JOY_AXIS_DPAD_X = 6
62    """ D-Pad X 轴 """
63    JOY_AXIS_DPAD_Y = 7
64    """ D-Pad Y 轴 """

手柄轴枚举,以下以 Xbox 手柄为例

JOY_AXIS_INVALID = <JoyAxis.JOY_AXIS_INVALID: -1>

无效轴

JOY_AXIS_LEFT_X = <JoyAxis.JOY_AXIS_LEFT_X: 0>

左摇杆 X 轴

JOY_AXIS_LEFT_Y = <JoyAxis.JOY_AXIS_LEFT_Y: 1>

左摇杆 Y 轴

JOY_AXIS_RIGHT_X = <JoyAxis.JOY_AXIS_RIGHT_X: 2>

右摇杆 X 轴

JOY_AXIS_RIGHT_Y = <JoyAxis.JOY_AXIS_RIGHT_Y: 3>

右摇杆 Y 轴

JOY_AXIS_TRIGGER_LEFT = <JoyAxis.JOY_AXIS_TRIGGER_LEFT: 4>

左扳机轴

JOY_AXIS_TRIGGER_RIGHT = <JoyAxis.JOY_AXIS_TRIGGER_RIGHT: 5>

右扳机轴

JOY_AXIS_DPAD_X = <JoyAxis.JOY_AXIS_DPAD_X: 6>

D-Pad X 轴

JOY_AXIS_DPAD_Y = <JoyAxis.JOY_AXIS_DPAD_Y: 7>

D-Pad Y 轴

Inherited Members
enum.Enum
name
value
JOY_MAPPING = {'A': <JoyButton.JOY_BUTTON_A: 0>, 'B': <JoyButton.JOY_BUTTON_B: 1>, 'X': <JoyButton.JOY_BUTTON_X: 2>, 'Y': <JoyButton.JOY_BUTTON_Y: 3>, 'BACK': <JoyButton.JOY_BUTTON_BACK: 4>, 'START': <JoyButton.JOY_BUTTON_START: 5>, 'LEFT_STICK': <JoyButton.JOY_BUTTON_LEFT_STICK: 6>, 'RIGHT_STICK': <JoyButton.JOY_BUTTON_RIGHT_STICK: 7>, 'LEFT_SHOULDER': <JoyButton.JOY_BUTTON_LEFT_SHOULDER: 8>, 'RIGHT_SHOULDER': <JoyButton.JOY_BUTTON_RIGHT_SHOULDER: 9>, 'LEFT_X': <JoyAxis.JOY_AXIS_LEFT_X: 0>, 'LEFT_Y': <JoyAxis.JOY_AXIS_LEFT_Y: 1>, 'RIGHT_X': <JoyAxis.JOY_AXIS_RIGHT_X: 2>, 'RIGHT_Y': <JoyAxis.JOY_AXIS_RIGHT_Y: 3>, 'TRIGGER_LEFT': <JoyAxis.JOY_AXIS_TRIGGER_LEFT: 4>, 'TRIGGER_RIGHT': <JoyAxis.JOY_AXIS_TRIGGER_RIGHT: 5>, 'DPAD_X': <JoyAxis.JOY_AXIS_DPAD_X: 6>, 'DPAD_Y': <JoyAxis.JOY_AXIS_DPAD_Y: 7>}
INPUTS_BUTTON_MAPPING = {'BTN_SOUTH': <JoyButton.JOY_BUTTON_A: 0>, 'BTN_EAST': <JoyButton.JOY_BUTTON_B: 1>, 'BTN_WEST': <JoyButton.JOY_BUTTON_X: 2>, 'BTN_NORTH': <JoyButton.JOY_BUTTON_Y: 3>, 'BTN_START': <JoyButton.JOY_BUTTON_BACK: 4>, 'BTN_SELECT': <JoyButton.JOY_BUTTON_START: 5>, 'BTN_THUMBL': <JoyButton.JOY_BUTTON_LEFT_STICK: 6>, 'BTN_THUMBR': <JoyButton.JOY_BUTTON_RIGHT_STICK: 7>, 'BTN_TL': <JoyButton.JOY_BUTTON_LEFT_SHOULDER: 8>, 'BTN_TR': <JoyButton.JOY_BUTTON_RIGHT_SHOULDER: 9>}
INPUTS_AXIS_MAPPING = {'ABS_X': <JoyAxis.JOY_AXIS_LEFT_X: 0>, 'ABS_Y': <JoyAxis.JOY_AXIS_LEFT_Y: 1>, 'ABS_RX': <JoyAxis.JOY_AXIS_RIGHT_X: 2>, 'ABS_RY': <JoyAxis.JOY_AXIS_RIGHT_Y: 3>, 'ABS_Z': <JoyAxis.JOY_AXIS_TRIGGER_LEFT: 4>, 'ABS_RZ': <JoyAxis.JOY_AXIS_TRIGGER_RIGHT: 5>, 'ABS_HAT0X': <JoyAxis.JOY_AXIS_DPAD_X: 6>, 'ABS_HAT0Y': <JoyAxis.JOY_AXIS_DPAD_Y: 7>}
INPUTS_AXIS_VALUE_MAPPING = {'ABS_X': 32767.0, 'ABS_Y': 32767.0, 'ABS_RX': 32767.0, 'ABS_RY': 32767.0, 'ABS_Z': 255.0, 'ABS_RZ': 255.0, 'ABS_HAT0X': 1.0, 'ABS_HAT0Y': 1.0}
class InputEvent:
130class InputEvent:
131    """ 输入事件基类 """
132    def __init__(self):
133        pass
134
135    def get_action_strength(self, action: str) -> float:
136        """ 返回某个动作的强度 """
137        pass
138
139    def is_action_pressed(self, action: str) -> bool:
140        """ 检查某个动作是否被按下 """
141        pass
142
143    def is_action_released(self, action: str) -> bool:
144        """ 检查某个动作是否被释放 """
145        pass

输入事件基类

def get_action_strength(self, action: str) -> float:
135    def get_action_strength(self, action: str) -> float:
136        """ 返回某个动作的强度 """
137        pass

返回某个动作的强度

def is_action_pressed(self, action: str) -> bool:
139    def is_action_pressed(self, action: str) -> bool:
140        """ 检查某个动作是否被按下 """
141        pass

检查某个动作是否被按下

def is_action_released(self, action: str) -> bool:
143    def is_action_released(self, action: str) -> bool:
144        """ 检查某个动作是否被释放 """
145        pass

检查某个动作是否被释放

class InputEventJoypadButton(InputEvent):
147class InputEventJoypadButton(InputEvent):
148    """手柄按钮事件"""
149    def __init__(self, button_index: JoyButton, pressed: bool):
150        """ 初始化手柄按键事件 """
151        self.button_index: JoyButton = button_index
152        """ 当前按键索引 """
153        self.pressed: bool = pressed
154        """ 当前按键是否被按下 """
155
156    def is_action_pressed(self, action: str) -> bool:
157        """ 检查当前事件是否是某个手柄按键被按下 """
158        if JOY_MAPPING.get(action) == self.button_index and self.pressed:
159            return True
160        return False
161
162    def is_action_released(self, action: str) -> bool:
163        """ 检查当前事件是否是某个手柄按键被释放 """
164        if JOY_MAPPING.get(action) == self.button_index and not self.pressed:
165            return True
166        return False
167    
168    def __repr__(self):
169        return f"JoypadButton({self.button_index}, {self.pressed})"

手柄按钮事件

InputEventJoypadButton(button_index: JoyButton, pressed: bool)
149    def __init__(self, button_index: JoyButton, pressed: bool):
150        """ 初始化手柄按键事件 """
151        self.button_index: JoyButton = button_index
152        """ 当前按键索引 """
153        self.pressed: bool = pressed
154        """ 当前按键是否被按下 """

初始化手柄按键事件

button_index: JoyButton

当前按键索引

pressed: bool

当前按键是否被按下

def is_action_pressed(self, action: str) -> bool:
156    def is_action_pressed(self, action: str) -> bool:
157        """ 检查当前事件是否是某个手柄按键被按下 """
158        if JOY_MAPPING.get(action) == self.button_index and self.pressed:
159            return True
160        return False

检查当前事件是否是某个手柄按键被按下

def is_action_released(self, action: str) -> bool:
162    def is_action_released(self, action: str) -> bool:
163        """ 检查当前事件是否是某个手柄按键被释放 """
164        if JOY_MAPPING.get(action) == self.button_index and not self.pressed:
165            return True
166        return False

检查当前事件是否是某个手柄按键被释放

Inherited Members
InputEvent
get_action_strength
class InputEventJoypadAxis(InputEvent):
171class InputEventJoypadAxis(InputEvent):
172    """手柄轴事件"""
173    def __init__(self, axis: JoyAxis, axis_value: float):
174        """ 初始化手柄轴事件 """
175        self.axis: JoyAxis = axis
176        """ 当前轴索引 """
177        self.axis_value: float = axis_value
178        """ 当前轴值 """
179
180    def get_action_strength(self, action: str) -> float:
181        """ 检查当前事件的某个轴值 """
182        if JOY_MAPPING.get(action) == self.axis:
183            return self.axis_value
184        return 0.0
185    
186    def __repr__(self):
187        return f"JoypadAxis({self.axis}, {self.axis_value})"

手柄轴事件

InputEventJoypadAxis(axis: JoyAxis, axis_value: float)
173    def __init__(self, axis: JoyAxis, axis_value: float):
174        """ 初始化手柄轴事件 """
175        self.axis: JoyAxis = axis
176        """ 当前轴索引 """
177        self.axis_value: float = axis_value
178        """ 当前轴值 """

初始化手柄轴事件

axis: JoyAxis

当前轴索引

axis_value: float

当前轴值

def get_action_strength(self, action: str) -> float:
180    def get_action_strength(self, action: str) -> float:
181        """ 检查当前事件的某个轴值 """
182        if JOY_MAPPING.get(action) == self.axis:
183            return self.axis_value
184        return 0.0

检查当前事件的某个轴值

class GamepadListener:
189class GamepadListener():
190    def __init__(self):
191        self.devices = inputs.devices.gamepads
192        if not self.devices:
193            error("您开启了 Gamepad 输入检测,但是未检测到 Gamepad 设备,请连接 Gamepad 设备后重试")
194        else:
195            warning(f"您开启了 Gamepad 输入检测,检测到 {len(self.devices)} 个 Gamepad 设备, 将使用第一个设备 {self.devices[0].name} 进行输入检测")
196
197    def listen(self) -> InputEvent: # type: ignore
198        """监听手柄输入并生成事件"""
199        _events = inputs.get_gamepad()
200        for _event in _events:
201            if _event.ev_type == 'Key':
202                # 假设是按键事件
203                button_index = JoyButton(INPUTS_BUTTON_MAPPING.get(_event.code))  # 获取按键代码
204                pressed = _event.state == 1
205                input_event = InputEventJoypadButton(button_index, pressed)
206                yield input_event
207            elif _event.ev_type == 'Absolute':
208                # 假设是轴向事件
209                axis = JoyAxis(INPUTS_AXIS_MAPPING.get(_event.code))  # 获取轴向代码
210                axis_value = _event.state / INPUTS_AXIS_VALUE_MAPPING.get(_event.code)
211                input_event = InputEventJoypadAxis(axis, axis_value)
212                yield input_event
devices
def listen(self) -> InputEvent:
197    def listen(self) -> InputEvent: # type: ignore
198        """监听手柄输入并生成事件"""
199        _events = inputs.get_gamepad()
200        for _event in _events:
201            if _event.ev_type == 'Key':
202                # 假设是按键事件
203                button_index = JoyButton(INPUTS_BUTTON_MAPPING.get(_event.code))  # 获取按键代码
204                pressed = _event.state == 1
205                input_event = InputEventJoypadButton(button_index, pressed)
206                yield input_event
207            elif _event.ev_type == 'Absolute':
208                # 假设是轴向事件
209                axis = JoyAxis(INPUTS_AXIS_MAPPING.get(_event.code))  # 获取轴向代码
210                axis_value = _event.state / INPUTS_AXIS_VALUE_MAPPING.get(_event.code)
211                input_event = InputEventJoypadAxis(axis, axis_value)
212                yield input_event

监听手柄输入并生成事件

class Input:
214class Input:
215    def __init__(self):
216        self._button_states = {
217            'A': False,
218            'B': False,
219            'X': False,
220            'Y': False,
221            'BACK': False,
222            'START': False,
223            'LEFT_STICK': False,
224            'RIGHT_STICK': False,
225            'LEFT_SHOULDER': False,
226            'RIGHT_SHOULDER': False,
227        }
228
229        self._axis_states = {
230            'LEFT_X': 0.0,
231            'LEFT_Y': 0.0,
232            'RIGHT_X': 0.0,
233            'RIGHT_Y': 0.0,
234            'TRIGGER_LEFT': 0.0,
235            'TRIGGER_RIGHT': 0.0,
236            'DPAD_X': 0.0,
237            'DPAD_Y': 0.0
238        }
239
240
241    def get_key_from_value(self, mapping, value):
242        for key, val in mapping.items():
243            if val == value:
244                return key
245        return None
246
247    def update(self, event: InputEvent):
248        if isinstance(event, InputEventJoypadButton):
249            self._button_states[self.get_key_from_value(JOY_MAPPING, event.button_index)] = event.pressed
250        elif isinstance(event, InputEventJoypadAxis):
251            self._axis_states[self.get_key_from_value(JOY_MAPPING, event.axis)] = event.axis_value
252
253    def get_axis(self, negative_action: str, positive_action: str) -> float:
254        if negative_action not in self.axis_states or positive_action not in self.axis_states:
255            raise ValueError(f"无效的 axis 动作: {negative_action}, {positive_action}")
256        negative = self._axis_states[negative_action]
257        positive = self._axis_states[positive_action]
258
259        return positive - negative
260    
261    def get_action_strength(self, action: str) -> bool:
262        if action in self._axis_states:
263            return self._axis_states[action]
264        else:
265            raise ValueError(f"无效的动作: {action}")
266    
267    def is_action_pressed(self, action: str) -> bool:
268        if action in self._button_states:
269            return self._button_states[action]
270        else:
271            raise ValueError(f"无效的动作: {action}")
272        
273    def is_action_released(self, action: str) -> bool:
274        if action in self._button_states:
275            return not self._button_states[action]
276        else:
277            raise ValueError(f"无效的动作: {action}")
278    
279    def is_anything_pressed(self) -> bool:
280        for value in self._button_states.values():
281            if value:
282                return True
283        return False
def get_key_from_value(self, mapping, value):
241    def get_key_from_value(self, mapping, value):
242        for key, val in mapping.items():
243            if val == value:
244                return key
245        return None
def update(self, event: InputEvent):
247    def update(self, event: InputEvent):
248        if isinstance(event, InputEventJoypadButton):
249            self._button_states[self.get_key_from_value(JOY_MAPPING, event.button_index)] = event.pressed
250        elif isinstance(event, InputEventJoypadAxis):
251            self._axis_states[self.get_key_from_value(JOY_MAPPING, event.axis)] = event.axis_value
def get_axis(self, negative_action: str, positive_action: str) -> float:
253    def get_axis(self, negative_action: str, positive_action: str) -> float:
254        if negative_action not in self.axis_states or positive_action not in self.axis_states:
255            raise ValueError(f"无效的 axis 动作: {negative_action}, {positive_action}")
256        negative = self._axis_states[negative_action]
257        positive = self._axis_states[positive_action]
258
259        return positive - negative
def get_action_strength(self, action: str) -> bool:
261    def get_action_strength(self, action: str) -> bool:
262        if action in self._axis_states:
263            return self._axis_states[action]
264        else:
265            raise ValueError(f"无效的动作: {action}")
def is_action_pressed(self, action: str) -> bool:
267    def is_action_pressed(self, action: str) -> bool:
268        if action in self._button_states:
269            return self._button_states[action]
270        else:
271            raise ValueError(f"无效的动作: {action}")
def is_action_released(self, action: str) -> bool:
273    def is_action_released(self, action: str) -> bool:
274        if action in self._button_states:
275            return not self._button_states[action]
276        else:
277            raise ValueError(f"无效的动作: {action}")
def is_anything_pressed(self) -> bool:
279    def is_anything_pressed(self) -> bool:
280        for value in self._button_states.values():
281            if value:
282                return True
283        return False