Menu
CoddyTech

Normal oder Schwer

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

Lass den Spieler vor dem Start wählen, wie schwierig das Spiel ist. Das Menü zeigt zwei Optionen, und mit den Pfeiltasten wählst du eine davon aus:

elif event.key == pygame.K_LEFT and state == "menu":
    difficulty = "normal"
elif event.key == pygame.K_RIGHT and state == "menu":
    difficulty = "hard"

Während des Spiels bewegen dieselben Pfeiltasten den Spieler. Die Prüfung state == "menu" hält die beiden Verwendungen auseinander.

Das Menü markiert die ausgewählte Option, damit der Spieler sieht, was mit Enter gestartet wird:

if difficulty == "normal":
    normal, hard = "> Normal <", "Hard"
else:
    normal, hard = "Normal", "> Hard <"

Dann liest das Spiel difficulty dort aus, wo die Zahlen festgelegt werden. Im Schwierigkeitsgrad Hard starten die Felsen mit 6 Pixeln pro Frame statt mit 3:

if difficulty == "normal":
    speed = 3 + seconds // 5
else:
    speed = 6 + seconds // 5

Setze difficulty = "normal" einmal vor der Schleife, nicht in reset(), damit R die Auswahl beibehält.

challenge icon

Aufgabe

Mittel
  1. Setze vor der Schleife difficulty = "normal".
  2. Im Menü setzt die linke Pfeiltaste den Wert auf "normal" und die rechte auf "hard".
  3. Das Menü zeigt die beiden Optionen zentriert bei (160, 260) und (320, 260): > Normal < und Hard oder Normal und > Hard <.
  4. Die Felsen bewegen sich bei Normal mit 3 Pixeln pro Bild und bei Hard mit 6 Pixeln pro Bild, plus 1 Pixel alle fünf Sekunden.

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)
POINT = pygame.USEREVENT + 1
SPAWN = pygame.USEREVENT + 2


def reset():
    global player, rocks, score, lives, start_time
    player = pygame.Rect(220, 300, 40, 40)
    rocks = []
    score = 0
    lives = 3
    start_time = pygame.time.get_ticks()
    pygame.time.set_timer(POINT, 1000)
    pygame.time.set_timer(SPAWN, 1000)


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)
    for rock in rocks:
        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 rocks, 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())

    seconds = (pygame.time.get_ticks() - start_time) // 1000
    speed = 3 + seconds // 5
    kept = []
    for rock in rocks:
        rock.y += speed
        if rock.colliderect(player):
            lives -= 1
        elif rock.top <= 360:
            kept.append(rock)
    rocks = kept
    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 == POINT and state == "play":
            score += 1
        if event.type == SPAWN and state == "play":
            rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
            seconds = (pygame.time.get_ticks() - start_time) // 1000
            interval = max(400, 1000 - seconds * 60)
            pygame.time.set_timer(SPAWN, interval)
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                reset()
                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