Document stub.png This article or section may not have content matching Scratch Wiki editing standards. Please improve it according to Scratch Wiki:Guidelines and Scratch Wiki:Editing Conventions. (November 2019)
Reason: Unprofessional, more description needed
This article is about how to make a scrolling platformer. For a basic platformer tutorial, see How to Make a Basic Platformer. For advanced platformer physics, see Advanced Platformer Physics.

This article is a step-by-step process about how to make a Scrolling Platformer. A scrolling platformer is a type of platformer where the camera follows the player as they move through the level(s).

Coding the Player

To code the movement of the player, the following scripts need to be made. All scripts in this section are to go in the 'Player' sprite.

Note Note: Variables in caps (e.g. "SCROLL X" and "SCROLL Y") are global variables, and those lowercase (e.g. "x" and "y") are made with the "For this sprite only" option selected.
When green flag clicked
broadcast (Green Flag v) and wait//A way to only need 1 flag block. Flag blocks create lag, so the fewer the better.
broadcast (Play Game v) and wait//Broadcasts to the other sprites that the game has started

When I receive [Play game v]
forever
broadcast (Reset v) and wait
    broadcast (Set Up v) and wait
    Game On::custom//sets up the variables
    repeat until <(EXIT)>()>//means the player has either died or won
        broadcast (Tick v)
    end
    if <(EXIT)=(win)> then
        Win::custom
    else
        Die::custom//if the player had not won, they would've had to have died
    end

define Position
go to x:((x)-(SCROLL X)) y: ((y) - (SCROLL Y)

define Game On//Run without screen refresh
point in direction (90)
set size to (100)%
clear graphic effects
set [in air v] to (0)
set rotation style [left-right v]
set [sy v] to (0)
set [x v] to (0)
set [y v] to (0)
set [EXIT v] to () // Nothing
set [SCROLLL X v] to (0)
set [SCROLLL Y v] to (0)
show

When I receive [Tick v]
broadcast (Ready v)
Tick <key (Right arrow v) pressed?> <key (Up arrow v) pressed?> <key (Left arrow v) pressed?>::custom//checks if a key has been pressed

define Tick <right> <up> <left>
if <left> then//If the left key was pressed, it moves the player left
    Change player X by [-8]::custom
end
if <right> then//If the right key was pressed, it moves the player right
    Change player X by [8]::custom
end
if <<up> and <(in air)< (4)>> then//If the up key was pressed, it checks if they are in the air still, if they are not, it makes the player jump
    set [sy v] to (16)
end
change [sy v] by (-1)//Gravity,set it to any negative number
Change player Y by (sy)::custom//Actually moves the player's Y position
Test dying::custom//Checks if the player has hit a danger sprite
if <(SCROLL X)<(0)> then
    set [SCROLL X v] to (0)
end
if <(SCROLL Y)<(0)> then
    set [SCROLL Y v] to (0)
end
change [SCROLL Y v] by (round(((y)-(SCROLL Y))/(10)))
change [SCROLL X v] by (round(((x)-(SCROLL X))/(5)))
Position::custom//Positions the player's location correctly
if <(y position) < (-180)> then//If the player has fallen into the abyss
    set [EXIT v] to [die]
end

define Change player X by (sx)//Moves the player's X axis
if <(sx::custom)<(0)> then//If the player is moving left
    point in direction (-90)//They point left
else
    point in direction (90)//They point right
end
change [x v] by (sx::csutom)//Changes the X variable by the amount of movement needed (sx)
Position::custom//Positions the player
if <touching (platforms v) ?> then//Will check if the player has hit a wall, or a slope
    repeat (12)//Will check if the wall/slope in question is 12 pixels steep or not
        change [y v] by (1)//Moves the player up 1 pixel
        Position::custom//Positions the player
        if <not<touching (platforms v) ?>> then//Then, that means it was a slope, so we can stop trying
            stop [this script v]
        end
    end
    change [y v] by (-12)//Corrects for the 12 that was used above
    repeat until <not<touching (platforms v)?>>
        if <(sx)>(0)> then
            change [x v] by (-1)
        else
            change [x v] by (1)
        end
        Position::custom
    end
end

define Change player Y by (sy)
change [y v] by (sy::custom)
change [in air v] by (1)
Position::custom
repeat until <not<touching (platforms v)?>>
    if <(sy::custom)>(0)> then
        change [y v] by (-1)
    else
        change [y v] by (1)
        set [in air v] to (0)
    end
    set [sy v] to (0)
    Position::custom
end

define Test dying
if <touching (Danger v)?> then
    set [EXIT v] to [die]
end

define Die
set [EXIT v] to ()//nothing
repeat (4)
    hide
    wait (0.1) seconds
    show
end
wait (0.5) seconds

define Win
set rotation style [don't rotate v]
repeat (50)
    point towards (Portal v)
    turn cw (65) degrees
    move ((distance to (Portal v))/(2)) steps
    change size by (-1)
    change [ghost v] effect by (2)
end
hide
change [LEVEL v] by (1)
wait (1) seconds
clear graphic effects
set rotation style [left-right v]

Coding the Platforms Sprite

Once the player's code has been completed, code for the ground sprite (called 'platforms' here) needs to be added in order to create a scrolling effect. The following scripts go in the 'platforms' sprite.

when I receive [Tick v]
Position ((x)-(SCROLL X)) ((y) - (SCROLL Y)
when I receive [Green flag v]
show

define Position (x) (y)
go to x: (x::custom) y: (y::custom)
if <<(x::custom)= (x position)> and <(y::custom) = (y position)>> then
    show
else
    hide
end

When I receive [Setup v]
set [x v] to (0)
set [y v] to (0)
if <(LEVEL)=(1)> then
    switch costume to (Level 1 1)
    Clone (450) (0) // This clones a new level. This needs to be done as many times as the number of levels. In this case, 3 is used as an example.
    Clone (450) (0)
    Clone (450) (0)
else
    ...::grey // If there is another scene then it should be cloned here using another if else block.
end

define Clone (x) (y)
create clone of (myself v)
change [x v] by (x::custom)
change [y v] by (y::custom)
next costume

Coding the Danger Sprite

To code the danger sprite simply duplicate the "platforms" sprite and replace all the levels with only the dangerous elements that would hurt the player.

Note Note: Make sure to call the danger sprite "danger" because the script above already makes the player sense for a sprite of that name.
when I receive [Tick v]
position ((x)-(SCROLL X))((y)-(SCROLL Y))::custom

when I receive [Green flag v]
show

when I receive [Reset v]
delete this clone

define Position (x) (y)
go to x: (x::custom) y: (y::custom)
if <<(x::custom)= (x position)> and <(y::custom) = (y position)>> then
    show
else
    hide
end

when I receive [Setup v]
set [x v] to (0)
set [y v] to (0)
if <(LEVEL)=(1)> then
    switch costume to (Level 1 1)
    Clone (450) (0) // This clones a new level, do this as many times as the number of levels, in this case 3 is used as an example.
    Clone (450) (0)
    Clone (450) (0)
else
    ...::grey // If there is another scene then it should be cloned here using another if else block.
end

define Clone (x) (y)
create clone of (myself v)
change [x v] by (x::custom)
change [y v] by (y::custom)
next costume

Coding the Portal

Now that everything is made, a way to go to the next level needs to be made.

When I receive [Tick v]
Position ((x)-(SCROLL X)) (((y) - (SCROLL Y)) + ((([sin v] of (timer)) *(100))*(20)))::custom
if <<(costume [number v]) = (2)> and <touching (player v)?>> then
    set [EXIT v] to [win]
end

When I receive [Setup v]
set [x v] to (0)
set [y v] to (0)
if <(LEVEL)=(1)> then
    switch costume to (Level 1 1)
    Position Portal at (450) (180)::custom
else
    ...::grey // If there is another scene than the portal needs to be positioned here using another if else block.
end

define Position Portal at (x) (y)
set [x v] to (x::custom)
set [y v] to (y::custom)

define Position (x) (y)
go to x: (x::custom) y: (y::custom)
if <<(x::custom)= (x position)> and <(y::custom) = (y position)>> then
    show
else
    hide
end

Adding Collectibles

Collectibles can be added to the game to make it more interesting. They are objects that need to be collected in order to achieve a certain goal. The code to make them is shown below:

When I receive [Tick v]
Position ((x)-(SCROLL X)) (((y) - (SCROLL Y)) + ((([sin v] of (timer)) *(300))*(5)))::custom
if <touching (player v)?> then
    change [COLLECTED v] by (1)
    if <(COLLECTED)=(COLLECTED MAX)> then
        broadcast (Open portal v)
        start sound (All coins collected v)
    else
        start sound (Collect v)
    end
    delete this clone
end

When I receive [Green flag v]
show

when [m v] key pressed
set [MOUSE v] to (join ((mouse x) + (SCROLL X))(join [,]((mouse y) + (SCROLL Y))))

When I receive [Reset v]
delete this clone

define Position (x) (y)
go to x: (x::custom) y: (y::custom)
if <<(x::custom)= (x position)> and <(y::custom) = (y position)>> then
    show
else
    hide
end

When I receive [Setup v]
set [x v] to (0)
set [y v] to (0)
if <(LEVEL)=(1)> then
    Clone (450) (180)::custom
else
    ...::grey // If there is another scene than coins need to be cloned here using another if else block.
end

define Clone (x) (y)
set [x v] to (x::custom)
set [y v] to (y::custom)
create clone of (myself v)
change [COLLECTED MAX v] by (1)

Transforming a Basic Platformer

Often, Scratchers make basic platformers before they make a scrolling platformer, and they may want to use their old script to make a scrolling platformer. To do this, the "ground" sprite would move with the player. Making a script to do this is simple:

when green flag clicked//This goes in the player sprite.
forever
Scroll (((0) - (x position)) * (0.8)) (((-40) - (y position)) * (0.8))//0 and -40 are the desired x and y positions of the player.
...//The basic platformer script goes here.
end

define Scroll (x) (y)//This goes in the player sprite.
change [level x v] by (round (x))//Round the variables so the level moves correctly.
change [level y v] by (round (y))
change x by (round (x))//When the level moves, the player must move with it.
change y by (round (y))

when green flag clicked//This goes in the ground sprite.
forever
go to x:(level x) y:(level y)
end

See Also