Menu
CoddyTech

Der Ritter läuft

Teil des Abschnitts Projekte der Pygame-Journey von Coddy. Lektion 22 von 31.

Der Ritter startet auf dem P der Karte und bewegt sich mit den Pfeiltasten, 3 Pixel pro Frame.

Sein Bild füllt ein ganzes Feld, 48 mal 48, und genauso groß sind auch die Abstände zwischen den Wänden. Ein 48 Pixel großes Rect würde nur dann in einen Abstand passen, wenn es genau auf den Pixel ausgerichtet ist. Das Rect des Ritters ist also kleiner als sein Bild, 32 mal 32, und das Bild wird mittig darauf gezeichnet. Das Rect kollidiert; das Bild ist das, was du siehst.

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

Die Wände halten ihn auf dieselbe Weise auf wie die Plattformen in Moss Caves: Bewege ihn entlang der x-Achse, schiebe ihn aus jeder Wand, die er überlappt, und mache dann dasselbe entlang der y-Achse. Wenn du jeweils nur eine Achse bearbeitest, erkennst du, welche Seite er getroffen hat.

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
    # dann dasselbe für dy, mit bottom und top
challenge icon

Aufgabe

Schwer
  1. Füge die Funktionen draw und cell_rect oben hinzu.
  2. Setze in Room vor der Schleife self.start = (72, 72) und für ein P self.start = cell_rect(col, row).center.
  3. Schreibe class Knight(pygame.sprite.Sprite): Die Methode __init__(self, center) setzt self.image = knight_img und ein 32 × 32 großes self.rect, das auf center zentriert ist. Füge die oben gezeigte Methode move(dx, dy, blocks) mit dem y-Teil hinzu.
  4. Erstelle nach dem Raum knight = Knight(room.start).
  5. Setze in jedem Frame dx auf -3 bei Links oder auf 3 bei Rechts und dy auf -3 bei Oben oder auf 3 bei Unten (ansonsten auf 0). Rufe dann knight.move(dx, dy, room.walls) auf.
  6. Zeichne den Ritter nach den Wänden: draw(knight.image, knight.rect).

Probier es selbst

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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Projekte

Übe selbstständig: Pygame-Playground