# Input and Movement drive a node from the keyboard with input actions. ```{raw} html ▶ Run in browser ``` **Tags:** `tutorial` `beginner` `input` # Input and Movement Now make something move when the player presses a key. SimVX does not ask you to check raw key codes scattered through your game. Instead you name an **action** ("move_right") and bind keys to it once; your gameplay reads the action. Rebinding keys or adding a gamepad later never touches the movement code. By the end you will drive a square around the window with WASD or the arrow keys. ## Step 1: Declare the actions on the root node Put an `input_actions` dictionary at class scope on your root node. Each action name maps to a list of bindings (here, two keys each): ```python class MovementDemo(Node2D): input_actions = { "move_left": [Key.A, Key.LEFT], "move_right": [Key.D, Key.RIGHT], "move_up": [Key.W, Key.UP], "move_down": [Key.S, Key.DOWN], } ``` > **Why the class attribute, not `main()`?** SimVX registers `input_actions` when > the scene starts, before the first frame. Registering actions inside `main()` > works on the desktop but is **silently skipped by the web export** (which never > runs `main()`), so your web build would have no input. The class attribute is > the one path that works everywhere. ## Step 2: Read the actions and move `Input.get_strength(action)` returns how hard an action is held, from 0 to 1. It reads identically for a key (0 or 1) or a gamepad axis (anything between), so the same line of code handles both. Subtract opposite directions to get a signed axis: ```python class Player(Node2D): SPEED = 360.0 def on_update(self, dt): dx = Input.get_strength("move_right") - Input.get_strength("move_left") dy = Input.get_strength("move_down") - Input.get_strength("move_up") self.position += Vec2(dx, dy) * self.SPEED * dt ``` ## Step 3: Stay frame-rate independent Multiplying by `dt` (seconds since the last frame) is what keeps the speed the same on a 60 fps and a 144 fps machine. Never add a fixed amount per frame: the game would run faster on faster hardware. ## Run it ```bash uv run python examples/tutorials/input_and_movement/main.py ``` ## What's next - **Bouncing Balls** -- `Property` descriptors and spawning many children. - **Pong** -- put input, signals, and collision together into a full game. ## Source ```{literalinclude} ../../examples/tutorials/input_and_movement/main.py :language: python :linenos: ```