Menu
CoddyTech

Bắn trúng và ghi điểm

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

Laser va kẻ địch đối đầu theo nhóm với groupcollide. Hình laser là một tia mảnh nằm giữa một hình vuông rộng 48 pixel, nên phép kiểm tra Rect sẽ khiến một laser lệch sang bên 20 pixel vẫn phá hủy được kẻ địch. Hãy kiểm tra hình ảnh bằng mask:

hits = pygame.sprite.groupcollide(enemies, lasers, True, True, pygame.sprite.collide_mask)
for enemy in hits:
    score += 10

Đối số thứ năm là phép kiểm tra, giống như với spritecollide. Tạo self.mask = pygame.mask.from_surface(self.image) cho cả Laser và Enemy, để mask chỉ được tạo một lần, không phải trong mỗi lần kiểm tra.

Lặp qua hits sẽ duyệt từng kẻ địch bị phá hủy: mỗi kẻ địch được 10 điểm. Hiển thị điểm ở góc trên bên trái bằng font = pygame.font.Font(None, 32), tạo một lần trước vòng lặp.

challenge icon

Thử thách

Trung bình

Cộng 10 điểm cho mỗi kẻ địch bị tia laser bắn trúng.

  1. Thêm self.mask cho Laser và Enemy. Đặt score = 0 và tạo phông chữ cỡ 32.
  2. Sau khi cập nhật, kiểm tra va chạm giữa enemies và lasers bằng pygame.sprite.collide_mask, loại bỏ cả hai; cộng 10 điểm cho mỗi kẻ địch bị bắn trúng.
  3. Vẽ f"Score: {score}" tại (10, 10) với màu (240, 240, 240).

Nhấn Chơi rồi bắn: kẻ địch biến mất và điểm số tăng thêm 10. 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()

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()


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

    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))

    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.speed = speed

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


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()
last_shot = 0
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()

    screen.fill((12, 14, 30))
    enemies.draw(screen)
    lasers.draw(screen)
    screen.blit(player.image, player.rect)
    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