Menu
CoddyTech

Obstacles

Part of the Game Rules section of Coddy's Pygame journey. Lesson 26 of 29.

Now something to jump over. An obstacle is a sprite that starts a little past the right edge, on the ground, and moves left:

class Obstacle(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = random.choice(obstacle_images)
        self.rect = self.image.get_rect(midbottom=(664, GROUND_Y))

    def update(self):
        self.rect.x -= speed
        if self.rect.right < 0:
            self.kill()

obstacle_images holds the spike ball and the blob, loaded once, so each obstacle picks a picture without reading a file. kill() takes a sprite out of every group it is in, so obstacles that leave on the left are forgotten.

Keep them in a group: obstacles.update() moves them all and obstacles.draw(screen) draws them all. A timer adds them. Each time it fires, start it again with a random gap, so the player cannot jump to a rhythm:

if event.type == SPAWN:
    obstacles.add(Obstacle())
    pygame.time.set_timer(SPAWN, random.randint(1000, 2000))

The runner cannot hit them yet. That comes next.

challenge icon

Challenge

Medium
  1. Add SPAWN = pygame.USEREVENT + 1, speed = 6 and a list obstacle_images with spike_ball.png and blob.png.
  2. Write the Obstacle sprite as shown.
  3. Make a group named obstacles and start the SPAWN timer at 1500 ms.
  4. On SPAWN, add an obstacle and restart the timer with random.randint(1000, 2000).
  5. Update and draw the group every frame.

Try it yourself

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()

SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1


class Runner(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.frames = [
            pygame.image.load("assets/images/player.png").convert_alpha(),
            pygame.image.load("assets/images/player_walk.png").convert_alpha(),
        ]
        self.image = self.frames[0]
        self.step = 0
        self.rect = self.image.get_rect(midbottom=(100, GROUND_Y))
        self.vy = 0

    def jump(self):
        if self.rect.bottom == GROUND_Y:
            self.vy = -16

    def update(self):
        self.vy += GRAVITY
        self.rect.y += self.vy
        if self.rect.bottom >= GROUND_Y:
            self.rect.bottom = GROUND_Y
            self.vy = 0
        if self.rect.bottom == GROUND_Y:
            self.step += 1
            self.image = self.frames[self.step // 8 % 2]
        else:
            self.image = self.frames[1]


runner = Runner()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
            runner.jump()

    runner.update()

    screen.fill(SKY)
    pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
    screen.blit(runner.image, runner.rect)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Game Rules

Practice on your own: Pygame playground