Menu
CoddyTech

Anahtar ve Kapı

Coddy'nin Pygame Journey'sinin Projeler bölümünün bir parçası. Ders 23 / 31.

Sağ duvardaki kapı kilitli. Şövalye üzerinden yürüyerek anahtarı alır ve anahtarı aldıktan sonra kapıya dokunduğunda kapı açılır.

Kilitli kapı, şövalyenin yolunu kapatan bir şey daha. Room üzerindeki bir metot, onu durduran Rect'lerin listesini verir:

def blocks(self):
    if self.door_open:
        return self.walls
    return self.walls + [self.door]

Kapıya dokunmanın bir püf noktası var: move, şövalyeyi her karede kapının dışına iter; bu yüzden Rect'i kapıyla hiçbir zaman örtüşmez. knight.rect.inflate(8, 8), her kenarı 4 piksel büyütülmüş Rect'inin bir kopyasıdır ve bu kopya, şövalyenin yaslandığı kapıyla örtüşür.

if room.has_key and knight.rect.inflate(8, 8).colliderect(room.door):
    room.door_open = True

Açık kapının ardında pencerenin kenarı vardır; bu yüzden şövalyeyi içeride tutmak için clamp_ip kullan. Daha sonraki bir derste kapı aralığı bir sonraki odaya açılacak. Anahtarı taşırken üstte göster.

challenge icon

Görev

Orta
  1. Room içinde self.has_key = False ve self.door_open = False değerlerini ayarlayın. Bir K, self.key = cell_rect(col, row) değerini ayarlar; bir D ise self.door değerini döşemesinin 48'e 48 boyutundaki Rect'i olarak ayarlar.
  2. Yukarıdaki blocks yöntemini ekleyin ve şövalyeyi knight.move(dx, dy, room.blocks()) ile hareket ettirin.
  3. Hareket ettikten sonra: knight.rect.clamp_ip(screen.get_rect()); anahtarı yokken room.key ile temas ederse room.has_key = True ayarını yapın; ardından kapıyı yukarıdaki gibi açın.
  4. Kapalıyken kapıyı screen.blit(door_img, room.door) ile, alınana kadar anahtarı draw(key_img, room.key) ile ve room.has_key doğruyken key_img görselini (136, 6) konumunda çizin.

Kendin dene

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()

Projeler bölümündeki tüm dersler

Kendi başına pratik yap: Pygame playground