Create your own
Lesson illustration

Move the Player with Keyboard Input in JavaScript

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:

  • true when the chosen key is being held down
  • false when 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 playerX values move right.
  • Smaller playerX values move left.
  • Larger playerY values move down.
  • Smaller playerY values move up.

That reversed-looking vertical direction is normal for screen coordinates: the top of the canvas has .

A p5.js key shown with the W, A, S, and D keys, the four-key layout used to control the dungeon player in this lesson.

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.

keyIsDown

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 movementKey to testPosition 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.

  1. If A is not held, keyIsDown('KeyA') is false, so the code between the braces is skipped.
  2. If A is held, the condition is true, so the code subtracts playerSpeed from playerX.
  3. The player is drawn at that new x-position later in the same frame.
  4. 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:

  • 1 for a careful, slow explorer
  • 3 for the current pace
  • 6 for 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: true or false.
  • An if statement runs movement code only when its condition is true.
  • playerX controls left and right movement; playerY controls up and down movement.
  • Four separate checks allow multiple held keys, including diagonal movement.
  • playerSpeed is 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