Tường chặn hiệp sĩ
Thuộc phần Dự án trong hành trình Pygame của Coddy. Bài học 24 trên 33.
Kỵ sĩ di chuyển bằng các phím mũi tên, mỗi khung hình 3 pixel, còn tường chặn kỵ sĩ giống như các bệ trong Moss Caves: di chuyển theo trục x, đẩy ra khỏi mọi bức tường mà kỵ sĩ chồng lên, rồi làm tương tự theo trục y. Xử lý từng trục một giúp bạn biết kỵ sĩ va vào phía nào.
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Đọc các phím mũi tên mỗi khung hình vào dx và dy, như trong Catch the Blocks, rồi truyền các bức tường trong căn phòng:
keys = pygame.key.get_pressed()
dx = 0
dy = 0
if keys[pygame.K_LEFT]:
dx = -3
# Làm tương tự với phím sang phải, lên và xuống
knight.move(dx, dy, room.walls)Thử thách
KhóĐiều khiển hiệp sĩ di chuyển và dừng lại khi gặp tường.
- Thêm phương thức
move(dx, dy, blocks)ở trên vàoKnight. - Mỗi khung hình, đặt
dxthành -3 khi nhấn Left hoặc 3 khi nhấn Right, và đặtdythành -3 khi nhấn Up hoặc 3 khi nhấn Down, nếu không thì đặt thành 0. - Sau đó gọi
knight.move(dx, dy, room.walls).
Nhấn Chơi rồi đi vào tường: hiệp sĩ sẽ dừng lại khi chạm tường. 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
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()
Tất cả bài học trong Dự án
Tự luyện tập: Playground Pygame