Menu
CoddyTech

Kunci dan Pintu

Termasuk bagian Proyek dalam perjalanan Pygame di Coddy. Pelajaran 23 dari 31.

Pintu di dinding kanan terkunci. Kesatria mengambil kunci dengan berjalan melewatinya, lalu pintu terbuka saat ia menyentuhnya sambil membawa kunci.

Pintu yang terkunci menjadi satu hal lagi yang menghalangi kesatria. Sebuah method pada Room memberikan daftar Rect yang menghalanginya:

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

Ada kendala saat menyentuh pintu: move mendorong kesatria menjauh darinya pada setiap frame, jadi Rect-nya tidak pernah bertumpang tindih dengan pintu. knight.rect.inflate(8, 8) adalah salinan Rect-nya yang diperbesar 4 piksel di setiap sisi, dan salinan itu bertumpang tindih dengan pintu yang sedang ia hadapi.

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

Di balik pintu yang terbuka ada tepi jendela, jadi jaga kesatria tetap di dalam dengan clamp_ip. Pada pelajaran berikutnya, pintu itu akan mengarah ke ruangan berikutnya. Tampilkan kunci di bagian atas saat ia membawanya.

challenge icon

Tantangan

Sedang
  1. Di Room, tetapkan self.has_key = False dan self.door_open = False. K menetapkan self.key = cell_rect(col, row); D menetapkan self.door ke Rect berukuran 48 kali 48 dari petaknya.
  2. Tambahkan method blocks di atas dan gerakkan knight dengan knight.move(dx, dy, room.blocks()).
  3. Setelah bergerak: knight.rect.clamp_ip(screen.get_rect()); saat knight belum memiliki kunci dan menyentuh room.key, tetapkan room.has_key = True; lalu buka pintu seperti di atas.
  4. Gambar pintu dengan screen.blit(door_img, room.door) saat pintu tertutup, kunci dengan draw(key_img, room.key) hingga diambil, dan key_img di (136, 6) saat room.has_key bernilai true.

Coba sendiri

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

Semua pelajaran di Proyek

Latihan sendiri: Playground Pygame