Menu
CoddyTech

Ein patrouillierender Blob

Teil des Abschnitts Spielwelten der Pygame-Journey von Coddy. Lektion 24 von 35.

Zwei Blobs laufen nach rechts und weiter in die Luft. Ein patrouillierender Gegner läuft hin und her: Er dreht um, wenn er eine Wand berührt oder das Ende seines Bodens erreicht. Die Klasse Blob speichert ihre direction, 1 für rechts und -1 für links.

Prüfe nach jedem Schritt den Punkt ein Pixel vor dem vorderen Fuß des Blobs, auf Höhe seiner Füße. Wenn an diesem Punkt keine Wand Halt bietet, würde der nächste Schritt in die Luft führen:

if self.direction > 0:
    ahead = self.rect.right
else:
    ahead = self.rect.left - 1
hit_wall = any(self.rect.colliderect(wall) for wall in walls)
ground_ahead = any(wall.collidepoint(ahead, self.rect.bottom) for wall in walls)
if hit_wall or not ground_ahead:
    self.rect.x -= self.direction
    self.direction = -self.direction

any(...) ist True, wenn mindestens eine Wand den Test besteht. Durch das Umdrehen wird der Schritt rückgängig gemacht und die Richtung umgekehrt. Das Rect des Blobs passt zu seinem Körper: 30 × 26, kleiner als das 48 Pixel große Bild, das mit seiner unteren Mitte auf der unteren Mitte des Rect gezeichnet wird.

challenge icon

Aufgabe

Schwer

In Blob.update, nach dem Schritt:

  1. Setze ahead beim Bewegen nach rechts auf self.rect.right, andernfalls auf self.rect.left - 1.
  2. Prüfe, ob sich der Blob mit einer Wand überschneidet und ob eine Wand den Punkt (ahead, self.rect.bottom) enthält.
  3. Wenn er eine Wand berührt hat oder sich vor ihm kein Boden befindet, mache den Schritt rückgängig und kehre self.direction um.

Probier es selbst

import pygame

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

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

pygame.init()
screen = pygame.display.set_mode((576, 360))
pygame.display.set_caption("Patrol")
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()
blob_img = pygame.image.load("assets/images/blob.png").convert_alpha()


class Blob(pygame.sprite.Sprite):
    def __init__(self, midbottom):
        super().__init__()
        self.image = blob_img
        self.rect = pygame.Rect(0, 0, 30, 26)
        self.rect.midbottom = midbottom
        self.direction = 1

    def update(self):
        self.rect.x += self.direction

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)

blobs = pygame.sprite.Group(Blob((432, 144)), Blob((432, 324)))
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
    for wall in walls:
        if player.colliderect(wall):
            if dx > 0:
                player.right = wall.left
            elif dx < 0:
                player.left = wall.right

    vel_y = min(vel_y + GRAVITY, MAX_FALL)
    player.y += vel_y
    on_ground = False
    for wall in walls:
        if player.colliderect(wall):
            if vel_y > 0:
                player.bottom = wall.top
                on_ground = True
            elif vel_y < 0:
                player.top = wall.bottom
            vel_y = 0

    blobs.update()

    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)
    for blob in blobs:
        screen.blit(blob.image, blob.image.get_rect(midbottom=blob.rect.midbottom))
    screen.blit(player_img, player)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Spielwelten

Übe selbstständig: Pygame-Playground