๐Ÿ My First Python Game ยท Episode 2 of 7 ยท See All Episodes
๐Ÿƒ Episode 2 ยท Beginner ยท Builds on Episode 1

Jump Around!
Simple Platformer

Gravity, jumping and platforms, build a Mario-style level in Pygame. You will learn velocity physics, landing detection and level design with a list of platforms.

๐Ÿ‘ถ Ages 10+ โฑ๏ธ ~1.5 Hours ๐Ÿ Python โœ“ Free
๐ŸŒ Gravity ๐Ÿฆ˜ Jumping ๐Ÿงฑ Platforms ๐Ÿ“‹ Lists ๐Ÿ’ฅ Landing detection ๐Ÿ† Goal & win
โญ
0 XP
Level 1
๐Ÿ”ฅ0
Your Progress 0 / 6 steps
๐Ÿงฉ
Need the game setup? Each episode builds a new game on the same "usual template", import pygameimport pygame, pygame.init()pygame.init(), the window and the while runningwhile running game loop. If you're starting here or need that template, grab it in one click: Episode 1 full template โ†’ ยท Python Cheatsheet โ†’
1
๐Ÿงฐ
Project Setup & Player
New game.py with a movable player square
Active
๐ŸŽฏ
Goal for this step

Set up the standard Pygame template with a player that moves left and right.

  • 1New folder, new game.py, same template as Episode 1 (800ร—480 window, clock, loop).
  • 2The player is a Rect: player = pygame.Rect(100, 380, 34, 44).
  • 3Arrow keys move ยฑ5 per frame using key.get_pressed(), you know this from Episode 1!
  • 4Draw the player orange. Run it and slide around.
game.py
player = pygame.Rect(100, 380, 34, 44)
speed = 5

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    player.x -= speed
if keys[pygame.K_RIGHT]:
    player.x += speed

pygame.draw.rect(screen, (255, 119, 0), player)player = pygame.Rect(100, 380, 34, 44)
speed = 5

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    player.x -= speed
if keys[pygame.K_RIGHT]:
    player.x += speed

pygame.draw.rect(screen, (255, 119, 0), player)
๐Ÿ“ฆ Full starter file , the Episode 1 pygame template

The standard 800ร—480 window, the clock and the while runningwhile running game loop. Save it as game.pygame.py and run it: a dark window opens. Every step below adds to this same file.

game.py
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 480))
pygame.display.set_caption("My Python Game")
clock = pygame.time.Clock()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((25, 30, 60))      # everything you build below is drawn here
    pygame.display.flip()
    clock.tick(60)                 # 60 frames per second

pygame.quit()import pygame
pygame.init()
screen = pygame.display.set_mode((800, 480))
pygame.display.set_caption("My Python Game")
clock = pygame.time.Clock()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    screen.fill((25, 30, 60))      # everything you build below is drawn here
    pygame.display.flip()
    clock.tick(60)                 # 60 frames per second

pygame.quit()
โœ๏ธ
Fill in the Blanks
+15 XP
A pygame. stores x, y, width and height in one object. We reuse the game loop template from Episode .
๐Ÿง 
Knowledge Check
+15 XP
The second and third numbers in Rect(100, 380, 34, 44) areโ€ฆ
Ay position, then width
Bwidth and height only
CBoth x positions
2
๐ŸŒ
Gravity & Velocity
A vy variable pulls the player down every frame
Locked
๐ŸŽฏ
Goal for this step

Make the player fall naturally with accelerating gravity.

  • 1Add vy = 0 (vertical velocity) and on_ground = False.
  • 2Every frame: vy += 1 (gravity), then player.y += vy.
  • 3Temporary floor: if the player passes y 480, snap back and zero the velocity.
  • 4Falling starts slow and speeds up, that is acceleration, the thing that makes jumps feel real.
game.py
vy = 0
on_ground = False

# inside the loop:
vy += 1              # gravity
player.y += vy

if player.bottom >= 480:      # temporary floor
    player.bottom = 480
    vy = 0
    on_ground = Truevy = 0
on_ground = False

# inside the loop:
vy += 1              # gravity
player.y += vy

if player.bottom >= 480:      # temporary floor
    player.bottom = 480
    vy = 0
    on_ground = True
๐Ÿ’ก
player.bottom is a Rect superpower, it reads AND sets the bottom edge, no maths needed.
โœ๏ธ
Fill in the Blanks
+15 XP
Gravity adds 1 to each frame, and vy is added to player.. Landing sets vy back to .
๐Ÿง 
Knowledge Check
+15 XP
Why does the fall get faster and faster?
APygame speeds up over time
Bvy grows every frame, so each frame moves the player further, acceleration
CThe floor attracts the player
3
๐Ÿฆ˜
Jumping
Launch upward with a negative velocity, only from the ground
Locked
๐ŸŽฏ
Goal for this step

Add a jump with a proper arc, and stop mid-air double jumps.

  • 1Jumping is one line: set vy = -16. Gravity does the rest of the arc.
  • 2Use a KEYDOWN event (a jump is a single press, not a held key).
  • 3Guard it with on_ground, and set on_ground = False when you launch.
  • 4Tune it: -20 is a moon jump, -12 is a hop. Pick your feel.
game.py
# in the event loop:
if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_SPACE and on_ground:
        vy = -16
        on_ground = False# in the event loop:
if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_SPACE and on_ground:
        vy = -16
        on_ground = False
โŒจ๏ธ
Code Challenge
+20 XP
Write the guarded jump:
game.py
if event.key == pygame.K_SPACE and if event.key == pygame.K_SPACE and :
    vy = :
    vy = 
    on_ground = 
    on_ground = 
๐Ÿ’ก Hint: Only jump while standing on something; launch is a negative velocity; and you are airborne immediately after.
๐Ÿง 
Knowledge Check
+15 XP
Movement uses get_pressed() but jumping uses a KEYDOWN event. Why?
ASpace bar only works with events
BRunning is continuous (held key); a jump is one action per press, different input styles for different actions
CEvents are faster
4
๐Ÿงฑ
Platforms
A list of Rects, drawn and landed on
Locked
๐ŸŽฏ
Goal for this step

Build the level from a list of platforms and land on top of them.

  • 1The level is just a list: platforms = [Rect(...), Rect(...), ...], a ground strip plus floating ledges.
  • 2Replace the temporary floor with a loop over platforms.
  • 3Land only when FALLING onto the top: vy > 0 and the playerโ€™s bottom was above the platform last frame.
  • 4Draw every platform green. Then redesign the layout, it is your level!
game.py
platforms = [
    pygame.Rect(0, 440, 800, 40),
    pygame.Rect(150, 340, 140, 16),
    pygame.Rect(380, 260, 140, 16),
    pygame.Rect(610, 180, 140, 16),
]

on_ground = False
for plat in platforms:
    if player.colliderect(plat) and vy > 0 \
            and player.bottom - vy <= plat.top:
        player.bottom = plat.top
        vy = 0
        on_ground = True

for plat in platforms:
    pygame.draw.rect(screen, (6, 214, 160), plat)platforms = [
    pygame.Rect(0, 440, 800, 40),
    pygame.Rect(150, 340, 140, 16),
    pygame.Rect(380, 260, 140, 16),
    pygame.Rect(610, 180, 140, 16),
]

on_ground = False
for plat in platforms:
    if player.colliderect(plat) and vy > 0 \
            and player.bottom - vy <= plat.top:
        player.bottom = plat.top
        vy = 0
        on_ground = True

for plat in platforms:
    pygame.draw.rect(screen, (6, 214, 160), plat)
โœ๏ธ
Fill in the Blanks
+15 XP
The level lives in a Python of Rects. We only land when vy > , which means the player is moving .
๐Ÿง 
Knowledge Check
+15 XP
What happens without the vy > 0 check?
APlatforms disappear
BJumping up through a platform would snap you on top of it instantly, teleport jumps
CNothing changes
5
โญ
Coins & Score
Collect stars scattered over the platforms
Locked
๐ŸŽฏ
Goal for this step

Scatter collectables and count them with an on-screen score.

  • 1Coins are a list of small Rects placed above each ledge.
  • 2Loop with a copy, for coin in coins[:], so removing while looping is safe.
  • 3On collision: remove the coin, score += 1.
  • 4Draw coins gold, score top-left, exactly like Episode 1.
game.py
coins = [pygame.Rect(205, 300, 18, 18),
         pygame.Rect(435, 220, 18, 18),
         pygame.Rect(665, 140, 18, 18)]
score = 0

for coin in coins[:]:          # loop over a COPY
    if player.colliderect(coin):
        coins.remove(coin)
        score += 1coins = [pygame.Rect(205, 300, 18, 18),
         pygame.Rect(435, 220, 18, 18),
         pygame.Rect(665, 140, 18, 18)]
score = 0

for coin in coins[:]:          # loop over a COPY
    if player.colliderect(coin):
        coins.remove(coin)
        score += 1
โš ๏ธ
Removing items from a list you are looping over skips items, the [:] copy avoids that classic bug.
โŒจ๏ธ
Code Challenge
+20 XP
Collect coins safely while looping:
game.py
for coin in coinsfor coin in coins]:
    if player.colliderect(coin):
        coins.]:
    if player.colliderect(coin):
        coins.(coin)
        score += 1(coin)
        score += 1
๐Ÿ’ก Hint: Slice the whole list to loop over a copy, then delete the coin from the real list.
๐Ÿง 
Knowledge Check
+15 XP
What does coins[:] create?
AA copy of the list to loop over, so removing from the original is safe
BAn empty list
CThe first coin only
6
๐Ÿ†
The Goal & Falling Off
A flag to win, a pit to lose, and a restart
Locked
๐ŸŽฏ
Goal for this step

Finish the level with a win flag, a falling-off respawn, and polish.

  • 1Add a gold flag Rect on the highest platform. Touch it with all coins collected โ†’ YOU WIN.
  • 2If player.top > 480 (fell into a pit), respawn at the start.
  • 3Draw win text with the big font; freeze movement once won.
  • 4Stretch goals: a moving platform (give one platform its own vx and bounce it between two x values), or a second level list.
game.py
flag = pygame.Rect(660, 130, 16, 50)
won = False

if not won:
    # ... all update code ...
    if player.colliderect(flag) and len(coins) == 0:
        won = True
    if player.top > 480:            # fell off!
        player.x, player.y = 100, 380
        vy = 0

if won:
    msg = big_font.render("YOU WIN!", True, (255, 209, 102))
    screen.blit(msg, (250, 190))flag = pygame.Rect(660, 130, 16, 50)
won = False

if not won:
    # ... all update code ...
    if player.colliderect(flag) and len(coins) == 0:
        won = True
    if player.top > 480:            # fell off!
        player.x, player.y = 100, 380
        vy = 0

if won:
    msg = big_font.render("YOU WIN!", True, (255, 209, 102))
    screen.blit(msg, (250, 190))
โœ๏ธ
Fill in the Blanks
+15 XP
The win needs two things: touching the AND len(coins) == . Falling past the bottom respawns the player at the .
๐Ÿง 
Knowledge Check
+15 XP
Why require all coins before the flag works?
AFlags need fuel
BIt gives the level a goal beyond "walk right", players must explore every platform
CPygame requires it
โœ… See the complete finished Platformer , all 6 steps assembled

Player movement, gravity, jumping, a list of platforms, collectable coins, a win flag and a fall-off respawn , one file. Save it as game.pygame.py, run python game.pypython game.py, and play. Stuck on a step? Compare your file against this.

game.py
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 480))
pygame.display.set_caption("Sky Hopper")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 32)
big_font = pygame.font.SysFont(None, 72)

player = pygame.Rect(100, 380, 34, 44)
speed = 5
vy = 0
on_ground = False

platforms = [
    pygame.Rect(0, 440, 800, 40),      # ground
    pygame.Rect(150, 340, 140, 16),
    pygame.Rect(380, 260, 140, 16),
    pygame.Rect(610, 180, 140, 16),
]
coins = [pygame.Rect(205, 300, 18, 18),
         pygame.Rect(435, 220, 18, 18),
         pygame.Rect(665, 140, 18, 18)]
flag = pygame.Rect(660, 130, 16, 50)
score = 0
won = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and on_ground and not won:
                vy = -16
                on_ground = False

    if not won:
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            player.x -= speed
        if keys[pygame.K_RIGHT]:
            player.x += speed
        if player.left < 0:
            player.left = 0
        if player.right > 800:
            player.right = 800

        vy += 1                 # gravity
        player.y += vy

        on_ground = False
        for plat in platforms:
            if player.colliderect(plat) and vy > 0 and player.bottom - vy <= plat.top:
                player.bottom = plat.top
                vy = 0
                on_ground = True

        for coin in coins[:]:            # loop over a COPY
            if player.colliderect(coin):
                coins.remove(coin)
                score += 1

        if player.colliderect(flag) and len(coins) == 0:
            won = True

        if player.top > 480:             # fell into a pit
            player.x, player.y = 100, 380
            vy = 0

    # draw
    screen.fill((25, 30, 60))
    for plat in platforms:
        pygame.draw.rect(screen, (6, 214, 160), plat)
    for coin in coins:
        pygame.draw.rect(screen, (255, 209, 102), coin)
    pygame.draw.rect(screen, (247, 160, 30), flag)
    pygame.draw.rect(screen, (255, 119, 0), player)
    screen.blit(font.render("Score: " + str(score), True, (255, 255, 255)), (12, 12))
    if won:
        msg = big_font.render("YOU WIN!", True, (255, 209, 102))
        screen.blit(msg, (250, 190))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()import pygame
pygame.init()
screen = pygame.display.set_mode((800, 480))
pygame.display.set_caption("Sky Hopper")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 32)
big_font = pygame.font.SysFont(None, 72)

player = pygame.Rect(100, 380, 34, 44)
speed = 5
vy = 0
on_ground = False

platforms = [
    pygame.Rect(0, 440, 800, 40),      # ground
    pygame.Rect(150, 340, 140, 16),
    pygame.Rect(380, 260, 140, 16),
    pygame.Rect(610, 180, 140, 16),
]
coins = [pygame.Rect(205, 300, 18, 18),
         pygame.Rect(435, 220, 18, 18),
         pygame.Rect(665, 140, 18, 18)]
flag = pygame.Rect(660, 130, 16, 50)
score = 0
won = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and on_ground and not won:
                vy = -16
                on_ground = False

    if not won:
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            player.x -= speed
        if keys[pygame.K_RIGHT]:
            player.x += speed
        if player.left < 0:
            player.left = 0
        if player.right > 800:
            player.right = 800

        vy += 1                 # gravity
        player.y += vy

        on_ground = False
        for plat in platforms:
            if player.colliderect(plat) and vy > 0 and player.bottom - vy <= plat.top:
                player.bottom = plat.top
                vy = 0
                on_ground = True

        for coin in coins[:]:            # loop over a COPY
            if player.colliderect(coin):
                coins.remove(coin)
                score += 1

        if player.colliderect(flag) and len(coins) == 0:
            won = True

        if player.top > 480:             # fell into a pit
            player.x, player.y = 100, 380
            vy = 0

    # draw
    screen.fill((25, 30, 60))
    for plat in platforms:
        pygame.draw.rect(screen, (6, 214, 160), plat)
    for coin in coins:
        pygame.draw.rect(screen, (255, 209, 102), coin)
    pygame.draw.rect(screen, (247, 160, 30), flag)
    pygame.draw.rect(screen, (255, 119, 0), player)
    screen.blit(font.render("Score: " + str(score), True, (255, 255, 255)), (12, 12))
    if won:
        msg = big_font.render("YOU WIN!", True, (255, 209, 102))
        screen.blit(msg, (250, 190))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
๐ŸŽ‰๐Ÿ†๐ŸŽฎโœจ๐ŸŽ‰
Workshop Complete!
Real platformer physics in Python, gravity, jump arcs and landing. Episode 3 turns up the chaos with Dodge & Collect!
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
โ–ถ Episode 3: Dodge & Collect โ†’
โญ View My Progress & Certificates

This workshop was free and took many hours to build. If it helped you learn something new, consider supporting the project.

☕ Support on Ko-fi