Menu
CoddyTech

Sicher nach einem Treffer

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

Stell dich in dieser Version unter einen Felsen. Der Felsen springt nach einem Treffer nicht mehr nach oben zurück, fällt durch den Spieler hindurch und berührt den Spieler viele Frames hintereinander. Jeder dieser Frames kostet ein Leben, also beendet ein Felsen das Spiel.

Viele Spiele gewähren nach einem Treffer eine kurze Schutzzeit. Um zu erfahren, wie viel Zeit vergangen ist, frage die Uhr ab. pygame.time.get_ticks() ist die Anzahl der Millisekunden seit pygame.init(). Merke dir den Zeitpunkt des Treffers und ziehe ihn ab:

now = pygame.time.get_ticks()
if rock.colliderect(player) and now - hit_time > 1000:
    hit_time = now
    lives -= 1

Setze hit_time in reset() auf -2000, damit der erste Treffer immer zählt.

Zeige die Schutzzeit durch Blinken an. get_ticks() // 100 % 2 ist für eine Zehntelsekunde 0, dann 1 und anschließend wieder 0. Wenn du den Spieler also nur zeichnest, wenn der Wert 0 ist, blinkt er:

safe = pygame.time.get_ticks() - hit_time < 1000
if not safe or pygame.time.get_ticks() // 100 % 2 == 0:
    pygame.draw.rect(screen, (255, 196, 0), player)
challenge icon

Aufgabe

Mittel
  1. Setze in reset() hit_time = -2000 (füge es zur global-Zeile hinzu).
  2. Ein Treffer kostet nur dann ein Leben, wenn seit hit_time mehr als 1000 ms vergangen sind; setze hit_time dann auf den aktuellen Zeitpunkt.
  3. Zeichne den Spieler während der 1000 ms nach einem Treffer nur dann, wenn pygame.time.get_ticks() // 100 % 2 == 0.

Probier es selbst

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Meteor Dodge")
clock = pygame.time.Clock()
heart = pygame.image.load("assets/images/heart.png").convert_alpha()
heart_empty = pygame.image.load("assets/images/heart_empty.png").convert_alpha()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)
WHITE = (240, 240, 240)
PLATE = (60, 60, 90)


def reset():
    global player, rock, score, lives
    player = pygame.Rect(220, 300, 40, 40)
    rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
    score = 0
    lives = 3


def draw_menu():
    screen.fill((30, 30, 46))
    title = big_font.render("Meteor Dodge", True, WHITE)
    title_rect = title.get_rect(center=(240, 140))
    pygame.draw.rect(screen, PLATE, title_rect.inflate(24, 12))
    screen.blit(title, title_rect)
    hint = font.render("Press Enter to play", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


def draw_game():
    screen.fill((30, 30, 46))
    pygame.draw.rect(screen, (255, 196, 0), player)
    pygame.draw.rect(screen, (235, 80, 80), rock)
    score_text = font.render(f"{score:05}", True, WHITE)
    score_rect = score_text.get_rect(topright=(470, 10))
    pygame.draw.rect(screen, PLATE, score_rect.inflate(12, 8))
    screen.blit(score_text, score_rect)
    for i in range(3):
        if i < lives:
            screen.blit(heart, (10 + i * 40, 10))
        else:
            screen.blit(heart_empty, (10 + i * 40, 10))


def play_frame():
    global score, lives, state
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= 6
    if keys[pygame.K_RIGHT]:
        player.x += 6
    player.clamp_ip(screen.get_rect())

    rock.y += 4
    if rock.top > 360:
        rock.y = -24
        rock.x = random.randint(0, 456)
        score += 1
    if rock.colliderect(player):
        lives -= 1
        if lives == 0:
            state = "over"
    draw_game()


def draw_over():
    draw_game()
    message = big_font.render("Game over", True, WHITE)
    screen.blit(message, message.get_rect(center=(240, 160)))
    hint = font.render("Press R to play again", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


reset()
state = "menu"

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                state = "play"
            elif event.key == pygame.K_r and state == "over":
                reset()
                state = "play"

    if state == "menu":
        draw_menu()
    elif state == "play":
        play_frame()
    else:
        draw_over()
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Alle Lektionen in Spielregeln

Übe selbstständig: Pygame-Playground