Menu
CoddyTech

El caballero camina

Parte de la sección Proyectos del Journey de Pygame de Coddy. Lección 22 de 31.

El caballero empieza en la P del mapa y camina con las teclas de flecha, 3 píxeles por fotograma.

Su imagen ocupa una casilla entera, de 48 por 48, y lo mismo ocurre con los espacios entre las paredes. Un Rect de 48 píxeles cabría en un espacio solo si estuviera alineado al píxel exacto. Por eso, el Rect del caballero es más pequeño que su imagen, de 32 por 32, y la imagen se dibuja centrada sobre él. El Rect es lo que colisiona; la imagen es lo que ves.

def draw(image, rect):
    screen.blit(image, image.get_rect(center=rect.center))


def cell_rect(col, row):
    rect = pygame.Rect(0, 0, 32, 32)
    rect.center = (col * TILE + 24, row * TILE + 24)
    return rect

Las paredes lo detienen igual que las plataformas en Moss Caves: muévete a lo largo del eje x, sácalo de cualquier pared con la que se superponga y luego haz lo mismo a lo largo del eje y. Hacerlo en un eje a la vez te indica de qué lado chocó.

def move(self, dx, dy, blocks):
    self.rect.x += dx
    for block in blocks:
        if self.rect.colliderect(block):
            if dx > 0:
                self.rect.right = block.left
            elif dx < 0:
                self.rect.left = block.right
    # luego lo mismo para dy, con bottom y top
challenge icon

Desafío

Difícil
  1. Añade las funciones draw y cell_rect arriba.
  2. En Room, establece self.start = (72, 72) antes del bucle y, para una P, establece self.start = cell_rect(col, row).center.
  3. Escribe class Knight(pygame.sprite.Sprite): su __init__(self, center) establece self.image = knight_img y un self.rect de 32 por 32 centrado en center. Asígnale el método move(dx, dy, blocks) de arriba, incluida la parte de y.
  4. Crea knight = Knight(room.start) después de la sala.
  5. En cada fotograma, establece dx en -3 con Left o en 3 con Right, y dy en -3 con Up o en 3 con Down (0 en caso contrario); después, llama a knight.move(dx, dy, room.walls).
  6. Dibuja al caballero después de las paredes: draw(knight.image, knight.rect).

Pruébalo tú mismo

import pygame

TILE = 48
MAP = [
    "##############",
    "#............#",
    "#.P......K...#",
    "#............#",
    "#....##......D",
    "#....##......#",
    "##.#######.###",
    "#............#",
    "#...S....H...#",
    "##############",
]

pygame.init()
screen = pygame.display.set_mode((672, 480))
pygame.display.set_caption("Rune Keep")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 32)


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")
door_img = load("dungeon_door.png")
key_img = load("key.png")
slime_img = load("slime.png")
spider_img = load("spider.png")
heart_img = load("heart.png")
empty_img = load("heart_empty.png")
sword_img = load("sword.png")
potion_img = load("potion_red.png")


class Room:
    def __init__(self, lines):
        self.walls = []
        for row, line in enumerate(lines):
            for col, char in enumerate(line):
                if char == "#":
                    self.walls.append(pygame.Rect(col * TILE, row * TILE, TILE, TILE))


room = Room(MAP)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    for row in range(10):
        for col in range(14):
            screen.blit(floor_img, (col * TILE, row * TILE))
    for wall in room.walls:
        screen.blit(wall_img, wall)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Proyectos

Practica por tu cuenta: Playground de Pygame