Menu
CoddyTech

Normal ou difficile

Fait partie de la section Règles du jeu du Journey Pygame de Coddy. Leçon 17 sur 29.

Laisse le joueur choisir le niveau de difficulté du jeu avant son démarrage. Le menu affiche deux options, et les flèches permettent d’en sélectionner une :

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

Les mêmes flèches déplacent le joueur pendant la partie. Tester state == "menu" permet de distinguer les deux usages.

Le menu indique l’option sélectionnée, afin que le joueur voie ce que la touche Entrée va lancer :

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

Ensuite, le jeu lit difficulty à l’endroit où les nombres sont définis. En mode Hard, les rochers commencent à 6 pixels par image au lieu de 3 :

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

Définis difficulty = "normal" une fois avant la boucle, et non dans reset(), afin que R conserve le choix.

challenge icon

Défi

Moyen
  1. Avant la boucle, définis difficulty = "normal".
  2. Dans le menu, la gauche lui attribue "normal" et la droite "hard".
  3. Le menu affiche les deux options centrées aux positions (160, 260) et (320, 260) : > Normal < et Hard, ou Normal et > Hard <.
  4. Les rochers commencent à 3 pixels par image en mode Normal et à 6 en mode Hard, puis leur vitesse augmente de 1 toutes les cinq secondes.

Essayez vous-même

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()

Toutes les leçons de Règles du jeu

Entraînez-vous par vous-même : Playground Pygame