Skip to content

Commit d78c915

Browse files
authored
Input Manager Finalization - Docs and Cleanup (#2822)
* Start work on input docs for 4.0 * Initial write-up of InputManager programming guide * small fix * some docstrings and cleanup * Handle input imports in top level package * Add helper method for combined positive/negative inputs to InputManager * Add basic sprite move example for InputManager * Fix __all__ * More docstrings for InputManager * InputManager updates for Pyglet 3.0 compatibility * Update sprite_move_input_manager example * Fix line lengths in example * More example formatting
1 parent b1aaa29 commit d78c915

10 files changed

Lines changed: 666 additions & 111 deletions

File tree

arcade/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,17 @@ def configure_logging(level: int | None = None):
145145
from .controller import ControllerManager
146146
from .controller import get_controllers
147147

148+
from .input import ActionState
149+
from .input import ControllerButtons
150+
from .input import ControllerSticks
151+
from .input import ControllerTriggers
152+
from .input import InputManager
153+
from .input import Keys
154+
from .input import MouseAxes
155+
from .input import MouseButtons
156+
from .input import PSControllerButtons
157+
from .input import XBoxControllerButtons
158+
148159
from .sound import Sound
149160
from .sound import load_sound
150161
from .sound import play_sound
@@ -249,6 +260,16 @@ def configure_logging(level: int | None = None):
249260
)
250261

251262
__all__ = [
263+
"ActionState",
264+
"ControllerButtons",
265+
"ControllerSticks",
266+
"ControllerTriggers",
267+
"InputManager",
268+
"Keys",
269+
"MouseAxes",
270+
"MouseButtons",
271+
"PSControllerButtons",
272+
"XBoxControllerButtons",
252273
"AStarBarrierList",
253274
"AnimatedWalkingSprite",
254275
"TextureAnimationSprite",

arcade/application.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ def on_mouse_press(self, x: int, y: int, button: int, modifiers: int) -> EVENT_H
680680
681681
modifiers:
682682
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
683-
active during this event. See :ref:`keyboard_modifiers`.
683+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
684684
"""
685685
pass
686686

@@ -705,7 +705,7 @@ def on_mouse_drag(
705705
Which button is pressed
706706
modifiers:
707707
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
708-
active during this event. See :ref:`keyboard_modifiers`.
708+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
709709
"""
710710
return self.on_mouse_motion(x, y, dx, dy)
711711

@@ -730,7 +730,7 @@ def on_mouse_release(self, x: int, y: int, button: int, modifiers: int) -> EVENT
730730
- ``arcade.MOUSE_BUTTON_MIDDLE``
731731
modifiers:
732732
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
733-
active during this event. See :ref:`keyboard_modifiers`.
733+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
734734
"""
735735
return EVENT_UNHANDLED
736736

@@ -831,7 +831,7 @@ def on_key_press(self, symbol: int, modifiers: int) -> EVENT_HANDLE_STATE:
831831
Key that was just pushed down
832832
modifiers:
833833
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
834-
active during this event. See :ref:`keyboard_modifiers`.
834+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
835835
"""
836836
return EVENT_UNHANDLED
837837

@@ -853,7 +853,7 @@ def on_key_release(self, symbol: int, modifiers: int) -> EVENT_HANDLE_STATE:
853853
symbol (int): Key that was released
854854
modifiers (int): Bitwise 'and' of all modifiers (shift,
855855
ctrl, num lock) active during this event.
856-
See :ref:`keyboard_modifiers`.
856+
See :ref:`pg_simple_input_keyboard_modifiers`.
857857
"""
858858
return EVENT_UNHANDLED
859859

@@ -1440,7 +1440,7 @@ def on_mouse_press(self, x: int, y: int, button: int, modifiers: int) -> bool |
14401440
14411441
modifiers:
14421442
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
1443-
active during this event. See :ref:`keyboard_modifiers`.
1443+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
14441444
"""
14451445
pass
14461446

@@ -1465,7 +1465,7 @@ def on_mouse_drag(
14651465
Which button is pressed
14661466
_modifiers:
14671467
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
1468-
active during this event. See :ref:`keyboard_modifiers`.
1468+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
14691469
"""
14701470
self.on_mouse_motion(x, y, dx, dy)
14711471
return False
@@ -1492,7 +1492,7 @@ def on_mouse_release(self, x: int, y: int, button: int, modifiers: int) -> bool
14921492
14931493
modifiers:
14941494
Bitwise 'and' of all modifiers (shift, ctrl, num lock)
1495-
active during this event. See :ref:`keyboard_modifiers`.
1495+
active during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
14961496
"""
14971497
pass
14981498

@@ -1547,7 +1547,7 @@ def on_key_press(self, symbol: int, modifiers: int) -> bool | None:
15471547
Key that was just pushed down
15481548
modifiers:
15491549
Bitwise 'and' of all modifiers (shift, ctrl, num lock) active
1550-
during this event. See :ref:`keyboard_modifiers`.
1550+
during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
15511551
"""
15521552
return False
15531553

@@ -1570,7 +1570,7 @@ def on_key_release(self, symbol: int, modifiers: int) -> bool | None:
15701570
Key that was released
15711571
modifiers:
15721572
Bitwise 'and' of all modifiers (shift, ctrl, num lock) active
1573-
during this event. See :ref:`keyboard_modifiers`.
1573+
during this event. See :ref:`pg_simple_input_keyboard_modifiers`.
15741574
"""
15751575
return False
15761576

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
"""
2+
Move Sprite With Keyboard or Controller using InputManager
3+
4+
Simple program to show moving a sprite with the keyboard or controller via InputManager.
5+
This is similar to the behavior in sprite_move_controller and sprite_move_keyboard
6+
but combining the devices using Arcade's advanced input system.
7+
8+
Artwork from https://kenney.nl
9+
10+
If Python and Arcade are installed, this example can be run from the command line with:
11+
python -m arcade.examples.sprite_move_input_manager
12+
"""
13+
14+
import arcade
15+
16+
SPRITE_SCALING = 0.5
17+
18+
WINDOW_WIDTH = 1280
19+
WINDOW_HEIGHT = 720
20+
WINDOW_TITLE = "Move Sprite with InputManager Example"
21+
22+
MOVEMENT_SPEED = 5
23+
24+
25+
class Player(arcade.Sprite):
26+
27+
def update(self, delta_time: float = 1/60):
28+
""" Move the player """
29+
# Move player.
30+
# Remove these lines if physics engine is moving player.
31+
self.center_x += self.change_x
32+
self.center_y += self.change_y
33+
34+
# Check for out-of-bounds
35+
if self.left < 0:
36+
self.left = 0
37+
elif self.right > WINDOW_WIDTH - 1:
38+
self.right = WINDOW_WIDTH - 1
39+
40+
if self.bottom < 0:
41+
self.bottom = 0
42+
elif self.top > WINDOW_HEIGHT - 1:
43+
self.top = WINDOW_HEIGHT - 1
44+
45+
46+
class GameView(arcade.View):
47+
"""
48+
Main application class.
49+
"""
50+
51+
def __init__(self):
52+
"""
53+
Initializer
54+
"""
55+
56+
# Call the parent class initializer
57+
super().__init__()
58+
59+
# Set our controller to None, this will get changed if we find a connected controller
60+
controller = None
61+
62+
# Ask arcade for a list of connected controllers
63+
controllers = arcade.get_controllers()
64+
if controllers:
65+
# Just use the first one in the list for now
66+
controller = controllers[0]
67+
68+
# Create a new InputManager, and assign our controller to it(if we have one)
69+
self.input_manager = arcade.InputManager(controller)
70+
71+
# Add a new horizontal movement axis to the input manager.
72+
# Also assign the LEFT/RIGHT arrow keys and left thumbstick to it
73+
self.input_manager.new_axis("MoveHorizontal")
74+
self.input_manager.add_axis_input_combined(
75+
"MoveHorizontal",
76+
arcade.Keys.RIGHT,
77+
arcade.Keys.LEFT
78+
)
79+
self.input_manager.add_axis_input("MoveHorizontal", arcade.ControllerSticks.LEFT_STICK_X)
80+
81+
# Same thing for vertical movement axis
82+
self.input_manager.new_axis("MoveVertical")
83+
self.input_manager.add_axis_input_combined(
84+
"MoveVertical",
85+
arcade.Keys.UP,
86+
arcade.Keys.DOWN
87+
)
88+
self.input_manager.add_axis_input("MoveVertical", arcade.ControllerSticks.LEFT_STICK_Y)
89+
90+
# Variables that will hold sprite lists
91+
self.player_list = None
92+
93+
# Set up the player info
94+
self.player_sprite = None
95+
96+
# Set the background color
97+
self.background_color = arcade.color.AMAZON
98+
99+
def setup(self):
100+
""" Set up the game and initialize the variables. """
101+
102+
# Sprite lists
103+
self.player_list = arcade.SpriteList()
104+
105+
# Set up the player
106+
self.player_sprite = Player(
107+
":resources:images/animated_characters/female_person/femalePerson_idle.png",
108+
scale=SPRITE_SCALING,
109+
)
110+
self.player_sprite.center_x = 50
111+
self.player_sprite.center_y = 50
112+
self.player_list.append(self.player_sprite)
113+
114+
def on_draw(self):
115+
""" Render the screen. """
116+
117+
# Clear the screen
118+
self.clear()
119+
120+
# Draw all the sprites.
121+
self.player_list.draw()
122+
123+
def on_update(self, delta_time):
124+
""" Movement and game logic """
125+
126+
# Update the input manager so it has the latest values from our devices
127+
self.input_manager.update()
128+
129+
# Apply the input axes to the player
130+
self.player_sprite.change_x = self.input_manager.axis("MoveHorizontal") * MOVEMENT_SPEED
131+
self.player_sprite.change_y = self.input_manager.axis("MoveVertical") * MOVEMENT_SPEED
132+
133+
# Call update to move the sprite
134+
# If using a physics engine, call update player to rely on physics engine
135+
# for movement, and call physics engine here.
136+
self.player_list.update(delta_time)
137+
138+
139+
def main():
140+
""" Main function """
141+
# Create a window class. This is what actually shows up on screen
142+
window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
143+
144+
# Create and setup the GameView
145+
game = GameView()
146+
game.setup()
147+
148+
# Show GameView on screen
149+
window.show_view(game)
150+
151+
# Start the arcade game loop
152+
arcade.run()
153+
154+
155+
if __name__ == "__main__":
156+
main()

arcade/input/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# type: ignore
33

44
from .inputs import (
5-
ControllerAxes,
65
ControllerButtons,
6+
ControllerSticks,
7+
ControllerTriggers,
78
XBoxControllerButtons,
89
PSControllerButtons,
910
Keys,
@@ -14,8 +15,9 @@
1415
from .input_mapping import Action, ActionMapping, Axis, AxisMapping
1516

1617
__all__ = [
17-
"ControllerAxes",
1818
"ControllerButtons",
19+
"ControllerSticks",
20+
"ControllerTriggers",
1921
"XBoxControllerButtons",
2022
"PSControllerButtons",
2123
"Keys",

arcade/input/inputs.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class InputType(Enum):
1616
MOUSE_BUTTON = 1
1717
MOUSE_AXIS = 2
1818
CONTROLLER_BUTTON = 3
19-
CONTROLLER_AXIS = 4
19+
CONTROLLER_AXIS_SINGLE = 4
20+
CONTROLLER_AXIS_DOUBLE = 5
2021

2122

2223
class InputEnum(Enum):
@@ -39,19 +40,14 @@ def _generate_next_value_(name, *_):
3940
return name
4041

4142

42-
class ControllerAxes(StrEnum):
43-
LEFT_STICK_X = "leftx"
44-
LEFT_STICK_POSITIVE_X = "leftxpositive"
45-
LEFT_STICK_NEGATIVE_X = "leftxnegative"
46-
LEFT_STICK_Y = "lefty"
47-
LEFT_STICK_POSITIVE_Y = "leftypositive"
48-
LEFT_STICK_NEGATIVE_Y = "leftynegative"
49-
RIGHT_STICK_X = "rightx"
50-
RIGHT_STICK_POSITIVE_X = "rightxpositive"
51-
RIGHT_STICK_NEGATIVE_X = "rightxnegative"
52-
RIGHT_STICK_Y = "righty"
53-
RIGHT_STICK_POSITIVE_Y = "rightypositive"
54-
RIGHT_STICK_NEGATIVE_Y = "rightynegative"
43+
class ControllerSticks(StrEnum):
44+
LEFT_STICK_X = "leftstickx"
45+
LEFT_STICK_Y = "leftsticky"
46+
RIGHT_STICK_X = "rightstickx"
47+
RIGHT_STICK_Y = "rightsticky"
48+
49+
50+
class ControllerTriggers(StrEnum):
5551
LEFT_TRIGGER = "lefttrigger"
5652
RIGHT_TRIGGER = "righttrigger"
5753

@@ -366,15 +362,17 @@ class MouseButtons(InputEnum):
366362
MouseButtons: InputType.MOUSE_BUTTON,
367363
MouseAxes: InputType.MOUSE_AXIS,
368364
ControllerButtons: InputType.CONTROLLER_BUTTON,
369-
ControllerAxes: InputType.CONTROLLER_AXIS,
365+
ControllerTriggers: InputType.CONTROLLER_AXIS_SINGLE,
366+
ControllerSticks: InputType.CONTROLLER_AXIS_DOUBLE,
370367
}
371368

372369
INPUT_TYPE_TO_CLASS: dict[InputType, type[InputEnum]] = {
373370
InputType.KEYBOARD: Keys,
374371
InputType.MOUSE_BUTTON: MouseButtons,
375372
InputType.MOUSE_AXIS: MouseAxes,
376373
InputType.CONTROLLER_BUTTON: ControllerButtons,
377-
InputType.CONTROLLER_AXIS: ControllerAxes,
374+
InputType.CONTROLLER_AXIS_SINGLE: ControllerTriggers,
375+
InputType.CONTROLLER_AXIS_DOUBLE: ControllerSticks,
378376
}
379377

380378

0 commit comments

Comments
 (0)