Menu
CoddyTech

Un menu pour Coureur du ciel

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

Sky Runner récupère les règles dans cette section, en commençant par un menu. Une nouvelle partie doit tout remettre à son état initial, alors ajoute cela dans reset() : un nouveau coureur, un groupe vide, la vitesse et le score, ainsi que les deux minuteurs relancés.

La barre d’espace a maintenant deux fonctions, une pour chaque état :

if state == "play":
    runner.jump()
elif state == "menu":
    reset()
    state = "play"

Le menu a besoin de deux lignes centrées et l’écran de fin de partie en aura besoin de trois, alors une petite fonction dessine une ligne centrée en x 320 :

def show(text, text_font, y):
    picture = text_font.render(text, True, INK)
    screen.blit(picture, picture.get_rect(center=(320, y)))

Le score fait partie d’une partie, alors affiche-le seulement lorsqu’une partie a commencé, et non dans le menu.

challenge icon

Défi

Moyen

Ajoute un menu à Sky Runner.

  1. Écris reset() pour le coureur, le groupe, speed, score et les deux minuteurs ; appelle-la avant la boucle et définis state = "menu".
  2. Dans le menu, utilise show() pour Sky Runner avec big_font et Press Space to start ; affiche le score uniquement hors du menu.
  3. Dans le menu, la touche Espace appelle reset() et définit state = "play".

Appuie sur « Jouer » : la touche Espace démarre une partie. Puis clique sur « Vérifier ».

Essayez vous-même

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 32)

SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1
POINT = pygame.USEREVENT + 2


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)
pygame.time.set_timer(POINT, 100)
score = 0
state = "play"

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):
            if state == "play":
                runner.jump()
        if event.type == SPAWN and state == "play":
            obstacles.add(Obstacle())
            pygame.time.set_timer(SPAWN, random.randint(1000, 2000))
        if event.type == POINT and state == "play":
            score += 1

    if state == "play":
        speed = min(14, 6 + score // 100)
        runner.update()
        obstacles.update()
        if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
            state = "over"

    screen.fill(SKY)
    pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
    screen.blit(runner.image, runner.rect)
    obstacles.draw(screen)
    score_text = font.render(f"{score:05}", True, (40, 50, 80))
    screen.blit(score_text, score_text.get_rect(topright=(630, 10)))
    if state == "over":
        message = font.render("Game over", True, (40, 50, 80))
        screen.blit(message, message.get_rect(center=(320, 140)))
    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