Menu
CoddyTech

Menú y mejor puntuación

Parte de la sección Reglas del juego del Journey de Pygame de Coddy. Lección 29 de 29.

Sky Runner obtiene las reglas de esta sección: un menú, una partida nueva al pulsar una tecla y la mejor puntuación.

reset() crea un nuevo corredor y un grupo vacío, restablece la puntuación y la velocidad, y reinicia ambos temporizadores. El juego comienza en "menu", y best se establece una vez, fuera de reset().

La tecla Espacio ahora cumple tres funciones, una por estado:

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

Espacio es la tecla para saltar, así que a menudo el jugador la está pulsando justo en el momento de chocar. Sin una espera, el juego se reiniciaría antes de que pudiera ver el resultado. Recuerda la hora del choque en over_time y acepta Espacio en la pantalla de fin de partida solo 500 ms después.

Una pequeña función show(text, text_font, y) dibuja una línea centrada en x 320, ya que el menú y la pantalla de fin de partida necesitan cinco.

challenge icon

Desafío

Difícil
  1. Escribe reset() para el corredor, el grupo, speed, score y ambos temporizadores; llámala antes del bucle y establece state = "menu", best = 0 y over_time = 0.
  2. En el menú, muestra Sky Runner (tamaño 48) y Press Space to start; la barra espaciadora o la flecha hacia arriba inicia una partida.
  3. Cuando haya una colisión, actualiza best y establece over_time.
  4. En la pantalla de fin de partida, muestra Game over, Best: 00120 (cinco dígitos) y Press Space to play again; la barra espaciadora inicia una nueva partida, pero solo 500 ms después de la colisión.
  5. Muestra la puntuación solo durante la partida y en la pantalla de fin de partida.

Pruébalo tú mismo

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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Reglas del juego

Practica por tu cuenta: Playground de Pygame