Menu
CoddyTech

Run and Jump

Part of the Worlds section of Coddy's Pygame journey. Lesson 29 of 35.

Now the explorer moves, with everything from Gravity and Jumping and Platform Collisions, in this order every frame:

  1. Read the arrows into dx, move along x, push out of walls.
  2. Add gravity up to MAX_FALL, move along y, land or bump the head, and set on_ground.
  3. If the player fell below the window, put it back at start.

The jump starts on a KEYDOWN of Space or Up when on_ground, and a KEYUP cuts a fast rise to -4 for short hops.

Add the speed constants at the top: SPEED = 4, GRAVITY = 1, JUMP = -15, MAX_FALL = 12. With these numbers a jump rises about 100 pixels: enough for a step of two tiles and to clear a pit of two.

challenge icon

Challenge

Medium
  1. Add the four constants and, before the loop, vel_y = 0 and on_ground = False.
  2. In the events: jump on Space or Up when on_ground; on KEYUP of either, cut vel_y to -4 when it is below -4.
  3. Each frame: move and fix x, then move and fix y as in Bump Your Head.
  4. When player.top > HEIGHT, set player.midbottom = start and vel_y = 0.

Try it yourself

import pygame

TILE = 36
WIDTH, HEIGHT = 576, 360

LEVEL = [
    "................................................................",
    "................................................................",
    "................................................................",
    "................................................................",
    "#..............................................................#",
    "#....................C.........................#####...........#",
    "#......CC...C................CC.....CC.........#####.....CC....#",
    "#....................#.........................D...............#",
    "#.P.........#...E....#...^.......K......E......D.C....^......F.#",
    "#######..####################..##########################..#####",
]

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Moss Caves")
clock = pygame.time.Clock()


def load(name):
    return pygame.image.load("assets/images/" + name).convert_alpha()


background = pygame.image.load("assets/backgrounds/forest.png").convert_alpha()
grass_img = load("grass.png")
grass_left_img = load("grass_left.png")
grass_right_img = load("grass_right.png")
dirt_img = load("dirt.png")
player_img = load("player.png")


def solid(row, col):
    if row < 0 or row >= len(LEVEL) or col < 0 or col >= len(LEVEL[0]):
        return False
    return LEVEL[row][col] == "#"


walls = []
tiles = []
for row, line in enumerate(LEVEL):
    for col, char in enumerate(line):
        rect = pygame.Rect(col * TILE, row * TILE, TILE, TILE)
        if char == "#":
            if solid(row - 1, col):
                image = dirt_img
            elif not solid(row, col - 1) and solid(row, col + 1):
                image = grass_left_img
            elif solid(row, col - 1) and not solid(row, col + 1):
                image = grass_right_img
            else:
                image = grass_img
            walls.append(rect)
            tiles.append((image, rect))
        elif char == "P":
            start = rect.midbottom

player = player_img.get_rect(midbottom=start)

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

    for y in range(0, HEIGHT, 72):
        for x in range(0, WIDTH, 72):
            screen.blit(background, (x, y))
    for image, rect in tiles:
        screen.blit(image, rect)
    screen.blit(player_img, player)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

All lessons in Worlds

Practice on your own: Pygame playground