من كل جانب
الدرس 6 من 20 في دورة مشروع Pygame: الصمود في القلعة على Coddy.
وحش واحد من نوع slime لا يشكّل حشدًا. أنشئ وحشًا جديدًا كل ثانية. تكون قيمة self.time % 60 صفرًا مرة كل 60 إطارًا، لذا يضيف هذا وحشًا مرة كل ثانية:
def spawn(self):
if self.time % 60 == 0:
self.monsters.add(Monster("slime", edge_point()))يُسمّى إنشاء أشياء جديدة توليدًا. خصّص له طريقته الخاصة: ستغيّر الدروس القادمة عدد مرات التوليد ونوعه، وسيكون كل ذلك ضمن spawn.
استدعِه في update قبل أن تتحرك الوحوش، حتى يخطو الوحش الجديد خطوته الأولى في الإطار الذي يظهر فيه.
التحدي
سهل- أزِل الكائن الوحيد من نوع slime من
Night.__init__. - اكتب
spawn(self): كائن slime عندedge_point()كل 60 إطارًا. - استدعِ
self.spawn()فيupdate، بعد تحرّك الفارس وقبلself.monsters.update(...).
جرّب بنفسك
import random
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}"
def edge_point():
side = random.randint(0, 3)
if side == 0:
return (random.randint(0, WIDTH), -24)
if side == 1:
return (random.randint(0, WIDTH), HEIGHT + 24)
if side == 2:
return (-24, random.randint(0, HEIGHT))
return (WIDTH + 24, random.randint(0, HEIGHT))
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", edge_point()))
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()
جميع دروس مشروع Pygame: الصمود في القلعة
تدرّب بنفسك: Playground لـ Pygame