Menu
CoddyTech

Zusammenstoß

Teil des Abschnitts Spielregeln der Pygame-Journey von Coddy. Lektion 27 von 29.

Wenn du ein Hindernis berührst, ist der Lauf zu Ende. pygame.sprite.spritecollideany(sprite, group) gibt das erste Sprite in der Gruppe zurück, das das Sprite berührt, oder None.

Standardmäßig werden die Rechtecke verglichen. Die Bilder haben durchsichtige Ecken, vor allem der Blob, sodass sich zwei Rechtecke überschneiden können, obwohl sich nichts Sichtbares berührt. Ein drittes Argument wählt einen genaueren Test aus:

if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
    state = "over"

collide_mask vergleicht die gezeichneten Pixel der Bilder und ignoriert die durchsichtigen. Ein Zusammenstoß ist dann ein Zusammenstoß, den der Spieler sehen kann.

Der Zustand funktioniert wie in Meteor Dodge: Aktualisieren, Springen und neue Hindernisse finden nur statt, während der Zustand "play" ist, und der Game-Over-Bildschirm zeigt das eingefrorene Spiel mit einer Nachricht an.

challenge icon

Aufgabe

Mittel
  1. Füge eine Schriftart assets/fonts/pixel.ttf in Größe 32 und state = "play" hinzu.
  2. Nur während der Zustand "play" ist: Springe, füge Hindernisse hinzu und aktualisiere den Läufer und die Hindernisse.
  3. Wenn der Läufer ein Hindernis berührt (collide_mask), setze den Zustand auf "over".
  4. Wenn das Spiel vorbei ist, zeige Game over in (40, 50, 80) zentriert bei (320, 140) an.

Probier es selbst

import random
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
SPAWN = pygame.USEREVENT + 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]


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 = [
    pygame.image.load("assets/images/spike_ball.png").convert_alpha(),
    pygame.image.load("assets/images/blob.png").convert_alpha(),
]
runner = Runner()
obstacles = pygame.sprite.Group()
speed = 6
pygame.time.set_timer(SPAWN, 1500)

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()
        if event.type == SPAWN:
            obstacles.add(Obstacle())
            pygame.time.set_timer(SPAWN, random.randint(1000, 2000))

    runner.update()
    obstacles.update()

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

pygame.quit()

Alle Lektionen in Spielregeln

Übe selbstständig: Pygame-Playground