מפלצת
שיעור 5 מתוך 20 בקורס פרויקט Pygame: להגן על המצודה של Coddy.
מפלצת הולכת ישר לעבר האביר. pygame.Vector2 מכיל ערכי x ו־y שיכולים להיות מספרים עשרוניים, ואפשר לחבר ולחסר ערכי Vector2 שלמים:
step = pygame.Vector2(target) - self.pos
if step.length() > 0:
self.pos += step.normalize() * self.speed
self.rect.center = self.posstep מצביע מהמפלצת אל האביר, רחוק ככל שיהיה. normalize() שומר על הכיוון שלו, אבל הופך את אורכו לפיקסל אחד, כך שכפול self.speed המפלצת נעה בדיוק במהירות שלה בכל פריים, לכל כיוון. Rect מכיל מספרים שלמים בלבד, לכן המיקום המדויק נשמר ב־self.pos וה־Rect עוקב אחריו.
כל סוג של מפלצת מקבל שורה אחת בטבלה, כך שהוספת סוג בהמשך דורשת שורה אחת:
MONSTERS = {
"slime": {"image": load("slime.png"), "speed": 1.0},
}מפלצות מגיעות מחוץ לחלון. edge_point() בוחר צד באמצעות random.randint(0, 3) ומיקום אקראי לאורכו, במרחק 24 פיקסלים ממנו.
אתגר
בינוניimport randomוהוסיפו את טבלתMONSTERSעם הרפש.- כתבו את
edge_point(): צד 0 הוא(random.randint(0, WIDTH), -24), צד 1 הוא אותו הדבר ב־HEIGHT + 24, צד 2 הוא(-24, random.randint(0, HEIGHT))וצד 3 הוא אותו הדבר ב־WIDTH + 24. - כתבו את
class Monster(pygame.sprite.Sprite):__init__(self, kind, pos)שומר אתkind, אתimageואתspeedמהטבלה, אתposכ־Vector2 ואתrectבגודל 28 על 28 שממורכז עליו;update(self, target)נע כפי שתואר לעיל. - בתוך
Night:self.monsters = pygame.sprite.Group()עם רפש אחד ב־edge_point();updateקוראת ל־self.monsters.update(self.knight.rect.center). ציירו כל מפלצת באמצעותdrawלפני האביר.
נסו בעצמכם
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")
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 Night:
def __init__(self):
self.knight = Knight()
self.time = 0
def update(self, keys):
self.time += 1
self.knight.move(keys)
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
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: להגן על המצודה
תרגלו בעצמכם: Pygame אונליין