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, info 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手柄按键映射 88 89这个表中的键值对表示了手柄按键和 JoyButton 与 JoyAxis 之间的映射关系。 90 91键值对的键表示手柄按键的名称,值表示手柄按键的枚举值。 92 93例如,"A" 键表示手柄的 A 按钮,其值为 JoyButton.JOY_BUTTON_A。 94""" 95 96 97INPUTS_BUTTON_MAPPING = { 98 "BTN_SOUTH": JoyButton.JOY_BUTTON_A, 99 "BTN_EAST": JoyButton.JOY_BUTTON_B, 100 "BTN_WEST": JoyButton.JOY_BUTTON_X, 101 "BTN_NORTH": JoyButton.JOY_BUTTON_Y, 102 "BTN_START": JoyButton.JOY_BUTTON_BACK, 103 "BTN_SELECT": JoyButton.JOY_BUTTON_START, 104 105 "BTN_THUMBL": JoyButton.JOY_BUTTON_LEFT_STICK, 106 "BTN_THUMBR": JoyButton.JOY_BUTTON_RIGHT_STICK, 107 "BTN_TL": JoyButton.JOY_BUTTON_LEFT_SHOULDER, 108 "BTN_TR": JoyButton.JOY_BUTTON_RIGHT_SHOULDER, 109} 110 111INPUTS_AXIS_MAPPING = { 112 "ABS_X": JoyAxis.JOY_AXIS_LEFT_X, 113 "ABS_Y": JoyAxis.JOY_AXIS_LEFT_Y, 114 "ABS_RX": JoyAxis.JOY_AXIS_RIGHT_X, 115 "ABS_RY": JoyAxis.JOY_AXIS_RIGHT_Y, 116 117 "ABS_Z": JoyAxis.JOY_AXIS_TRIGGER_LEFT, 118 "ABS_RZ": JoyAxis.JOY_AXIS_TRIGGER_RIGHT, 119 120 "ABS_HAT0X": JoyAxis.JOY_AXIS_DPAD_X, 121 "ABS_HAT0Y": JoyAxis.JOY_AXIS_DPAD_Y 122} 123 124INPUTS_AXIS_VALUE_MAPPING = { 125 "ABS_X": 32767.0, 126 "ABS_Y": 32767.0, 127 "ABS_RX": 32767.0, 128 "ABS_RY": 32767.0, 129 130 "ABS_Z": 255.0, 131 "ABS_RZ": 255.0, 132 133 "ABS_HAT0X": 1.0, 134 "ABS_HAT0Y": 1.0 135} 136 137# 定义 InputEvent 类以及子类 138class InputEvent: 139 """ 输入事件基类 """ 140 def __init__(self): 141 pass 142 143 def get_action_strength(self, action: str) -> float: 144 """ 返回某个动作的强度 """ 145 pass 146 147 def is_action_pressed(self, action: str) -> bool: 148 """ 检查某个动作是否被按下 """ 149 pass 150 151 def is_action_released(self, action: str) -> bool: 152 """ 检查某个动作是否被释放 """ 153 pass 154 155class InputEventJoypadButton(InputEvent): 156 """手柄按钮事件""" 157 def __init__(self, button_index: JoyButton, pressed: bool): 158 """ 初始化手柄按键事件 """ 159 self.button_index: JoyButton = button_index 160 """ 当前按键索引 """ 161 self.pressed: bool = pressed 162 """ 当前按键是否被按下 """ 163 164 def is_action_pressed(self, action: str) -> bool: 165 """ 检查当前事件是否是某个手柄按键被按下 """ 166 if JOY_MAPPING.get(action) == self.button_index and self.pressed: 167 return True 168 return False 169 170 def is_action_released(self, action: str) -> bool: 171 """ 检查当前事件是否是某个手柄按键被释放 """ 172 if JOY_MAPPING.get(action) == self.button_index and not self.pressed: 173 return True 174 return False 175 176 def __repr__(self): 177 return f"JoypadButton({self.button_index}, {self.pressed})" 178 179class InputEventJoypadAxis(InputEvent): 180 """手柄轴事件""" 181 def __init__(self, axis: JoyAxis, axis_value: float): 182 """ 初始化手柄轴事件 """ 183 self.axis: JoyAxis = axis 184 """ 当前轴索引 """ 185 self.axis_value: float = axis_value 186 """ 当前轴值 """ 187 188 def get_action_strength(self, action: str) -> float: 189 """ 检查当前事件的某个轴值 """ 190 if JOY_MAPPING.get(action) == self.axis: 191 return self.axis_value 192 return 0.0 193 194 def __repr__(self): 195 return f"JoypadAxis({self.axis}, {self.axis_value})" 196 197class GamepadListener(): 198 def __init__(self): 199 self.devices = inputs.devices.gamepads 200 if not self.devices: 201 error("您开启了 Gamepad 输入检测,但是未检测到 Gamepad 设备,请连接 Gamepad 设备后重试") 202 else: 203 info(f"您开启了 Gamepad 输入检测,检测到 {len(self.devices)} 个 Gamepad 设备, 将使用第一个设备 {self.devices[0].name} 进行输入检测") 204 205 def listen(self) -> InputEvent: # type: ignore 206 """监听手柄输入并生成事件""" 207 _events = inputs.get_gamepad() 208 for _event in _events: 209 if _event.ev_type == 'Key': 210 # 假设是按键事件 211 button_index = JoyButton(INPUTS_BUTTON_MAPPING.get(_event.code)) # 获取按键代码 212 pressed = _event.state == 1 213 input_event = InputEventJoypadButton(button_index, pressed) 214 yield input_event 215 elif _event.ev_type == 'Absolute': 216 # 假设是轴向事件 217 axis = JoyAxis(INPUTS_AXIS_MAPPING.get(_event.code)) # 获取轴向代码 218 axis_value = _event.state / INPUTS_AXIS_VALUE_MAPPING.get(_event.code) 219 input_event = InputEventJoypadAxis(axis, axis_value) 220 yield input_event 221 222class Input: 223 """ 224 输入类,每个 Node 节点都可以使用 self.input 来获取 Input 对象。 225 226 输入类的使用方法: 227 228 # 获取输入对象 229 input = self.input 230 231 # 检查某个动作是否被按下 232 if input.is_action_pressed("A"): 233 print("A 键被按下") 234 235 # 检查某个动作的强度 236 print(input.get_action_strength("LEFT_X")) 237 238 Input 与 _input 的用法有所不同 239 240 Input 在检测按键是否按下时,如果此时函数连续被调用,则会连续返回 True,直到按键被释放。 241 242 而 _input 则类似于中断,当按键被按下后,只会在 _input 事件中检测到一次。 243 244 """ 245 def __init__(self): 246 self._button_states = { 247 'A': False, 248 'B': False, 249 'X': False, 250 'Y': False, 251 'BACK': False, 252 'START': False, 253 'LEFT_STICK': False, 254 'RIGHT_STICK': False, 255 'LEFT_SHOULDER': False, 256 'RIGHT_SHOULDER': False, 257 } 258 259 self._axis_states = { 260 'LEFT_X': 0.0, 261 'LEFT_Y': 0.0, 262 'RIGHT_X': 0.0, 263 'RIGHT_Y': 0.0, 264 'TRIGGER_LEFT': 0.0, 265 'TRIGGER_RIGHT': 0.0, 266 'DPAD_X': 0.0, 267 'DPAD_Y': 0.0 268 } 269 270 def _get_key_from_value(self, mapping, value): 271 for key, val in mapping.items(): 272 if val == value: 273 return key 274 return None 275 276 def _update(self, event: InputEvent): 277 if isinstance(event, InputEventJoypadButton): 278 self._button_states[self._get_key_from_value(JOY_MAPPING, event.button_index)] = event.pressed 279 elif isinstance(event, InputEventJoypadAxis): 280 self._axis_states[self._get_key_from_value(JOY_MAPPING, event.axis)] = event.axis_value 281 282 def get_axis(self, negative_action: str, positive_action: str) -> float: 283 if negative_action not in self.axis_states or positive_action not in self.axis_states: 284 raise ValueError(f"无效的 axis 动作: {negative_action}, {positive_action}") 285 negative = self._axis_states[negative_action] 286 positive = self._axis_states[positive_action] 287 288 return positive - negative 289 290 def get_action_strength(self, action: str) -> float: 291 if action in self._axis_states: 292 return self._axis_states[action] 293 else: 294 return 0.0 295 296 def is_action_pressed(self, action: str) -> bool: 297 if action in self._button_states: 298 return self._button_states[action] 299 else: 300 return False 301 302 def is_action_released(self, action: str) -> bool: 303 if action in self._button_states: 304 return not self._button_states[action] 305 else: 306 return False 307 308 def flush_action(self, action: str) -> None: 309 if action in self._button_states: 310 self._button_states[action] = False 311 elif action in self._axis_states: 312 self._axis_states[action] = 0.0 313 314 def is_anything_pressed(self) -> bool: 315 for value in self._button_states.values(): 316 if value: 317 return True 318 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 手柄为例
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 手柄为例
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>}
手柄按键映射
这个表中的键值对表示了手柄按键和 JoyButton 与 JoyAxis 之间的映射关系。
键值对的键表示手柄按键的名称,值表示手柄按键的枚举值。
例如,"A" 键表示手柄的 A 按钮,其值为 JoyButton.JOY_BUTTON_A。
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:
139class InputEvent: 140 """ 输入事件基类 """ 141 def __init__(self): 142 pass 143 144 def get_action_strength(self, action: str) -> float: 145 """ 返回某个动作的强度 """ 146 pass 147 148 def is_action_pressed(self, action: str) -> bool: 149 """ 检查某个动作是否被按下 """ 150 pass 151 152 def is_action_released(self, action: str) -> bool: 153 """ 检查某个动作是否被释放 """ 154 pass
输入事件基类
156class InputEventJoypadButton(InputEvent): 157 """手柄按钮事件""" 158 def __init__(self, button_index: JoyButton, pressed: bool): 159 """ 初始化手柄按键事件 """ 160 self.button_index: JoyButton = button_index 161 """ 当前按键索引 """ 162 self.pressed: bool = pressed 163 """ 当前按键是否被按下 """ 164 165 def is_action_pressed(self, action: str) -> bool: 166 """ 检查当前事件是否是某个手柄按键被按下 """ 167 if JOY_MAPPING.get(action) == self.button_index and self.pressed: 168 return True 169 return False 170 171 def is_action_released(self, action: str) -> bool: 172 """ 检查当前事件是否是某个手柄按键被释放 """ 173 if JOY_MAPPING.get(action) == self.button_index and not self.pressed: 174 return True 175 return False 176 177 def __repr__(self): 178 return f"JoypadButton({self.button_index}, {self.pressed})"
手柄按钮事件
InputEventJoypadButton(button_index: JoyButton, pressed: bool)
158 def __init__(self, button_index: JoyButton, pressed: bool): 159 """ 初始化手柄按键事件 """ 160 self.button_index: JoyButton = button_index 161 """ 当前按键索引 """ 162 self.pressed: bool = pressed 163 """ 当前按键是否被按下 """
初始化手柄按键事件
def
is_action_pressed(self, action: str) -> bool:
165 def is_action_pressed(self, action: str) -> bool: 166 """ 检查当前事件是否是某个手柄按键被按下 """ 167 if JOY_MAPPING.get(action) == self.button_index and self.pressed: 168 return True 169 return False
检查当前事件是否是某个手柄按键被按下
def
is_action_released(self, action: str) -> bool:
171 def is_action_released(self, action: str) -> bool: 172 """ 检查当前事件是否是某个手柄按键被释放 """ 173 if JOY_MAPPING.get(action) == self.button_index and not self.pressed: 174 return True 175 return False
检查当前事件是否是某个手柄按键被释放
Inherited Members
180class InputEventJoypadAxis(InputEvent): 181 """手柄轴事件""" 182 def __init__(self, axis: JoyAxis, axis_value: float): 183 """ 初始化手柄轴事件 """ 184 self.axis: JoyAxis = axis 185 """ 当前轴索引 """ 186 self.axis_value: float = axis_value 187 """ 当前轴值 """ 188 189 def get_action_strength(self, action: str) -> float: 190 """ 检查当前事件的某个轴值 """ 191 if JOY_MAPPING.get(action) == self.axis: 192 return self.axis_value 193 return 0.0 194 195 def __repr__(self): 196 return f"JoypadAxis({self.axis}, {self.axis_value})"
手柄轴事件
InputEventJoypadAxis(axis: JoyAxis, axis_value: float)
182 def __init__(self, axis: JoyAxis, axis_value: float): 183 """ 初始化手柄轴事件 """ 184 self.axis: JoyAxis = axis 185 """ 当前轴索引 """ 186 self.axis_value: float = axis_value 187 """ 当前轴值 """
初始化手柄轴事件
def
get_action_strength(self, action: str) -> float:
189 def get_action_strength(self, action: str) -> float: 190 """ 检查当前事件的某个轴值 """ 191 if JOY_MAPPING.get(action) == self.axis: 192 return self.axis_value 193 return 0.0
检查当前事件的某个轴值
Inherited Members
class
GamepadListener:
198class GamepadListener(): 199 def __init__(self): 200 self.devices = inputs.devices.gamepads 201 if not self.devices: 202 error("您开启了 Gamepad 输入检测,但是未检测到 Gamepad 设备,请连接 Gamepad 设备后重试") 203 else: 204 info(f"您开启了 Gamepad 输入检测,检测到 {len(self.devices)} 个 Gamepad 设备, 将使用第一个设备 {self.devices[0].name} 进行输入检测") 205 206 def listen(self) -> InputEvent: # type: ignore 207 """监听手柄输入并生成事件""" 208 _events = inputs.get_gamepad() 209 for _event in _events: 210 if _event.ev_type == 'Key': 211 # 假设是按键事件 212 button_index = JoyButton(INPUTS_BUTTON_MAPPING.get(_event.code)) # 获取按键代码 213 pressed = _event.state == 1 214 input_event = InputEventJoypadButton(button_index, pressed) 215 yield input_event 216 elif _event.ev_type == 'Absolute': 217 # 假设是轴向事件 218 axis = JoyAxis(INPUTS_AXIS_MAPPING.get(_event.code)) # 获取轴向代码 219 axis_value = _event.state / INPUTS_AXIS_VALUE_MAPPING.get(_event.code) 220 input_event = InputEventJoypadAxis(axis, axis_value) 221 yield input_event
206 def listen(self) -> InputEvent: # type: ignore 207 """监听手柄输入并生成事件""" 208 _events = inputs.get_gamepad() 209 for _event in _events: 210 if _event.ev_type == 'Key': 211 # 假设是按键事件 212 button_index = JoyButton(INPUTS_BUTTON_MAPPING.get(_event.code)) # 获取按键代码 213 pressed = _event.state == 1 214 input_event = InputEventJoypadButton(button_index, pressed) 215 yield input_event 216 elif _event.ev_type == 'Absolute': 217 # 假设是轴向事件 218 axis = JoyAxis(INPUTS_AXIS_MAPPING.get(_event.code)) # 获取轴向代码 219 axis_value = _event.state / INPUTS_AXIS_VALUE_MAPPING.get(_event.code) 220 input_event = InputEventJoypadAxis(axis, axis_value) 221 yield input_event
监听手柄输入并生成事件
class
Input:
223class Input: 224 """ 225 输入类,每个 Node 节点都可以使用 self.input 来获取 Input 对象。 226 227 输入类的使用方法: 228 229 # 获取输入对象 230 input = self.input 231 232 # 检查某个动作是否被按下 233 if input.is_action_pressed("A"): 234 print("A 键被按下") 235 236 # 检查某个动作的强度 237 print(input.get_action_strength("LEFT_X")) 238 239 Input 与 _input 的用法有所不同 240 241 Input 在检测按键是否按下时,如果此时函数连续被调用,则会连续返回 True,直到按键被释放。 242 243 而 _input 则类似于中断,当按键被按下后,只会在 _input 事件中检测到一次。 244 245 """ 246 def __init__(self): 247 self._button_states = { 248 'A': False, 249 'B': False, 250 'X': False, 251 'Y': False, 252 'BACK': False, 253 'START': False, 254 'LEFT_STICK': False, 255 'RIGHT_STICK': False, 256 'LEFT_SHOULDER': False, 257 'RIGHT_SHOULDER': False, 258 } 259 260 self._axis_states = { 261 'LEFT_X': 0.0, 262 'LEFT_Y': 0.0, 263 'RIGHT_X': 0.0, 264 'RIGHT_Y': 0.0, 265 'TRIGGER_LEFT': 0.0, 266 'TRIGGER_RIGHT': 0.0, 267 'DPAD_X': 0.0, 268 'DPAD_Y': 0.0 269 } 270 271 def _get_key_from_value(self, mapping, value): 272 for key, val in mapping.items(): 273 if val == value: 274 return key 275 return None 276 277 def _update(self, event: InputEvent): 278 if isinstance(event, InputEventJoypadButton): 279 self._button_states[self._get_key_from_value(JOY_MAPPING, event.button_index)] = event.pressed 280 elif isinstance(event, InputEventJoypadAxis): 281 self._axis_states[self._get_key_from_value(JOY_MAPPING, event.axis)] = event.axis_value 282 283 def get_axis(self, negative_action: str, positive_action: str) -> float: 284 if negative_action not in self.axis_states or positive_action not in self.axis_states: 285 raise ValueError(f"无效的 axis 动作: {negative_action}, {positive_action}") 286 negative = self._axis_states[negative_action] 287 positive = self._axis_states[positive_action] 288 289 return positive - negative 290 291 def get_action_strength(self, action: str) -> float: 292 if action in self._axis_states: 293 return self._axis_states[action] 294 else: 295 return 0.0 296 297 def is_action_pressed(self, action: str) -> bool: 298 if action in self._button_states: 299 return self._button_states[action] 300 else: 301 return False 302 303 def is_action_released(self, action: str) -> bool: 304 if action in self._button_states: 305 return not self._button_states[action] 306 else: 307 return False 308 309 def flush_action(self, action: str) -> None: 310 if action in self._button_states: 311 self._button_states[action] = False 312 elif action in self._axis_states: 313 self._axis_states[action] = 0.0 314 315 def is_anything_pressed(self) -> bool: 316 for value in self._button_states.values(): 317 if value: 318 return True 319 return False
输入类,每个 Node 节点都可以使用 self.input 来获取 Input 对象。
输入类的使用方法:
# 获取输入对象
input = self.input
# 检查某个动作是否被按下
if input.is_action_pressed("A"):
print("A 键被按下")
# 检查某个动作的强度
print(input.get_action_strength("LEFT_X"))
Input 与 _input 的用法有所不同
Input 在检测按键是否按下时,如果此时函数连续被调用,则会连续返回 True,直到按键被释放。
而 _input 则类似于中断,当按键被按下后,只会在 _input 事件中检测到一次。
def
get_axis(self, negative_action: str, positive_action: str) -> float:
283 def get_axis(self, negative_action: str, positive_action: str) -> float: 284 if negative_action not in self.axis_states or positive_action not in self.axis_states: 285 raise ValueError(f"无效的 axis 动作: {negative_action}, {positive_action}") 286 negative = self._axis_states[negative_action] 287 positive = self._axis_states[positive_action] 288 289 return positive - negative