Menu
CoddyTech

Menu et meilleur score

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

Sky Runner tire ses règles de cette section : un menu, une nouvelle partie déclenchée par une touche et le meilleur score.

reset() crée un nouveau personnage et un groupe vide, réinitialise le score et la vitesse, puis redémarre les deux minuteurs. Le jeu commence sur "menu", et best est défini une seule fois, en dehors de reset().

La barre d’espace a maintenant trois fonctions, une par état :

if state == "play":
    runner.jump()
elif state == "menu":
    reset()
    state = "play"
elif pygame.time.get_ticks() - over_time > 500:
    reset()
    state = "play"

La barre d’espace sert à sauter ; le joueur est donc souvent en train d’appuyer dessus au moment d’un crash. Sans délai, le jeu redémarrerait avant qu’il ait pu voir le résultat. Mémorise le moment du crash dans over_time et n’accepte la barre d’espace sur l’écran de fin de partie qu’après 500 ms.

Une petite fonction show(text, text_font, y) dessine une ligne centrée en x 320, car le menu et l’écran de fin de partie en nécessitent cinq.

challenge icon

Défi

Difficile
  1. Écris reset() pour le coureur, le groupe, speed, score et les deux minuteurs ; appelle cette fonction avant la boucle et définis state = "menu", best = 0 et over_time = 0.
  2. Dans le menu, affiche Sky Runner (taille 48) et Press Space to start ; la touche Espace ou Flèche haut démarre une partie.
  3. En cas de collision, mets à jour best et définis over_time.
  4. Sur l’écran de fin de partie, affiche Game over, Best: 00120 (cinq chiffres) et Press Space to play again ; la touche Espace démarre une nouvelle partie, mais seulement 500 ms après la collision.
  5. Affiche le score uniquement pendant la partie et sur l’écran de fin de partie.

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()
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Règles du jeu

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