A platformer is a type of game distinguished by jumping across platforms and avoiding obstacles. In order to make the game realistic, more advanced scripting must be used.

Note Note: This tutorial is geared towards users who already have intermediate knowledge of Scratch. For those new to Scratch, How to Make a Basic Platformer can be used instead.

Gravity

Main article: Simulating Gravity

The most basic gravity script works like this:

if <touching [ground v]?> then
change y by (10)
else
change y by (-10)
end

However, this causes the player to:

  1. Move at a fixed speed
  2. Jitter when it touches the ground
A more realistic gravity script as follows:
set [speed y v] to [0]
forever
change [speed y v] by [-1] //this can be -0.5 if you wish to have low gravity
change y by (speed y)
check ground touch //this pulls the player out of the ground

define check ground touch
//make sure this is "run without screen refresh"
repeat until <not<touching [ground v]?>>
change y by (1)
end 

This allows the sprite to fall faster and faster, like in real life.

Jumping

Main article: Jumping

Jumping is as easy as this:

if <key [space v] pressed?> then
if <not<touching [ground v]?>> then //this is so you can't fly up
set [speed y v] to [15] //can be any value, test different numbers

Ceiling Detection

Let's add to our "check ground touch" block:
define check ground touch
if <(speed y) < [0] > then
repeat until <not<touching [ground v]?>>
change y by (1)
end
else
set [speed y v] to [0]
end

That way, if the player is going up and hit a platform, the scripts don't push it through the platform, and instead it stops going up and falls back down.

So the final scripts are:
when gf clicked
forever
change [speed y v] by [-1]
change y by (speed y)
check ground touch
if <key [space v] pressed?> then
if <not<touching [ground v]?>> then
set [speed y v] to [15]
end
end
if <key [left v] pressed?> then //the moving script
change x by (-4)
end
if <key [right v] pressed?> then //ditto
change x by (4)
end

define check ground touch
if <(speed y) < [0] > then
repeat until <not<touching [ground v]?>>
change y by (1)
end
else
set [speed y v] to [0]
end

Wall Detection

The "check ground touch" block causes the player to walk up walls. To get rid of this, make a new custom block called move:

define move (distance :: custom)
//this is also "run without screen refresh"
change x by (distance :: custom)
set [slope v] to [0] //new variable
repeat until <<(slope) > [8]> or <not <touching [ground v]>>>
change y by (1)
change [slope v] by [1]
end
if <(slope) > [8]> then
change x by ((0)-(distance :: custom)
change y by ((0)-(slope)
end
Every time the player left or right, it checks if the slope is higher than 8 (basically, if it moves you more than 8 units), if it is, it moves you back. Replace the "change x by ()" blocks with two of these.

Hitboxes

If your player, avatar, etc. has arms, they will catch on the platforms (if your player is a smooth rectangle you can skip this). The answer to that is a hitbox. Create a new costume for your sprite and make it a filled rectangle about the size of your normal costume (the one it's showing). Then update your scripts like this:
when gf clicked
forever
switch costume to [hitbox v]
... //other scripts
switch costume to [regular v]
end

Walking Momentum

To simulate momentum, it needs a gliding effect - after you stop pressing the left/right key, it "glides" to a stop instead of stopping right away. First, update the "move" block - replace the "change x" block with a "change speed x" block

define move (dist)
change [speed x v] by (dist) //replace with this
... //the other scripts

Then, after the "check ground touch" block, add:

when gf clicked
forever
switch costume to [hitbox v]
change [speed y v] by [-1]
change y by (speed y)
check ground touch::custom
set [speed x v] to ((speed x)*(0.8)) //add this!
change x by (speed x) //and this!
...
end

What this does is slowly (but not too slowly) speed up when you are pressing the key, and slowly lose speed when you let go.