Menu
CoddyTech

Menu e miglior punteggio

Fa parte della sezione Regole di gioco del percorso Pygame di Coddy. Lezione 29 di 29.

Sky Runner prende le regole da questa sezione: un menu, una nuova partita con un tasto e il punteggio migliore.

reset() crea un nuovo runner e un gruppo vuoto, reimposta il punteggio e la velocità e riavvia entrambi i timer. Il gioco inizia con "menu" e best viene impostato una volta, al di fuori di reset().

Ora la barra spaziatrice ha tre funzioni, una per ogni stato:

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

La barra spaziatrice è il tasto per saltare, quindi spesso il giocatore la sta premendo nel momento in cui si schianta. Senza un'attesa, il gioco ricomincerebbe prima che possa vedere il risultato. Memorizza il momento dello schianto in over_time e accetta la barra spaziatrice nella schermata di fine partita solo 500 ms dopo.

Una piccola funzione show(text, text_font, y) disegna una riga centrata su x 320, dato che il menu e la schermata di fine partita ne richiedono cinque.

challenge icon

Sfida

Difficile
  1. Scrivi reset() per il corridore, il gruppo, speed, score e entrambi i timer; chiamala prima del ciclo e imposta state = "menu", best = 0 e over_time = 0.
  2. Nel menu mostra Sky Runner (dimensione 48) e Press Space to start; premendo Spazio o Freccia su si avvia una partita.
  3. In caso di collisione, aggiorna best e imposta over_time.
  4. Nella schermata di fine partita mostra Game over, Best: 00120 (cinque cifre) e Press Space to play again; Spazio avvia una nuova partita, ma solo 500 ms dopo la collisione.
  5. Mostra il punteggio solo durante la partita e nella schermata di fine partita.

Provalo tu

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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Regole di gioco

Esercitati da solo: Playground Pygame