Add a controllable player object that moves with WASD keys.
Every game you've ever played has a movement system. Press a button, character moves. But HOW does that actually work? It's simpler than you think — and today you'll build it yourself.
Video: 2D Movement in Unity — Brackeys (8 min)
Brackeys explains the fundamentals of player movement — input detection, position updates, and the game loop. Even though this uses Unity, the CONCEPT is identical to what you'll build in Three.js: read keyboard input, update position, render.
Discussion after watching: What are the three steps of movement? (1. Read input, 2. Update position, 3. Render.) Why does the game need to check for input EVERY frame, not just once?
Movement = Input → Update Position → Render. The player presses a key, the game updates the player's position in state, and the renderer shows the new position. This happens every frame.
Before writing any code, play this game to feel how keyboard input works.
Setup: One person is the "keyboard" (gives commands), the other is the "robot" (follows them exactly).
Rules:
- The "keyboard" person calls out single keys: W (forward), A (left), S (back), D (right).
- The "robot" takes ONE step in that direction for each call.
- Try to navigate the robot across the room to touch a specific object (a chair, a wall, a door).
- Then switch roles.
Round 2 — Continuous mode:
- Now the "keyboard" says "W DOWN" (start walking forward) and the robot keeps walking until they hear "W UP" (stop).
- This is exactly how
keydownandkeyupevents work in your code.
Key insight: Round 1 is like checking keypress events (one action per press). Round 2 is like tracking keydown/keyup state (smooth continuous movement). Your game uses Round 2 — that's why movement feels smooth instead of stuttery.
Player cube = Hero exploring Manhattan. The red cube represents your character moving through dangerous streets.
Player cube = Developer walking between lots. The red cube represents you surveying your construction sites.
Create the player mesh:
Track keyboard input with keydown/keyup:
Define movement speed and update position inside the animation loop:
Cube moves smoothly with WASD. Camera follows or stays appropriately angled.
No jumping. No sprinting. No collision detection. No diagonal speed normalization. Just basic 4-direction movement.
Movement speed too high — the player teleports across the screen instead of moving smoothly.
Forgetting to update position inside the animation loop — movement only happens once or not at all.
Not using keydown/keyup tracking — relying on keypress alone causes stuttering movement instead of smooth gliding.
The Human Robot game should come first. It builds physical intuition for something that's otherwise abstract. When they later write if (keys['w']), they'll remember being the robot walking forward — the code is just the written version of the game they played.
Let them play with movement speed. "What breaks if speed is 100?" The player teleports. "What about 0.001?" It barely moves. This teaches that values need tuning. Game feel is about finding the right numbers — not just making things "work."
The cube IS the player. No character model needed for v1. If they want to make it fancier, redirect: "That's a Week 4 polish item. Right now we're building the foundation."
If movement feels stuttery: Make sure they're using keydown/keyup tracking (the keys object) instead of relying on a single keypress event. The keys object lets the animation loop check state continuously — that's the difference between jerky and smooth.
Tomorrow: We build the world your player walks through — zones and lots. Right now the player moves over a blank plane. Tomorrow, that plane becomes a map with distinct areas.