La clé et la porte
Fait partie de la section Projets du Journey Pygame de Coddy. Leçon 23 sur 31.
La porte du mur de droite est verrouillée. Le chevalier ramasse la clé en marchant dessus et, avec la clé, la porte s’ouvre lorsqu’il la touche.
Une porte verrouillée est un obstacle de plus pour le chevalier. Une méthode de Room fournit la liste des Rects qui l’arrêtent :
def blocks(self):
if self.door_open:
return self.walls
return self.walls + [self.door]Toucher la porte a une particularité : move repousse le chevalier hors de celle-ci à chaque image, donc son Rect ne chevauche jamais la porte. knight.rect.inflate(8, 8) est une copie de son Rect agrandie de 4 pixels de chaque côté, et cette copie chevauche bien la porte contre laquelle il est appuyé.
if room.has_key and knight.rect.inflate(8, 8).colliderect(room.door):
room.door_open = TrueAu-delà de la porte ouverte se trouve le bord de la fenêtre : garde donc le chevalier à l’intérieur avec clamp_ip. Dans une leçon ultérieure, l’embrasure mènera à la pièce suivante. Affiche la clé en haut lorsqu’il la porte.
Défi
Moyen- Dans
Room, définisself.has_key = Falseetself.door_open = False. UnKdéfinitself.key = cell_rect(col, row); unDdéfinitself.doorcomme le Rect de 48 par 48 de sa tuile. - Ajoute la méthode
blocksci-dessus et déplace le chevalier avecknight.move(dx, dy, room.blocks()). - Après le déplacement :
knight.rect.clamp_ip(screen.get_rect()); s’il n’a pas de clé et toucheroom.key, définisroom.has_key = True; ouvre ensuite la porte comme ci-dessus. - Affiche la porte avec
screen.blit(door_img, room.door)lorsqu’elle est fermée, la clé avecdraw(key_img, room.key)jusqu’à ce qu’elle soit ramassée, etkey_imgà(136, 6)lorsqueroom.has_keyest vrai.
Essayez vous-même
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()
Toutes les leçons de Projets
Entraînez-vous par vous-même : Playground Pygame