Kẻ địch từ bản đồ
Thuộc phần Thế giới trò chơi trong hành trình Pygame của Coddy. Bài học 27 trên 36.
Các blob được đặt bằng số trong code, còn mọi thứ khác trong màn chơi lấy từ bản đồ. Hãy thêm chúng vào bản đồ: E là kẻ địch đứng trên ô đó.
elif char == "E":
blobs.add(Blob((col * TILE + TILE // 2, row * TILE + TILE)))(col * TILE + TILE // 2, row * TILE + TILE) là điểm giữa cạnh dưới của ô, cũng là điểm xuất phát của người chơi. Rect của blob đặt điểm giữa cạnh dưới của nó ở đó, nên blob đứng trên mặt đất bên dưới E. Tạo nhóm trước các vòng lặp để các vòng lặp có thể thêm phần tử vào nhóm.
Giờ đây, thiết kế màn chơi chỉ cần nhập: di chuyển một E thì blob cũng di chuyển; thêm một E thì có thêm một blob. Đặt mỗi E trên ô có mặt đất bên dưới, nếu không blob sẽ quay đầu ngay và đứng yên.
Thử thách
DễĐặt các khối blob theo bản đồ.
- Tạo
blobs = pygame.sprite.Group()trước các vòng lặp qua bản đồ. - Với mỗi
E, thêmBlob((col * TILE + TILE // 2, row * TILE + TILE))vàoblobs. - Xóa dòng tạo hai khối blob tại các vị trí cố định.
Nhấn "Chơi": một khối blob tuần tra tại mỗi E trên bản đồ. Sau đó nhấn "Kiểm tra".
Tự làm thử
import pygame
TILE = 36
SPEED = 4
GRAVITY = 1
JUMP = -15
MAX_FALL = 12
LEVEL = [
"................",
"................",
"................",
"...........E....",
"..........####..",
"....E...........",
"...####.........",
"................",
"#.P.........E..#",
"################",
]
pygame.init()
screen = pygame.display.set_mode((576, 360))
pygame.display.set_caption("Enemies From the Map")
clock = pygame.time.Clock()
background = pygame.image.load("assets/backgrounds/clouds.png").convert_alpha()
block_img = pygame.image.load("assets/images/block.png").convert_alpha()
player_img = pygame.image.load("assets/images/player.png").convert_alpha()
blob_img = pygame.image.load("assets/images/blob.png").convert_alpha()
blob_walk_img = pygame.image.load("assets/images/blob_walk.png").convert_alpha()
class Blob(pygame.sprite.Sprite):
def __init__(self, midbottom):
super().__init__()
self.image = blob_img
self.rect = pygame.Rect(0, 0, 30, 26)
self.rect.midbottom = midbottom
self.direction = 1
self.frames = [blob_img, blob_walk_img]
self.timer = 0
def update(self):
self.timer += 1
self.image = self.frames[self.timer // 10 % 2]
self.rect.x += self.direction
if self.direction > 0:
ahead = self.rect.right
else:
ahead = self.rect.left - 1
hit_wall = any(self.rect.colliderect(wall) for wall in walls)
ground_ahead = any(wall.collidepoint(ahead, self.rect.bottom) for wall in walls)
if hit_wall or not ground_ahead:
self.rect.x -= self.direction
self.direction = -self.direction
walls = []
for row, line in enumerate(LEVEL):
for col, char in enumerate(line):
if char == "#":
walls.append(pygame.Rect(col * TILE, row * TILE, TILE, TILE))
elif char == "P":
start = (col * TILE + TILE // 2, row * TILE + TILE)
blobs = pygame.sprite.Group(Blob((432, 144)), Blob((432, 324)))
player = player_img.get_rect(midbottom=start)
vel_y = 0
on_ground = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
if on_ground:
vel_y = JUMP
elif event.type == pygame.KEYUP and event.key in (pygame.K_SPACE, pygame.K_UP):
if vel_y < -4:
vel_y = -4
keys = pygame.key.get_pressed()
dx = 0
if keys[pygame.K_LEFT]:
dx -= SPEED
if keys[pygame.K_RIGHT]:
dx += SPEED
player.x += dx
for wall in walls:
if player.colliderect(wall):
if dx > 0:
player.right = wall.left
elif dx < 0:
player.left = wall.right
vel_y = min(vel_y + GRAVITY, MAX_FALL)
player.y += vel_y
on_ground = False
for wall in walls:
if player.colliderect(wall):
if vel_y > 0:
player.bottom = wall.top
on_ground = True
elif vel_y < 0:
player.top = wall.bottom
vel_y = 0
blobs.update()
for blob in blobs:
if player.colliderect(blob.rect):
if vel_y > 0 and player.bottom < blob.rect.centery:
blob.kill()
vel_y = -8
else:
player.midbottom = start
vel_y = 0
for y in range(0, 360, 72):
for x in range(0, 576, 72):
screen.blit(background, (x, y))
for wall in walls:
screen.blit(block_img, wall)
for blob in blobs:
screen.blit(blob.image, blob.image.get_rect(midbottom=blob.rect.midbottom))
screen.blit(player_img, player)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Thế giới trò chơi
1Bản đồ dạng văn bản
Một màn chơi bằng văn bảnHàng và cộtCác chữ cái mang ý nghĩaNơi người chơi bắt đầuTừng màn hình mộtTự luyện tập: Playground Pygame