Der Schlüssel und die Tür
Teil des Abschnitts Projekte der Pygame-Journey von Coddy. Lektion 23 von 31.
Die Tür in der rechten Wand ist verschlossen. Der Ritter nimmt den Schlüssel auf, indem er darüberläuft, und mit dem Schlüssel öffnet sich die Tür, wenn er sie berührt.
Eine verschlossene Tür ist ein weiteres Hindernis für den Ritter. Eine Methode in Room liefert die Liste der Rects, die ihn aufhalten:
def blocks(self):
if self.door_open:
return self.walls
return self.walls + [self.door]Beim Berühren der Tür gibt es einen Haken: move schiebt den Ritter in jedem Frame aus ihr heraus, sodass sein Rect die Tür nie überlappt. knight.rect.inflate(8, 8) ist eine Kopie seines Rect, die auf jeder Seite um 4 Pixel vergrößert wurde, und diese Kopie überlappt die Tür, an die er stößt.
if room.has_key and knight.rect.inflate(8, 8).colliderect(room.door):
room.door_open = TrueHinter der geöffneten Tür liegt der Rand des Fensters, also halte den Ritter mit clamp_ip im Fenster. In einer späteren Lektion führt die Tür zum nächsten Raum. Zeige den Schlüssel oben an, solange er ihn bei sich trägt.
Aufgabe
Mittel- Setze in
Roomself.has_key = Falseundself.door_open = False. EinKsetztself.key = cell_rect(col, row); einDsetztself.doorauf das 48 mal 48 große Rect seines Feldes. - Füge die obige Methode
blockshinzu und bewege den Ritter mitknight.move(dx, dy, room.blocks()). - Nach der Bewegung:
knight.rect.clamp_ip(screen.get_rect()); wenn er keinen Schlüssel hat undroom.keyberührt, setzeroom.has_key = True; öffne dann die Tür wie oben beschrieben. - Zeichne die Tür mit
screen.blit(door_img, room.door), solange sie geschlossen ist, den Schlüssel mitdraw(key_img, room.key), bis er aufgehoben wird, undkey_imgan(136, 6), solangeroom.has_keywahr ist.
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")
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
class Room:
def __init__(self, lines):
self.walls = []
self.start = (72, 72)
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))
elif char == "P":
self.start = cell_rect(col, row).center
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
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
self.rect.y += dy
for block in blocks:
if self.rect.colliderect(block):
if dy > 0:
self.rect.bottom = block.top
elif dy < 0:
self.rect.top = block.bottom
room = Room(MAP)
knight = Knight(room.start)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
dx = 0
dy = 0
if keys[pygame.K_LEFT]:
dx = -3
if keys[pygame.K_RIGHT]:
dx = 3
if keys[pygame.K_UP]:
dy = -3
if keys[pygame.K_DOWN]:
dy = 3
knight.move(dx, dy, room.walls)
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)
draw(knight.image, knight.rect)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Alle Lektionen in Projekte
Übe selbstständig: Pygame-Playground