Menu
CoddyTech

Trò chơi kết thúc

Thuộc phần Sprite và hình ảnh trong hành trình Pygame của Coddy. Bài học 37 trên 39.

Khi không còn mạng, trò chơi sẽ dừng lại. Mọi thứ làm thay đổi trò chơi đều diễn ra trong phần cập nhật của vòng lặp, vì vậy chỉ cần đặt một if quanh phần đó là cả trò chơi sẽ dừng, trong khi phần vẽ vẫn tiếp tục:

if lives > 0:
    player.update()
    # ... mọi thứ cho đến khi xảy ra va chạm
explosions.update()

Đặt explosions.update() bên ngoài phần đó để vụ nổ kết thúc trò chơi vẫn diễn ra.

Sau đó, thông báo cho người chơi. Chỉ vẽ thông báo khi lives <= 0, rồi căn giữa thông báo bằng get_rect(center=(x, y)), giống như bộ đếm Lives đã dùng topright.

challenge icon

Thử thách

Trung bình

Kết thúc trò chơi khi số mạng còn lại bằng 0.

  1. Đặt phần cập nhật, từ player.update() đến phần xử lý va chạm, bên trong if lives > 0:. Để explosions.update() ở bên ngoài.
  2. Khi lives <= 0, vẽ Game over ở chính giữa tại (320, 240).

Nhấn Chơi và để ba kẻ địch lọt qua: Game over sẽ xuất hiện và mọi thứ dừng lại. Sau đó nhấn Kiểm tra.

Tự làm thử

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Star Patrol")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)

ship_image = pygame.image.load("assets/images/ship.png").convert_alpha()
laser_image = pygame.image.load("assets/images/laser.png").convert_alpha()
red_image = pygame.image.load("assets/images/enemy_red.png").convert_alpha()
explosion_frames = []
for number in range(1, 5):
    explosion_frames.append(pygame.image.load(f"assets/images/explosion_{number}.png").convert_alpha())


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = ship_image
        self.rect = self.image.get_rect(midbottom=(320, 470))
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 6
        if keys[pygame.K_RIGHT]:
            self.rect.x += 6
        self.rect.clamp_ip(screen.get_rect())


class Laser(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = laser_image
        self.rect = self.image.get_rect(midbottom=(x, y))
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        self.rect.y -= 10
        if self.rect.bottom < 0:
            self.kill()


class Enemy(pygame.sprite.Sprite):
    def __init__(self, image, x, y, speed):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(center=(x, y))
        self.mask = pygame.mask.from_surface(self.image)
        self.speed = speed

    def update(self):
        self.rect.y += self.speed


class Explosion(pygame.sprite.Sprite):
    def __init__(self, center):
        super().__init__()
        self.index = 0
        self.timer = 0
        self.image = explosion_frames[0]
        self.rect = self.image.get_rect(center=center)

    def update(self):
        self.timer += 1
        if self.timer == 5:
            self.timer = 0
            self.index += 1
            if self.index == len(explosion_frames):
                self.kill()
            else:
                self.image = explosion_frames[self.index]


def spawn_wave(image, count, speed):
    for i in range(count):
        x = random.randint(40, 600)
        enemies.add(Enemy(image, x, -40 - i * 120, speed))


player = Player()
lasers = pygame.sprite.Group()
enemies = pygame.sprite.Group()
explosions = pygame.sprite.Group()
last_shot = 0
score = 0
lives = 3
spawn_wave(red_image, 6, 2)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    player.update()
    keys = pygame.key.get_pressed()
    now = pygame.time.get_ticks()
    if keys[pygame.K_SPACE] and now - last_shot >= 250:
        lasers.add(Laser(player.rect.centerx, player.rect.top))
        last_shot = now
    lasers.update()
    enemies.update()
    for enemy in enemies:
        if enemy.rect.top > 480:
            enemy.kill()
            lives -= 1
    hits = pygame.sprite.groupcollide(enemies, lasers, True, True, pygame.sprite.collide_mask)
    for enemy in hits:
        score += 10
        explosions.add(Explosion(enemy.rect.center))
    crashes = pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_mask)
    for enemy in crashes:
        lives -= 1
        explosions.add(Explosion(enemy.rect.center))
    explosions.update()

    screen.fill((12, 14, 30))
    enemies.draw(screen)
    lasers.draw(screen)
    screen.blit(player.image, player.rect)
    explosions.draw(screen)
    score_text = font.render(f"Score: {score}", True, (240, 240, 240))
    screen.blit(score_text, (10, 10))
    lives_text = font.render(f"Lives: {max(lives, 0)}", True, (240, 240, 240))
    screen.blit(lives_text, lives_text.get_rect(topright=(630, 10)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Tất cả bài học trong Sprite và hình ảnh

Tự luyện tập: Playground Pygame