Hello again. In the last lesson, the dungeon player moved automatically because draw() repeatedly added playerSpeed to playerX. Now you will replace that automatic motion with player input: your code will check whether a key is currently held down and change the position only then.
By the end of this lesson, your p5.js dungeon explorer will move with W, A, S, and D. This is the same basic control pattern used in many keyboard games: read input during each frame, update the game state, then draw the updated world. Plan on about 35–40 minutes.
Input is another part of the game loop
Your sketch already repeats draw() many times per second. In each repetition, it can ask a question such as:
“Is the player holding the W key right now?”
p5.js provides keyIsDown() for exactly this. It returns one of the Boolean values you met earlier:
truewhen the chosen key is being held downfalsewhen it is not
For example:
keyIsDown('KeyW')
This expression checks the physical W key. It does not move anything on its own; it only gives your program information. To make movement happen, place that check inside an if statement:
if (keyIsDown('KeyW')) {
playerY = playerY - playerSpeed;
}
Read it as: “If W is held, decrease the player’s y-position by the player speed.”
The result is upward movement because p5.js coordinates begin at the canvas’s top-left corner:
- Larger
playerXvalues move right. - Smaller
playerXvalues move left. - Larger
playerYvalues move down. - Smaller
playerYvalues move up.
That reversed-looking vertical direction is normal for screen coordinates: the top of the canvas has .

Learn the p5.js input check
The official p5.js reference uses the same “check a key while draw() repeats” approach. It also shows why independently checking keys matters when a player holds two keys for diagonal movement.
Read the official p5.js reference entry to see the exact meaning of keyIsDown() and a compact example using movement keys.
In the opening explanation of the keyIsDown() reference, read the explanation and example. Focus on the fact that the function reports the key's current state, rather than merely remembering the last key pressed. Then scan the Syntax, Parameters, and Returns section: keyIsDown() needs the name of a key and produces a Boolean result.
The names in this lesson use keyboard codes:
| Desired movement | Key to test | Position change |
|---|---|---|
| Up | 'KeyW' | decrease playerY |
| Left | 'KeyA' | decrease playerX |
| Down | 'KeyS' | increase playerY |
| Right | 'KeyD' | increase playerX |
The quotes are essential. 'KeyW' is text—a JavaScript string that names the key. KeyW without quotes would mean something entirely different to JavaScript and cause an error.
Turn the automatic player into a controllable player
Return to your p5.js editor. In the code from the last lesson, remove this automatic movement line:
playerX = playerX + playerSpeed;
Then replace the full sketch with the version below. It keeps your dungeon room and player artwork, but adds an Input section at the start of draw().
// Dungeon game state
let playerName = "Quest Runner";
let playerHealth = 3;
let hasDungeonKey = false;
// Player position and movement speed
let playerX = 300;
let playerY = 200;
let playerSpeed = 3;
function setup() {
createCanvas(600, 400);
}
function draw() {
// Read keyboard input and update the player position.
if (keyIsDown('KeyW')) {
playerY = playerY - playerSpeed;
}
if (keyIsDown('KeyA')) {
playerX = playerX - playerSpeed;
}
if (keyIsDown('KeyS')) {
playerY = playerY + playerSpeed;
}
if (keyIsDown('KeyD')) {
playerX = playerX + playerSpeed;
}
// Redraw the dungeon floor.
background(18, 21, 31);
// Stone walls
fill(63, 54, 75);
stroke(109, 92, 126);
strokeWeight(3);
rect(0, 0, 600, 28);
rect(0, 372, 600, 28);
rect(0, 0, 28, 400);
rect(572, 0, 28, 400);
// Draw the player.
fill(95, 204, 180);
stroke(220, 255, 245);
strokeWeight(2);
circle(playerX, playerY, 30);
// Draw the player's sword.
stroke(245, 215, 120);
strokeWeight(4);
line(playerX + 8, playerY, playerX + 21, playerY - 13);
}
Press Play, then click once inside the running canvas before using the keys. Clicking gives the sketch focus, so it can receive your keyboard input. Hold W, A, S, or D and confirm that the player moves in the expected direction.
For now, your player can still walk through walls or leave the room. That is not a failure: keeping the player inside the playable area is a separate rule you will add soon.
What each movement block does
Look closely at the left-movement block:
if (keyIsDown('KeyA')) {
playerX = playerX - playerSpeed;
}
Each frame, p5.js evaluates the condition inside the parentheses.
- If A is not held,
keyIsDown('KeyA')isfalse, so the code between the braces is skipped. - If A is held, the condition is
true, so the code subtractsplayerSpeedfromplayerX. - The player is drawn at that new x-position later in the same frame.
- On the next frame, the check happens again. Holding the key makes many small position changes, which appear as smooth motion.
The other keys use the same pattern. Only the variable and whether the value increases or decreases change.
You may also see this shorter form in games:
playerX -= playerSpeed;
It has the same effect as:
playerX = playerX - playerSpeed;
For the moment, the longer form is more useful because it makes the arithmetic clear.
Why these are four separate if statements
You might be tempted to write one long choice:
if (keyIsDown('KeyW')) {
playerY = playerY - playerSpeed;
} else if (keyIsDown('KeyD')) {
playerX = playerX + playerSpeed;
}
That code creates a limitation: if W and D are held together, only the first matching branch runs. The player would move up but not right.
Instead, this lesson uses four independent checks. Each key gets a chance to affect the player during the current frame:
if (keyIsDown('KeyW')) {
playerY = playerY - playerSpeed;
}
if (keyIsDown('KeyD')) {
playerX = playerX + playerSpeed;
}
Now hold W and D together. Both conditions are true, so playerY decreases and playerX increases in the same frame. Your player moves diagonally toward the upper-right.
This is why keyIsDown() is well suited to movement controls: it checks the current state of each key, including more than one key at once. A “last key pressed” value would not reliably remember both W and D.
One small detail to notice: diagonal movement covers more distance per frame than movement in one direction because both position values change. That is acceptable for your first controller. More advanced games can normalize diagonal speed, but that is unnecessary while you are building the core mechanics.
Tune and test your controller
Your movement speed remains a variable near the top of the sketch:
let playerSpeed = 3;
Try a few values, pressing Stop and Play after each change:
1for a careful, slow explorer3for the current pace6for a very fast player
Changing the variable changes every movement direction consistently. You do not need to hunt through four separate blocks and replace numbers.
Use this brief playtest checklist:
- Hold each of W, A, S, and D separately; the player should move in the correct direction.
- Hold W and D together; the player should travel diagonally upward and right.
- Release all keys; the player should stop immediately.
- Check that the sword remains attached to the moving player.
- If nothing moves, click inside the canvas and try again.
If the player moves in the wrong direction, inspect the relevant line. For example, W must subtract from playerY, while S must add to it.
Key takeaways
You have changed your automatic animation into player-controlled movement:
keyIsDown('KeyW')checks whether a named key is currently held.keyIsDown()returns a Boolean value:trueorfalse.- An
ifstatement runs movement code only when its condition is true. playerXcontrols left and right movement;playerYcontrols up and down movement.- Four separate checks allow multiple held keys, including diagonal movement.
playerSpeedis one named value that controls how quickly the player moves.
Next, you will use conditionals for a different game purpose: changing what happens based on the game’s state, not just based on a movement key.
Can't find a good explanation? Sign up and we'll make it for you
Sign up