Menu
CoddyTech

Walls Left and Right

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

The blocks are drawn, but the player walks through them. A wall must stop the player. Move first, then fix the move: if the player now overlaps a wall, push it back out on the side it came from.

player.x += dx
for wall in walls:
    if player.colliderect(wall):
        if dx > 0:
            player.right = wall.left
        elif dx < 0:
            player.left = wall.right

dx is this frame's sideways move: positive to the right. Moving right, the player hit the wall's left side, so its right edge goes there. Moving left, its left edge goes to the wall's right side.

The map is built into walls, a list of Rects, the same way as in Maps from Text. The floor is still the line at FLOOR, and the player can still fall into the top of a block: landing on walls comes next.

challenge icon

Challenge

Medium
  1. After player.x += dx, loop over walls.
  2. For each wall the player collides with: when dx > 0, set player.right = wall.left; when dx < 0, set player.left = wall.right.

Try it yourself

import pygame

TILE = 36
SPEED = 4
GRAVITY = 1
JUMP = -15
MAX_FALL = 12
FLOOR = 324

LEVEL = [
    "................",
    "................",
    "................",
    "................",
    "................",
    "................",
    "................",
    "#..........##..#",
    "#.P..#.....##..#",
    "################",
]

pygame.init()
screen = pygame.display.set_mode((576, 360))
pygame.display.set_caption("Walls")
clock = pygame.time.Clock()

background = pygame.image.load("assets/backgrounds/clouds.png").convert_alpha()
block_img = pygame.image.load("assets/images/block.png").convert_alpha()
player_img = pygame.image.load("assets/images/player.png").convert_alpha()

walls = []
for row, line in enumerate(LEVEL):
    for col, char in enumerate(line):
        if char == "#":
            walls.append(pygame.Rect(col * TILE, row * TILE, TILE, TILE))
        elif char == "P":
            start = (col * TILE + TILE // 2, row * TILE + TILE)

player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
            if on_ground:
                vel_y = JUMP
        elif event.type == pygame.KEYUP and event.key in (pygame.K_SPACE, pygame.K_UP):
            if vel_y < -4:
                vel_y = -4

    keys = pygame.key.get_pressed()
    dx = 0
    if keys[pygame.K_LEFT]:
        dx -= SPEED
    if keys[pygame.K_RIGHT]:
        dx += SPEED

    player.x += dx

    vel_y = min(vel_y + GRAVITY, MAX_FALL)
    player.y += vel_y
    on_ground = False
    if player.bottom > FLOOR:
        player.bottom = FLOOR
        vel_y = 0
        on_ground = True

    for y in range(0, 360, 72):
        for x in range(0, 576, 72):
            screen.blit(background, (x, y))
    for wall in walls:
        screen.blit(block_img, wall)
    screen.blit(player_img, player)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

All lessons in Worlds

Practice on your own: Pygame playground