Menu
CoddyTech

벽은 기사를 막아요

Coddy Pygame 여정의 프로젝트 섹션에 포함된 레슨. 33개 중 24번째.

기사는 화살표 키로 프레임당 3픽셀씩 이동하고, 벽에 막히는 방식은 Moss Caves의 플랫폼과 같습니다. x축을 따라 이동하고, 겹치는 벽이 있으면 밀어내고, 그다음 y축을 따라 똑같이 이동합니다. 한 번에 한 축씩 처리하면 어느 쪽에 부딪혔는지 알 수 있습니다.

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

Catch the Blocks에서처럼 매 프레임 화살표 키를 읽어 dx와 dy에 넣고, 방의 벽을 전달합니다.

keys = pygame.key.get_pressed()
dx = 0
dy = 0
if keys[pygame.K_LEFT]:
    dx = -3
# Right, Up, Down도 같은 방식으로 처리
knight.move(dx, dy, room.walls)
challenge icon

챌린지

어려움

기사가 벽에 막히도록 이동하게 하세요.

  1. Knight에 위의 move(dx, dy, blocks) 메서드를 추가하세요.
  2. 매 프레임마다 왼쪽 키를 누르면 dx를 -3으로, 오른쪽 키를 누르면 3으로 설정하고, 위쪽 키를 누르면 dy를 -3으로, 아래쪽 키를 누르면 3으로 설정하세요. 아무 키도 누르지 않으면 0으로 설정하세요.
  3. 그런 다음 knight.move(dx, dy, room.walls)를 호출하세요.

‘플레이’를 눌러 벽을 향해 걸어 보세요. 기사가 벽에 부딪혀 멈춥니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

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


room = Room(MAP)
knight = Knight(room.start)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

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

프로젝트의 모든 레슨

직접 연습해 보세요: Pygame 플레이그라운드