pygameP 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pygameP/__init__.py ADDED
@@ -0,0 +1,36 @@
1
+ """pygameP - Pygame Plus 高级游戏开发框架"""
2
+
3
+ __version__ = "0.0.1"
4
+ __author__ = "pygameP contributors"
5
+
6
+ from .shaders import Shader, ShaderEffect, BuiltInEffects
7
+ from .performance import ObjectPool, SpatialHash, FPSMonitor, BatchRenderer
8
+ from .scene import Scene, SceneManager, SceneEntity
9
+ from .physics import RigidBody, PhysicsWorld, Collider, BoxCollider, CircleCollider
10
+ from .input import InputManager, GamepadHandler, TouchHandler
11
+
12
+ __all__ = [
13
+ # Shaders
14
+ "Shader",
15
+ "ShaderEffect",
16
+ "BuiltInEffects",
17
+ # Performance
18
+ "ObjectPool",
19
+ "SpatialHash",
20
+ "FPSMonitor",
21
+ "BatchRenderer",
22
+ # Scene
23
+ "Scene",
24
+ "SceneManager",
25
+ "SceneEntity",
26
+ # Physics
27
+ "RigidBody",
28
+ "PhysicsWorld",
29
+ "Collider",
30
+ "BoxCollider",
31
+ "CircleCollider",
32
+ # Input
33
+ "InputManager",
34
+ "GamepadHandler",
35
+ "TouchHandler",
36
+ ]
pygameP/input.py ADDED
@@ -0,0 +1,548 @@
1
+ """扩展输入设备支持模块"""
2
+
3
+ from typing import Dict, List, Optional, Tuple, Callable, Any
4
+ import pygame
5
+
6
+
7
+ class InputManager:
8
+ """输入管理器 - 统一管理所有输入设备
9
+
10
+ 支持键盘、鼠标、手柄、触摸等多种输入方式。
11
+ """
12
+
13
+ def __init__(self):
14
+ """初始化输入管理器"""
15
+ self.keyboard = KeyboardHandler()
16
+ self.mouse = MouseHandler()
17
+ self.gamepads: Dict[int, GamepadHandler] = {}
18
+ self.touch = TouchHandler()
19
+
20
+ # 输入映射
21
+ self.action_mappings: Dict[str, List[Tuple[str, Any]]] = {}
22
+
23
+ # 初始化手柄
24
+ self._init_gamepads()
25
+
26
+ def _init_gamepads(self):
27
+ """初始化手柄设备"""
28
+ pygame.joystick.init()
29
+ for i in range(pygame.joystick.get_count()):
30
+ joystick = pygame.joystick.Joystick(i)
31
+ joystick.init()
32
+ self.gamepads[i] = GamepadHandler(joystick)
33
+
34
+ def update(self, events: List[pygame.event.Event]):
35
+ """更新所有输入设备状态
36
+
37
+ Args:
38
+ events: pygame 事件列表
39
+ """
40
+ self.keyboard.update(events)
41
+ self.mouse.update(events)
42
+ self.touch.update(events)
43
+
44
+ for gamepad in self.gamepads.values():
45
+ gamepad.update(events)
46
+
47
+ def is_action_pressed(self, action: str) -> bool:
48
+ """检查动作是否被按下
49
+
50
+ Args:
51
+ action: 动作名称
52
+
53
+ Returns:
54
+ 是否按下
55
+ """
56
+ if action not in self.action_mappings:
57
+ return False
58
+
59
+ for device, binding in self.action_mappings[action]:
60
+ if device == 'keyboard' and self.keyboard.is_key_pressed(binding):
61
+ return True
62
+ elif device == 'mouse' and self.mouse.is_button_pressed(binding):
63
+ return True
64
+ elif device == 'gamepad':
65
+ pad_id, button = binding
66
+ if pad_id in self.gamepads:
67
+ return self.gamepads[pad_id].is_button_pressed(button)
68
+
69
+ return False
70
+
71
+ def is_action_just_pressed(self, action: str) -> bool:
72
+ """检查动作是否刚刚被按下
73
+
74
+ Args:
75
+ action: 动作名称
76
+
77
+ Returns:
78
+ 是否刚刚按下
79
+ """
80
+ if action not in self.action_mappings:
81
+ return False
82
+
83
+ for device, binding in self.action_mappings[action]:
84
+ if device == 'keyboard' and self.keyboard.is_key_just_pressed(binding):
85
+ return True
86
+ elif device == 'mouse' and self.mouse.is_button_just_pressed(binding):
87
+ return True
88
+ elif device == 'gamepad':
89
+ pad_id, button = binding
90
+ if pad_id in self.gamepads:
91
+ return self.gamepads[pad_id].is_button_just_pressed(button)
92
+
93
+ return False
94
+
95
+ def is_action_just_released(self, action: str) -> bool:
96
+ """检查动作是否刚刚被释放
97
+
98
+ Args:
99
+ action: 动作名称
100
+
101
+ Returns:
102
+ 是否刚刚释放
103
+ """
104
+ if action not in self.action_mappings:
105
+ return False
106
+
107
+ for device, binding in self.action_mappings[action]:
108
+ if device == 'keyboard' and self.keyboard.is_key_just_released(binding):
109
+ return True
110
+ elif device == 'mouse' and self.mouse.is_button_just_released(binding):
111
+ return True
112
+ elif device == 'gamepad':
113
+ pad_id, button = binding
114
+ if pad_id in self.gamepads:
115
+ return self.gamepads[pad_id].is_button_just_released(button)
116
+
117
+ return False
118
+
119
+ def get_action_value(self, action: str) -> float:
120
+ """获取动作的模拟值(用于手柄摇杆等)
121
+
122
+ Args:
123
+ action: 动作名称
124
+
125
+ Returns:
126
+ 动作值 (-1.0 到 1.0)
127
+ """
128
+ if action not in self.action_mappings:
129
+ return 0.0
130
+
131
+ for device, binding in self.action_mappings[action]:
132
+ if device == 'gamepad':
133
+ pad_id, axis = binding
134
+ if pad_id in self.gamepads:
135
+ return self.gamepads[pad_id].get_axis(axis)
136
+
137
+ # 数字输入返回 0 或 1
138
+ return 1.0 if self.is_action_pressed(action) else 0.0
139
+
140
+ def map_action(self, action: str, device: str, binding: Any):
141
+ """映射动作到输入
142
+
143
+ Args:
144
+ action: 动作名称
145
+ device: 设备类型 ('keyboard', 'mouse', 'gamepad')
146
+ binding: 绑定值(键码、按钮索引等)
147
+ """
148
+ if action not in self.action_mappings:
149
+ self.action_mappings[action] = []
150
+
151
+ self.action_mappings[action].append((device, binding))
152
+
153
+ def unmap_action(self, action: str):
154
+ """移除动作映射
155
+
156
+ Args:
157
+ action: 动作名称
158
+ """
159
+ if action in self.action_mappings:
160
+ del self.action_mappings[action]
161
+
162
+ def get_gamepad_count(self) -> int:
163
+ """获取连接的手柄数量"""
164
+ return len(self.gamepads)
165
+
166
+ def get_gamepad(self, index: int) -> Optional['GamepadHandler']:
167
+ """获取指定索引的手柄
168
+
169
+ Args:
170
+ index: 手柄索引
171
+
172
+ Returns:
173
+ 手柄处理器或 None
174
+ """
175
+ return self.gamepads.get(index)
176
+
177
+
178
+ class KeyboardHandler:
179
+ """键盘输入处理器"""
180
+
181
+ def __init__(self):
182
+ """初始化键盘处理器"""
183
+ self.keys_pressed = set()
184
+ self.keys_just_pressed = set()
185
+ self.keys_just_released = set()
186
+
187
+ def update(self, events: List[pygame.event.Event]):
188
+ """更新键盘状态
189
+
190
+ Args:
191
+ events: pygame 事件列表
192
+ """
193
+ self.keys_just_pressed.clear()
194
+ self.keys_just_released.clear()
195
+
196
+ for event in events:
197
+ if event.type == pygame.KEYDOWN:
198
+ self.keys_pressed.add(event.key)
199
+ self.keys_just_pressed.add(event.key)
200
+ elif event.type == pygame.KEYUP:
201
+ self.keys_pressed.discard(event.key)
202
+ self.keys_just_released.add(event.key)
203
+
204
+ def is_key_pressed(self, key: int) -> bool:
205
+ """检查键是否被按下
206
+
207
+ Args:
208
+ key: pygame 键码
209
+
210
+ Returns:
211
+ 是否按下
212
+ """
213
+ return key in self.keys_pressed
214
+
215
+ def is_key_just_pressed(self, key: int) -> bool:
216
+ """检查键是否刚刚被按下
217
+
218
+ Args:
219
+ key: pygame 键码
220
+
221
+ Returns:
222
+ 是否刚刚按下
223
+ """
224
+ return key in self.keys_just_pressed
225
+
226
+ def is_key_just_released(self, key: int) -> bool:
227
+ """检查键是否刚刚被释放
228
+
229
+ Args:
230
+ key: pygame 键码
231
+
232
+ Returns:
233
+ 是否刚刚释放
234
+ """
235
+ return key in self.keys_just_released
236
+
237
+ def get_pressed_keys(self) -> set:
238
+ """获取所有按下的键"""
239
+ return self.keys_pressed.copy()
240
+
241
+
242
+ class MouseHandler:
243
+ """鼠标输入处理器"""
244
+
245
+ def __init__(self):
246
+ """初始化鼠标处理器"""
247
+ self.position = (0, 0)
248
+ self.rel_motion = (0, 0)
249
+ self.buttons_pressed = set()
250
+ self.buttons_just_pressed = set()
251
+ self.buttons_just_released = set()
252
+ self.scroll_amount = 0
253
+
254
+ def update(self, events: List[pygame.event.Event]):
255
+ """更新鼠标状态
256
+
257
+ Args:
258
+ events: pygame 事件列表
259
+ """
260
+ self.buttons_just_pressed.clear()
261
+ self.buttons_just_released.clear()
262
+ self.rel_motion = (0, 0)
263
+ self.scroll_amount = 0
264
+
265
+ for event in events:
266
+ if event.type == pygame.MOUSEMOTION:
267
+ self.position = event.pos
268
+ self.rel_motion = event.rel
269
+ elif event.type == pygame.MOUSEBUTTONDOWN:
270
+ self.buttons_pressed.add(event.button)
271
+ self.buttons_just_pressed.add(event.button)
272
+ self.position = event.pos
273
+ elif event.type == pygame.MOUSEBUTTONUP:
274
+ self.buttons_pressed.discard(event.button)
275
+ self.buttons_just_released.add(event.button)
276
+ self.position = event.pos
277
+ elif event.type == pygame.MOUSEWHEEL:
278
+ self.scroll_amount = event.y
279
+
280
+ def is_button_pressed(self, button: int) -> bool:
281
+ """检查鼠标按钮是否被按下
282
+
283
+ Args:
284
+ button: 按钮索引 (1=左, 2=中, 3=右)
285
+
286
+ Returns:
287
+ 是否按下
288
+ """
289
+ return button in self.buttons_pressed
290
+
291
+ def is_button_just_pressed(self, button: int) -> bool:
292
+ """检查鼠标按钮是否刚刚被按下
293
+
294
+ Args:
295
+ button: 按钮索引
296
+
297
+ Returns:
298
+ 是否刚刚按下
299
+ """
300
+ return button in self.buttons_just_pressed
301
+
302
+ def is_button_just_released(self, button: int) -> bool:
303
+ """检查鼠标按钮是否刚刚被释放
304
+
305
+ Args:
306
+ button: 按钮索引
307
+
308
+ Returns:
309
+ 是否刚刚释放
310
+ """
311
+ return button in self.buttons_just_released
312
+
313
+ def get_position(self) -> Tuple[int, int]:
314
+ """获取鼠标位置"""
315
+ return self.position
316
+
317
+ def get_relative_motion(self) -> Tuple[int, int]:
318
+ """获取相对运动"""
319
+ return self.rel_motion
320
+
321
+ def get_scroll(self) -> int:
322
+ """获取滚轮滚动量"""
323
+ return self.scroll_amount
324
+
325
+
326
+ class GamepadHandler:
327
+ """手柄输入处理器"""
328
+
329
+ def __init__(self, joystick: pygame.joystick.Joystick):
330
+ """初始化手柄处理器
331
+
332
+ Args:
333
+ joystick: pygame Joystick 对象
334
+ """
335
+ self.joystick = joystick
336
+ self.buttons_pressed = set()
337
+ self.buttons_just_pressed = set()
338
+ self.buttons_just_released = set()
339
+ self.axes = {}
340
+ self.hats = {}
341
+
342
+ # 初始化轴和帽子状态
343
+ for i in range(joystick.get_numaxes()):
344
+ self.axes[i] = 0.0
345
+ for i in range(joystick.get_numhats()):
346
+ self.hats[i] = (0, 0)
347
+
348
+ def update(self, events: List[pygame.event.Event]):
349
+ """更新手柄状态
350
+
351
+ Args:
352
+ events: pygame 事件列表
353
+ """
354
+ self.buttons_just_pressed.clear()
355
+ self.buttons_just_released.clear()
356
+
357
+ for event in events:
358
+ if event.type == pygame.JOYBUTTONDOWN:
359
+ if event.joy == self.joystick.get_id():
360
+ self.buttons_pressed.add(event.button)
361
+ self.buttons_just_pressed.add(event.button)
362
+ elif event.type == pygame.JOYBUTTONUP:
363
+ if event.joy == self.joystick.get_id():
364
+ self.buttons_pressed.discard(event.button)
365
+ self.buttons_just_released.add(event.button)
366
+ elif event.type == pygame.JOYAXISMOTION:
367
+ if event.joy == self.joystick.get_id():
368
+ self.axes[event.axis] = event.value
369
+ elif event.type == pygame.JOYHATMOTION:
370
+ if event.joy == self.joystick.get_id():
371
+ self.hats[event.hat] = event.value
372
+
373
+ def is_button_pressed(self, button: int) -> bool:
374
+ """检查按钮是否被按下
375
+
376
+ Args:
377
+ button: 按钮索引
378
+
379
+ Returns:
380
+ 是否按下
381
+ """
382
+ return button in self.buttons_pressed
383
+
384
+ def is_button_just_pressed(self, button: int) -> bool:
385
+ """检查按钮是否刚刚被按下
386
+
387
+ Args:
388
+ button: 按钮索引
389
+
390
+ Returns:
391
+ 是否刚刚按下
392
+ """
393
+ return button in self.buttons_just_pressed
394
+
395
+ def is_button_just_released(self, button: int) -> bool:
396
+ """检查按钮是否刚刚被释放
397
+
398
+ Args:
399
+ button: 按钮索引
400
+
401
+ Returns:
402
+ 是否刚刚释放
403
+ """
404
+ return button in self.buttons_just_released
405
+
406
+ def get_axis(self, axis: int) -> float:
407
+ """获取摇杆轴的值
408
+
409
+ Args:
410
+ axis: 轴索引
411
+
412
+ Returns:
413
+ 轴值 (-1.0 到 1.0)
414
+ """
415
+ return self.axes.get(axis, 0.0)
416
+
417
+ def get_left_stick(self) -> Tuple[float, float]:
418
+ """获取左摇杆值
419
+
420
+ Returns:
421
+ (x, y) 摇杆值
422
+ """
423
+ return (self.axes.get(0, 0.0), self.axes.get(1, 0.0))
424
+
425
+ def get_right_stick(self) -> Tuple[float, float]:
426
+ """获取右摇杆值
427
+
428
+ Returns:
429
+ (x, y) 摇杆值
430
+ """
431
+ return (self.axes.get(2, 0.0), self.axes.get(3, 0.0))
432
+
433
+ def get_hat(self, hat: int = 0) -> Tuple[int, int]:
434
+ """获取方向帽值
435
+
436
+ Args:
437
+ hat: 帽子索引
438
+
439
+ Returns:
440
+ (x, y) 方向值 (-1, 0, 1)
441
+ """
442
+ return self.hats.get(hat, (0, 0))
443
+
444
+ def get_name(self) -> str:
445
+ """获取手柄名称"""
446
+ return self.joystick.get_name()
447
+
448
+ def rumble(self, low_freq: float, high_freq: float, duration: int):
449
+ """手柄震动(如果支持)
450
+
451
+ Args:
452
+ low_freq: 低频震动强度 (0.0-1.0)
453
+ high_freq: 高频震动强度 (0.0-1.0)
454
+ duration: 持续时间(毫秒)
455
+ """
456
+ try:
457
+ self.joystick.rumble(low_freq, high_freq, duration)
458
+ except:
459
+ # 某些手柄不支持震动
460
+ pass
461
+
462
+
463
+ class TouchHandler:
464
+ """触摸输入处理器"""
465
+
466
+ def __init__(self):
467
+ """初始化触摸处理器"""
468
+ self.touches: Dict[int, Tuple[int, int]] = {}
469
+ self.touches_just_started: Dict[int, Tuple[int, int]] = {}
470
+ self.touches_just_ended: List[int] = []
471
+
472
+ def update(self, events: List[pygame.event.Event]):
473
+ """更新触摸状态
474
+
475
+ Args:
476
+ events: pygame 事件列表
477
+ """
478
+ self.touches_just_started.clear()
479
+ self.touches_just_ended.clear()
480
+
481
+ for event in events:
482
+ if event.type == pygame.FINGERDOWN:
483
+ touch_id = event.finger_id
484
+ pos = (int(event.x * pygame.display.get_surface().get_width()),
485
+ int(event.y * pygame.display.get_surface().get_height()))
486
+ self.touches[touch_id] = pos
487
+ self.touches_just_started[touch_id] = pos
488
+ elif event.type == pygame.FINGERUP:
489
+ touch_id = event.finger_id
490
+ if touch_id in self.touches:
491
+ del self.touches[touch_id]
492
+ self.touches_just_ended.append(touch_id)
493
+ elif event.type == pygame.FINGERMOTION:
494
+ touch_id = event.finger_id
495
+ if touch_id in self.touches:
496
+ pos = (int(event.x * pygame.display.get_surface().get_width()),
497
+ int(event.y * pygame.display.get_surface().get_height()))
498
+ self.touches[touch_id] = pos
499
+
500
+ def is_touching(self) -> bool:
501
+ """检查是否有触摸"""
502
+ return len(self.touches) > 0
503
+
504
+ def get_touch_count(self) -> int:
505
+ """获取当前触摸点数量"""
506
+ return len(self.touches)
507
+
508
+ def get_touch_position(self, finger_id: int = 0) -> Optional[Tuple[int, int]]:
509
+ """获取触摸位置
510
+
511
+ Args:
512
+ finger_id: 手指 ID(默认为第一个触摸点)
513
+
514
+ Returns:
515
+ 触摸位置或 None
516
+ """
517
+ if finger_id in self.touches:
518
+ return self.touches[finger_id]
519
+
520
+ # 返回第一个触摸点
521
+ if self.touches:
522
+ return list(self.touches.values())[0]
523
+
524
+ return None
525
+
526
+ def get_all_touches(self) -> Dict[int, Tuple[int, int]]:
527
+ """获取所有触摸点
528
+
529
+ Returns:
530
+ {finger_id: position} 字典
531
+ """
532
+ return self.touches.copy()
533
+
534
+ def is_touch_just_started(self) -> bool:
535
+ """检查是否有新的触摸开始"""
536
+ return len(self.touches_just_started) > 0
537
+
538
+ def is_touch_just_ended(self) -> bool:
539
+ """检查是否有触摸结束"""
540
+ return len(self.touches_just_ended) > 0
541
+
542
+ def get_new_touches(self) -> Dict[int, Tuple[int, int]]:
543
+ """获取新开始的触摸
544
+
545
+ Returns:
546
+ {finger_id: position} 字典
547
+ """
548
+ return self.touches_just_started.copy()