Guide

How to move a character with a joystick

You add a joystick, you press Play, you push the stick — and your character stands there. This is the most common first-game question we get, and the answer is always the same. The joystick doesn't move anything. It sits on the screen publishing numbers, and nothing reads them until you write one small formula. This guide writes that formula, then builds a world big enough to walk around in.

The mistake almost everyone makes

You add Move (Velocity) and type numbers into linear x and linear y — say 150 and 150. Numbers never change. So the block says "always go down-right", no matter which way you push. The joystick is never consulted. Whatever you type there, the character can only ever move one direction.

What the joystick actually gives you

While the stick is held, it publishes four numbers you can use anywhere a value is accepted. The first part of each name is the joystick's own variable name — joystick unless you rename it.

NumberRangeWhat it means
joystick_value_x-1 to 1How far left or right you're pushing
joystick_value_y-1 to 1How far up or down you're pushing
joystick_distance0 to 1How far from the centre — a light push or a hard one
joystick_angleradiansThe direction as an angle, handy for aiming

Step 1: a character that can move

Physics moves your character, so it needs a body. Without one nothing you write will have any effect at all.

  1. Add a Sprite object and name it player. Give every object a real name — two objects called "new game object" is how scripts end up on the wrong one.
  2. Add a Rigid Body. Set Body Type to dynamic, Gravity Scale to 0, and turn Fixed Rotation on.
  3. Add a Box Collider roughly the size of the sprite.
Why those three settings

dynamic because Move (Velocity) is skipped entirely on a static body — nothing happens and no error appears. Gravity Scale 0 because this is a top-down world and nothing should fall. Fixed Rotation because the first corner your character clips would otherwise spin it forever.

Step 2: add the joystick

  1. Open UI Components in the scene panel.
  2. Add a Joystick and pick Left Side.
  3. Leave its variable name as joystick.

Press Play and you'll see the thumbstick. Push it — nothing moves yet, and that's expected. You've added the dial; you haven't wired it to anything.

Step 3: the formula that connects them

This step is the whole guide. On the player object, open the Scripts tab and build this:

  1. Add On Play. It runs every frame, so the joystick gets re-read constantly.
  2. Add Move (Velocity) and connect On Play to it.
  3. Next to linear x, tap the small arrow and choose Expression solver.
  4. Build joystick_distance * joystick_value_x * 260. The joystick values are in the variables list — tap them rather than typing, so you can't misspell one.
  5. Do the same for linear y, using joystick_value_y.
FieldWhat goes in it
linear xjoystick_distance * joystick_value_x * 260
linear yjoystick_distance * joystick_value_y * 260

Press Play. Your character walks in any direction you push — not four directions, any direction — and a half-pushed stick walks while a full push runs. That last part is what joystick_distance buys you, and it's why this is one formula instead of a pile of If blocks.

A number is a constant. An expression is a live reading.

This is the idea worth taking away. Typing 150 into a field fixes it forever. The Expression solver is how a block reads something that changes while the game runs — a joystick, a score, a countdown. Once you've used it here, every other block in Max2D opens up the same way.

One catch: a field holds an expression or a number, never both. Setting an expression clears the number, and typing a number clears the expression.

You don't need a minus sign

Max2D flips the up/down value for you before it reaches your expression, so joystick_value_y already matches the way you're pushing. If your character goes up when you push down, you've added a minus that isn't needed.

Step 4: let the camera follow

Make your world bigger than the screen — a large ground sprite, some trees and rocks — and the character will walk straight off the edge of the view. Fix that in one field:

  1. Open Scene Camera in the scene panel.
  2. Type player into Follow Object. The spelling has to match the object's name exactly.
  3. Set Deadzone to about 0.18.

Deadzone is how far the character may drift before the world starts scrolling. At 0 the camera is welded to the sprite and every step shoves the whole world, which feels seasick. A small deadzone lets small movements happen without the background lurching.

Step 5: keep the score on the screen

Add a Text object for a score and you'll notice it scrolls away with the world. The rule behind that is simple, and it's worth knowing early:

ObjectWhere it lives
Has a Rigid BodyIn the world. The camera moves past it.
No Rigid BodyOn the screen. It ignores the camera and stays put.

So: no Rigid Body on anything you want pinned as a HUD, and a Rigid Body on everything that should stay planted in the world — including scenery that never moves.

Step 6: something to collect

Walking around is not yet a game. Give it a point:

  1. Make a number variable called score.
  2. Add a gem: a Sprite with a Rigid Body set to static with Is Sensor on, and a Box Collider. A sensor lets the player walk through it instead of bouncing off, and still registers the touch.
  3. On the gem, add On Collision Enter and set the object to player.
  4. Connect it to Set variable: score = score + 1.
  5. Connect that to Destroy object.
  6. Copy the gem a few times and scatter the copies.

Putting the collision on the gem rather than the player means each gem cleans itself up, and nothing has to keep a list of how many gems exist.

To show the score, add a Text object with no Rigid Body, then On PlaySet text with score in its box.

Set text takes a variable name, not a sum

The box on Set text is matched against your variable names — it is not worked out like an expression. score works. score + 1 does not, and fails quietly. To show a fixed message instead, type it into the block's text field rather than the expression box.

The blocks you used

BlockJob
On PlayRuns every frame, so the joystick is re-read constantly
Move (Velocity)Turns the joystick numbers into movement
On Collision EnterFires when the player touches a gem
Set variableAdds one to the score
Destroy objectRemoves the collected gem
Set textShows the score on screen
If (True/False)Checks whether every gem has been found

When it doesn't behave

What you seeWhat's wrong
Character doesn't move at allPlain numbers in linear x and linear y instead of an expression. Or no Rigid Body on the character — Move (Velocity) is skipped on a static body and says nothing.
Moves, but always the same directionSame cause: the fields hold constants. Check they read {expression} and not a number.
Script is on the wrong objectTwo objects named "new game object". Rename everything before you script it.
Keeps sliding after you let goYou used the Joystick Move event instead of On Play. If the release is ever missed, nothing sets the speed back to zero. On Play re-reads every frame, so letting go always stops.
Up and down are invertedA minus sign on joystick_value_y that isn't needed — Max2D already flips it.
Character spins when it hits somethingFixed Rotation is off.
Camera ignores the characterThe name in Follow Object doesn't match the object's name exactly.
Score text scrolls away with the worldIt has a Rigid Body. Remove it.
Scenery slides around as you walkThe opposite problem — scenery with no Rigid Body is drawn on the screen, not in the world. Give it a static body.
Gem blocks you instead of being collectedIs Sensor is off on the gem's Rigid Body.

Try it: Explorer

The example project is this guide finished: a world about three screens wide, eight gems to find, trees and rocks that block you, and a camera that follows. Open the player object to read the movement formula, and any gem to see the three-block collect chain. Every script has a note beside it explaining what it does.

Change the 260 in the player's expression to change the walking speed. Change the Deadzone on the Scene Camera to make the camera hug tighter or hang back.

Get the example project

Download Explorer.zip (3.9 KB)

In Max2D: ProjectsImport Project → pick the zip. Play it in landscape.

Frequently asked questions

Why doesn't my character move when I use the joystick?

Almost always because Move (Velocity) has plain numbers in linear x and linear y. Numbers never change, so the block pushes the same way whichever direction you hold. Open the next to the field, choose Expression solver, and build joystick_distance * joystick_value_x * 260. The other common cause is a character with no Rigid Body, or one set to static — Move (Velocity) is skipped on a static body and nothing happens at all.

How do I add a joystick in Max2D?

Open UI Components in the scene panel, add a Joystick, and pick Default, Left Side or Right Side. That puts the thumbstick on screen — it doesn't move anything by itself, it only publishes numbers your blocks can read.

What are joystick_value_x and joystick_distance?

The numbers the joystick publishes while it's held. joystick_value_x and joystick_value_y are the direction, -1 to 1 on each axis. joystick_distance is how far you've pushed, 0 to 1. Multiply all three together and you get direction and speed at once. The prefix is the joystick's variable name, so one named stick gives you stick_value_x.

Do I need to flip the y value for up and down?

No — Max2D flips it before it reaches your expression. If your character moves up when you push down, you've added a minus sign that isn't needed.

How do I make the camera follow my character?

Open Scene Camera and type the character's name into Follow Object — spelling must match exactly. Deadzone below it sets how far it can drift before the world scrolls; a small amount feels far calmer than a camera welded to the sprite.

Why does my score text slide off the screen?

It has a Rigid Body. An object with a body lives in the world and the camera moves past it; an object with no body is drawn onto the screen and stays put. Remove the body from anything you want pinned, and add one to anything that should stay planted in the world.

One formula, and your character walks.

Build it tonight on your phone. Max2D is free on Google Play.

Free onGoogle Play