Menu
CoddyTech

The Knight

Part of the Projects section of Coddy's Pygame journey. Lesson 23 of 33.

The knight starts on the P of the map.

His picture is a whole tile, 48 by 48, and so are the gaps between walls. A 48 pixel Rect would fit a gap only when lined up to the exact pixel. So the knight's Rect is smaller than his picture, 32 by 32, and the picture is drawn centred on it. The Rect is what collides; the picture is what you see.

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

cell_rect(col, row) is the 32 by 32 Rect in the middle of a tile. The knight is a sprite, like the runner of Sky Runner, made at a point:

class Knight(pygame.sprite.Sprite):
    def __init__(self, center):
        super().__init__()
        self.image = knight_img
        self.rect = pygame.Rect(0, 0, 32, 32)
        self.rect.center = center
challenge icon

Challenge

Medium

Put the knight in the first room, standing on the P.

  1. Add the draw and cell_rect functions above.
  2. In Room, set self.start = (72, 72); a P sets self.start = cell_rect(col, row).center.
  3. Write the Knight class above, and make knight = Knight(room.start) after the room.
  4. After the walls, call draw(knight.image, knight.rect).

Press Play: the knight stands on the P. Then Check.

Try it yourself

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

All lessons in Projects

Practice on your own: Pygame playground