Menu
CoddyTech

Conto alla rovescia per partire

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

Premendo Invio, il giocatore si ritrova subito tra rocce in caduta. Un conto alla rovescia, 3, 2, 1, gli dà un momento per prepararsi. È un altro stato, "countdown", che disegna il gioco senza farlo avanzare, con un numero in primo piano.

Il numero dipende dal tempo trascorso dall'inizio del conto alla rovescia:

left = 3 - (pygame.time.get_ticks() - countdown_start) // 1000

Nel primo secondo // dà 0, quindi left è 3; poi 2, poi 1. Quando arriva a 0, il gioco inizia:

def countdown_frame():
    global state
    left = 3 - (pygame.time.get_ticks() - countdown_start) // 1000
    draw_game()
    if left > 0:
        number = big_font.render(str(left), True, WHITE)
        screen.blit(number, number.get_rect(center=(240, 170)))
    else:
        state = "play"

Invio e R avviano entrambi un conto alla rovescia, quindi una piccola funzione imposta lo stato e memorizza l'ora di inizio:

def start_countdown():
    global state, countdown_start
    state = "countdown"
    countdown_start = pygame.time.get_ticks()
challenge icon

Sfida

Medio
  1. Scrivi start_countdown() e countdown_frame() come mostrato e chiama countdown_frame() quando lo stato è "countdown".
  2. Premere Invio nel menu e R nella schermata di fine partita chiama start_countdown() invece di impostare "play".
  3. Il conto alla rovescia mostra 3, 2 e 1 per un secondo ciascuno, centrati in (240, 170).

Provalo tu

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, hit_time, wave, to_spawn
    player = pygame.Rect(220, 300, 40, 40)
    rocks = []
    wave = 1
    to_spawn = 3
    score = 0
    lives = 3
    hit_time = -2000
    pygame.time.set_timer(POINT, 1000)
    pygame.time.set_timer(SPAWN, 800)


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))
    safe = pygame.time.get_ticks() - hit_time < 1000
    if not safe or pygame.time.get_ticks() // 100 % 2 == 0:
        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)
    wave_text = font.render(f"Wave {wave}", True, WHITE)
    screen.blit(wave_text, wave_text.get_rect(midtop=(240, 10)))
    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 score, lives, state, hit_time, rocks, wave, to_spawn
    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())

    for rock in rocks:
        rock.y += 4
    rocks = [rock for rock in rocks if rock.top <= 360]
    if to_spawn == 0 and not rocks:
        wave += 1
        to_spawn = wave + 2
    now = pygame.time.get_ticks()
    for rock in rocks:
        if rock.colliderect(player) and now - hit_time > 1000:
            hit_time = now
            lives -= 1
            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" and to_spawn > 0:
            rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
            to_spawn -= 1
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                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()
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