Chìa khóa và cánh cửa
Thuộc phần Dự án trong hành trình Pygame của Coddy. Bài học 25 trên 33.
Cánh cửa trên bức tường bên phải đang khóa. Hiệp sĩ nhặt chìa khóa khi đi qua nó, và khi có chìa khóa, anh ấy sẽ mở được cửa khi chạm vào.
Cánh cửa bị khóa là một vật cản nữa đối với hiệp sĩ. Một phương thức trong Room trả về danh sách các Rect cản đường anh ấy:
def blocks(self):
if self.door_open:
return self.walls
return self.walls + [self.door]Việc chạm vào cửa có một điểm cần lưu ý: move đẩy hiệp sĩ ra khỏi cửa ở mỗi khung hình, nên Rect của anh ấy không bao giờ chồng lên cửa. knight.rect.inflate(8, 8) là một bản sao của Rect được nới rộng thêm 4 pixel về mỗi phía, và bản sao đó có chồng lên cánh cửa mà anh ấy đang áp sát.
if room.has_key and knight.rect.inflate(8, 8).colliderect(room.door):
room.door_open = TrueSau cánh cửa mở là mép cửa sổ, vì vậy hãy giữ hiệp sĩ bên trong bằng clamp_ip. Trong một bài học sau, lối đi qua cửa sẽ dẫn đến căn phòng tiếp theo. Hiển thị chìa khóa ở phía trên khi anh ấy mang nó.
Thử thách
Trung bìnhKhóa cửa cho đến khi hiệp sĩ tìm thấy chìa khóa.
- Trong
Room:self.has_key = Falsevàself.door_open = False;Kgánself.key = cell_rect(col, row),Dgánself.doorthành Rect của ô bản đồ có kích thước 48 x 48. - Thêm
blocks(); gọiknight.move(dx, dy, room.blocks()), rồi gọiknight.rect.clamp_ip(screen.get_rect()). - Chạm vào
room.keysẽ gánroom.has_key = True; sau đó mở cửa như trên.
Nhấn Chơi: cửa vẫn đóng cho đến khi bạn lấy chìa khóa. Sau đó nhấn Kiểm tra.
Tự làm thử
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()
Tất cả bài học trong Dự án
Tự luyện tập: Playground Pygame