Corazones
Lección 7 de 20 del curso Proyecto con Pygame: Defiende la fortaleza de Coddy.
Un monstruo que alcanza al caballero le cuesta un corazón. Sin una pausa después de recibir un golpe, un monstruo que estuviera sobre el caballero le quitaría un corazón en cada fotograma: los cinco en una doceava parte de segundo. Así que un golpe inicia un contador, hurt, y mientras cuenta hacia atrás nada puede hacer daño al caballero:
def take_hits(self):
knight = self.knight
if knight.hurt > 0:
knight.hurt -= 1
elif pygame.sprite.spritecollideany(knight, self.monsters):
knight.hearts -= 1
knight.hurt = 75spritecollideany(sprite, group) devuelve el primer sprite del grupo cuyo rectángulo se superpone, o None.
Ahora el juego tiene estados: "playing" y "lost". El bucle ejecuta night.update solo mientras se está jugando, así que cuando se acaban los corazones todo se detiene donde está.
Mientras hurt cuenta, dibuja al caballero solo cuando knight.hurt % 10 < 5: parpadea y el jugador ve por qué nada le hace daño.
Desafío
Intermedio- Asigna al caballero
hearts = 5,max_hearts = 5yhurt = 0; asigna aNightstate = "playing". - Escribe
take_hitscomo se muestra arriba; cuando los corazones lleguen a 0, estableceself.state = "lost". Llámala al final deupdate. - En el bucle, actualiza solo cuando se cumpla
if night.state == "playing", y dibuja al caballero solo cuando se cumplaknight.hurt % 10 < 5. - Carga
heart.pngyheart_empty.pngcomoheart_imgyempty_img. Para cada uno de losmax_hearts, dibuja con blit un corazón lleno o vacío en(8 + i * 34, 6). - Crea
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)y, cuando hayas perdido, dibuja"The keep has fallen"centrado en (360, 200).
Pruébalo tú mismo
import random
import pygame
WIDTH, HEIGHT = 720, 480
TILE = 48
NIGHT = 60 * 60 * 4
WHITE = (240, 240, 240)
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Hold the Keep")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
def load(name):
return pygame.image.load("assets/images/" + name).convert_alpha()
floor_img = load("floor.png")
wall_img = load("wall.png")
knight_img = load("knight.png")
MONSTERS = {
"slime": {"image": load("slime.png"), "speed": 1.0},
}
courtyard = pygame.Rect(TILE, TILE, WIDTH - 2 * TILE, HEIGHT - 2 * TILE)
background = pygame.Surface((WIDTH, HEIGHT))
for row in range(HEIGHT // TILE):
for col in range(WIDTH // TILE):
x = col * TILE
y = row * TILE
if courtyard.collidepoint(x, y):
background.blit(floor_img, (x, y))
else:
background.blit(wall_img, (x, y))
def draw(image, center):
screen.blit(image, image.get_rect(center=center))
def clock_text(frames):
seconds = frames // 60
return f"{seconds // 60}:{seconds % 60:02d}"
def edge_point():
side = random.randint(0, 3)
if side == 0:
return (random.randint(0, WIDTH), -24)
if side == 1:
return (random.randint(0, WIDTH), HEIGHT + 24)
if side == 2:
return (-24, random.randint(0, HEIGHT))
return (WIDTH + 24, random.randint(0, HEIGHT))
class Knight(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = knight_img
self.rect = pygame.Rect(0, 0, 24, 24)
self.rect.center = courtyard.center
self.speed = 3
def move(self, keys):
if keys[pygame.K_LEFT]:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT]:
self.rect.x += self.speed
if keys[pygame.K_UP]:
self.rect.y -= self.speed
if keys[pygame.K_DOWN]:
self.rect.y += self.speed
self.rect.clamp_ip(courtyard)
class Monster(pygame.sprite.Sprite):
def __init__(self, kind, pos):
super().__init__()
self.kind = kind
self.image = MONSTERS[kind]["image"]
self.speed = MONSTERS[kind]["speed"]
self.pos = pygame.Vector2(pos)
self.rect = pygame.Rect(0, 0, 28, 28)
self.rect.center = self.pos
def update(self, target):
step = pygame.Vector2(target) - self.pos
if step.length() > 0:
self.pos += step.normalize() * self.speed
self.rect.center = self.pos
class Night:
def __init__(self):
self.knight = Knight()
self.time = 0
self.monsters = pygame.sprite.Group()
def spawn(self):
if self.time % 60 == 0:
self.monsters.add(Monster("slime", edge_point()))
def update(self, keys):
self.time += 1
self.knight.move(keys)
self.spawn()
self.monsters.update(self.knight.rect.center)
night = Night()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
night.update(pygame.key.get_pressed())
screen.blit(background, (0, 0))
knight = night.knight
for monster in night.monsters:
draw(monster.image, monster.rect.center)
draw(knight.image, knight.rect.center)
left = font.render(clock_text(max(0, NIGHT - night.time)) + " until dawn", True, WHITE)
screen.blit(left, left.get_rect(center=(WIDTH // 2, 24)))
pygame.display.flip()
clock.tick(60)
pygame.quit()
Todas las lecciones de Proyecto con Pygame: Defiende la fortaleza
Practica por tu cuenta: Playground de Pygame