Menu
CoddyTech

Al sicuro dopo un colpo

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

In questa versione, mettiti sotto una roccia. La roccia non torna più in cima quando colpisce, attraversa il giocatore e lo tocca per molti fotogrammi di fila. Ognuno di quei fotogrammi fa perdere una vita, quindi una sola roccia pone fine alla partita.

Molti giochi concedono un breve periodo di invulnerabilità dopo un colpo. Per sapere quanto tempo è passato, chiedi all'orologio. pygame.time.get_ticks() restituisce il numero di millisecondi trascorsi da pygame.init(). Ricorda il momento del colpo e sottrailo:

now = pygame.time.get_ticks()
if rock.colliderect(player) and now - hit_time > 1000:
    hit_time = now
    lives -= 1

Imposta hit_time su -2000 in reset(), così il primo colpo conta sempre.

Mostra il periodo di invulnerabilità facendo lampeggiare il giocatore. get_ticks() // 100 % 2 vale 0 per un decimo di secondo, poi 1, poi di nuovo 0; quindi, disegnando il giocatore solo quando vale 0, lo farai lampeggiare:

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)
challenge icon

Sfida

Medio
  1. In reset(), imposta hit_time = -2000 (aggiungilo alla riga global).
  2. Un colpo fa perdere una vita solo quando sono passati più di 1000 ms da hit_time; poi imposta hit_time sull'ora corrente.
  3. Per 1000 ms dopo un colpo, disegna il giocatore solo quando pygame.time.get_ticks() // 100 % 2 == 0.

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)


def reset():
    global player, rock, score, lives
    player = pygame.Rect(220, 300, 40, 40)
    rock = pygame.Rect(random.randint(0, 456), -24, 24, 24)
    score = 0
    lives = 3


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))
    pygame.draw.rect(screen, (255, 196, 0), player)
    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)
    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
    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())

    rock.y += 4
    if rock.top > 360:
        rock.y = -24
        rock.x = random.randint(0, 456)
        score += 1
    if rock.colliderect(player):
        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 == 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()

Tutte le lezioni di Regole di gioco

Esercitati da solo: Playground Pygame