Từ mọi phía
Bài học 6 trên 25 trong khóa học Dự án Pygame: Trấn giữ thành trì của Coddy.
Một con slime chưa phải là cả một bầy. Quái vật nên xuất hiện từ bên ngoài cửa sổ, ở bất kỳ cạnh nào. Một hàm chọn một cạnh bằng random.randint(0, 3), rồi chọn ngẫu nhiên một vị trí dọc theo cạnh đó, cách ra 24 pixel. Cạnh trên và cạnh dưới trông như sau:
side = random.randint(0, 3)
if side == 0:
return (random.randint(0, WIDTH), -24)
if side == 1:
return (random.randint(0, WIDTH), HEIGHT + 24)Sau đó, tạo một con mới mỗi giây. self.time % 60 bằng 0 sau mỗi 60 khung hình. Việc tạo ra những vật thể mới được gọi là sinh ra; hãy tạo một phương thức riêng cho việc này, spawn, vì các bài học tiếp theo sẽ thay đổi tần suất và loại quái vật được tạo ra.
Gọi phương thức này trong update trước khi quái vật di chuyển, để quái vật mới có bước đi đầu tiên ngay trong khung hình nó xuất hiện.
Thử thách
DễĐưa một slime vào từ một cạnh ngẫu nhiên mỗi giây.
- Thêm
import randomvà viếtedge_point(): cạnh 0 và 1 như trên, cạnh 2 trả về(-24, random.randint(0, HEIGHT))và cạnh 3 cũng tương tự tạiWIDTH + 24. - Xóa slime đầu tiên khỏi
Night.__init__. - Viết
spawn(self): cứ mỗi 60 khung hình, thêm một slime tạiedge_point(). Gọi hàm này trongupdatesau khi hiệp sĩ di chuyển.
Nhấn “Chơi”: cứ mỗi giây, một slime xuất hiện từ một cạnh. Sau đó nhấn “Kiểm tra”.
Tự làm thử
import pygame
WIDTH, HEIGHT = 720, 480
TILE = 48
NIGHT = 60 * 60 * 4
WHITE = (240, 240, 240)
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Hold the Keep")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
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")
MONSTERS = {
"slime": {"image": load("slime.png"), "speed": 1.0},
}
courtyard = pygame.Rect(TILE, TILE, WIDTH - 2 * TILE, HEIGHT - 2 * TILE)
background = pygame.Surface((WIDTH, HEIGHT))
for row in range(HEIGHT // TILE):
for col in range(WIDTH // TILE):
x = col * TILE
y = row * TILE
if courtyard.collidepoint(x, y):
background.blit(floor_img, (x, y))
else:
background.blit(wall_img, (x, y))
def draw(image, center):
screen.blit(image, image.get_rect(center=center))
def clock_text(frames):
seconds = frames // 60
return f"{seconds // 60}:{seconds % 60:02d}"
class Knight(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = knight_img
self.rect = pygame.Rect(0, 0, 24, 24)
self.rect.center = courtyard.center
self.speed = 3
def move(self, keys):
if keys[pygame.K_LEFT]:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT]:
self.rect.x += self.speed
if keys[pygame.K_UP]:
self.rect.y -= self.speed
if keys[pygame.K_DOWN]:
self.rect.y += self.speed
self.rect.clamp_ip(courtyard)
class Monster(pygame.sprite.Sprite):
def __init__(self, kind, pos):
super().__init__()
self.kind = kind
self.image = MONSTERS[kind]["image"]
self.speed = MONSTERS[kind]["speed"]
self.pos = pygame.Vector2(pos)
self.rect = pygame.Rect(0, 0, 28, 28)
self.rect.center = self.pos
def update(self, target):
step = pygame.Vector2(target) - self.pos
if step.length() > 0:
self.pos += step.normalize() * self.speed
self.rect.center = self.pos
class Night:
def __init__(self):
self.knight = Knight()
self.time = 0
self.monsters = pygame.sprite.Group()
self.monsters.add(Monster("slime", (0, 0)))
def update(self, keys):
self.time += 1
self.knight.move(keys)
self.monsters.update(self.knight.rect.center)
night = Night()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
night.update(pygame.key.get_pressed())
screen.blit(background, (0, 0))
knight = night.knight
for monster in night.monsters:
draw(monster.image, monster.rect.center)
draw(knight.image, knight.rect.center)
left = font.render(clock_text(max(0, NIGHT - night.time)) + " until dawn", True, WHITE)
screen.blit(left, left.get_rect(center=(WIDTH // 2, 24)))
pygame.display.flip()
clock.tick(60)
pygame.quit()
Tất cả bài học trong Dự án Pygame: Trấn giữ thành trì
Tự luyện tập: Playground Pygame