المفتاح والباب
جزء من قسم المشاريع في رحلة Pygame على Coddy. الدرس 23 من 31.
الباب في الجدار الأيمن مُغلق. يلتقط الفارس المفتاح بالمشي فوقه، وباستخدام المفتاح يُفتح الباب عندما يلمسه.
الباب المُغلق شيء آخر يعترض طريق الفارس. توفّر إحدى الطرق في Room قائمة Rects التي تمنعه من المرور:
def blocks(self):
if self.door_open:
return self.walls
return self.walls + [self.door]للمس الباب حيلة: تدفع move الفارس إلى الخارج منه في كل إطار، لذا لا يتداخل Rect الخاص به مع الباب أبدًا. إن knight.rect.inflate(8, 8) نسخة من Rect الخاص به مكبّرة بمقدار 4 بكسلات من كل جانب، وهذه النسخة تتداخل فعلًا مع الباب الذي يضغط عليه.
if room.has_key and knight.rect.inflate(8, 8).colliderect(room.door):
room.door_open = Trueبعد الباب المفتوح تقع حافة النافذة، لذا أبقِ الفارس داخلها باستخدام clamp_ip. في درس لاحق، يؤدي المدخل إلى الغرفة التالية. أظهِر المفتاح في الأعلى بينما يحمله.
التحدي
متوسط- في
Room، اضبطself.has_key = Falseوself.door_open = False. يحددKالقيمةself.key = cell_rect(col, row)؛ ويحددDself.doorلتكون مستطيلًا بأبعاد 48 في 48 لبلاطته. - أضف الطريقة
blocksالمذكورة أعلاه وحرّك الفارس باستخدامknight.move(dx, dy, room.blocks()). - بعد التحريك:
knight.rect.clamp_ip(screen.get_rect())؛ عندما لا يكون معه مفتاح ويلامسroom.key، اضبطroom.has_key = True؛ ثم افتح الباب كما سبق. - ارسم الباب باستخدام
screen.blit(door_img, room.door)عندما يكون مغلقًا، والمفتاح باستخدامdraw(key_img, room.key)حتى يلتقطه، وkey_imgعند(136, 6)ما دامتroom.has_keyتساوي true.
جرّب بنفسك
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()
جميع دروس المشاريع
تدرّب بنفسك: Playground لـ Pygame