Hati
Pelajaran 7 dari 20 dalam kursus Proyek Pygame: Pertahankan Benteng di Coddy.
Monster yang mencapai ksatria mengurangi satu hati. Tanpa jeda setelah terkena serangan, monster yang berdiri di atas ksatria akan mengurangi satu hati setiap frame, kelima hati dalam waktu seperduabelas detik. Jadi, serangan memulai penghitung, hurt, dan selama penghitungannya berjalan, tidak ada yang bisa melukai ksatria:
def take_hits(self):
knight = self.knight
if knight.hurt > 0:
knight.hurt -= 1
elif pygame.sprite.spritecollideany(knight, self.monsters):
knight.hearts -= 1
knight.hurt = 75spritecollideany(sprite, group) memberikan sprite pertama dalam group yang rect-nya bertumpang tindih, atau None.
Game sekarang memiliki status: "playing" dan "lost". Perulangan menjalankan night.update hanya saat game berlangsung, jadi saat hati habis, semuanya berhenti di tempatnya.
Selama hurt menghitung mundur, gambar ksatria hanya saat knight.hurt % 10 < 5: ksatria berkedip, dan pemain melihat alasan tidak ada yang bisa melukainya.
Tantangan
Sedang- Beri ksatria nilai
hearts = 5,max_hearts = 5, danhurt = 0; beriNightstate = "playing". - Tulis
take_hitsseperti di atas; saat jumlah hati mencapai 0, aturself.state = "lost". Panggil fungsi ini terakhir diupdate. - Dalam perulangan, perbarui hanya saat
if night.state == "playing", dan gambar ksatria hanya saatknight.hurt % 10 < 5. - Muat
heart.pngdanheart_empty.pngsebagaiheart_imgdanempty_img. Untuk setiapmax_hearts, gambar hati penuh atau kosong di(8 + i * 34, 6). - Buat
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)dan, saat kalah, gambar"The keep has fallen"di tengah pada (360, 200).
Coba sendiri
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()
def spawn(self):
if self.time % 60 == 0:
self.monsters.add(Monster("slime", edge_point()))
def update(self, keys):
self.time += 1
self.knight.move(keys)
self.spawn()
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()
Semua pelajaran di Proyek Pygame: Pertahankan Benteng
Latihan sendiri: Playground Pygame