Menu
CoddyTech

A salvo tras un golpe

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

Colócate debajo de una roca en esta versión. La roca ya no vuelve a saltar a la parte superior al golpear, atraviesa al jugador y lo toca durante muchos fotogramas seguidos. Cada uno de esos fotogramas quita una vida, así que una roca termina la partida.

Muchos juegos ofrecen un breve período de seguridad después de un golpe. Para saber cuánto tiempo ha pasado, consulta el reloj. pygame.time.get_ticks() es el número de milisegundos transcurridos desde pygame.init(). Recuerda el momento del golpe y réstalo:

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

Inicia hit_time en -2000 en reset(), para que el primer golpe siempre cuente.

Muestra el período de seguridad haciendo parpadear al jugador. get_ticks() // 100 % 2 es 0 durante una décima de segundo, después 1 y luego vuelve a 0, así que dibujar al jugador solo cuando es 0 hace que parpadee:

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

Desafío

Intermedio
  1. En reset(), establece hit_time = -2000 (añádelo a la línea global).
  2. Un impacto solo quita una vida cuando han pasado más de 1000 ms desde hit_time; después, establece hit_time en el momento actual.
  3. Durante los 1000 ms posteriores a un impacto, dibuja al jugador solo cuando pygame.time.get_ticks() // 100 % 2 == 0.

Pruébalo tú mismo

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()

Todas las lecciones de Reglas del juego

Practica por tu cuenta: Playground de Pygame