Menu
CoddyTech

Khựng hình khi trúng đòn

Thuộc phần Âm thanh và cảm giác chơi trong hành trình Pygame của Coddy. Bài học 14 trên 23.

Một đòn đánh mạnh sẽ tạo cảm giác uy lực hơn nếu trò chơi dừng lại trong tích tắc. Các trò chơi đối kháng và hành động luôn làm vậy: khi trúng đòn mạnh, mọi thứ đóng băng trong vài khung hình rồi tiếp tục. Cách này gọi là hit stop.

Hãy dùng lại một bộ đếm để theo dõi số khung hình còn đóng băng. Khi bộ đếm lớn hơn 0, giảm nó xuống và bỏ qua toàn bộ bước cập nhật. Vẫn vẽ khung hình để khoảnh khắc đóng băng tiếp tục hiển thị trên màn hình:

if freeze > 0:
    freeze -= 1
else:
    enemy.x += enemy_speed
    # ... phần còn lại của quá trình cập nhật

Chỉ đặt bộ đếm này khi đòn đánh đủ quan trọng. Ở đây, đòn đánh thứ ba hạ gục kẻ địch, nên đòn đó đặt freeze = 12, tương đương một phần năm giây. Đóng băng trò chơi sau mỗi đòn đánh nhẹ sẽ khiến trò chơi có cảm giác ì ạch thay vì mạnh mẽ.

Bộ đếm hiệu ứng chớp sáng cũng là một phần của bước cập nhật, nên nó cũng phải chờ: kẻ địch vẫn trắng trong suốt thời gian đóng băng, âm thanh vụ nổ vang lên rồi trò chơi tiếp tục. Sự kiện vẫn được xử lý trong lúc đóng băng, nên nếu người chơi nhấn phím lúc đó thì trò chơi vẫn ghi nhận; ở đây, phím Space chỉ đánh trúng khi hp > 0.

challenge icon

Thử thách

Trung bình

Tạm dừng trò chơi trong chốc lát khi tung đòn kết liễu.

  1. Tạo freeze = 0 trước vòng lặp.
  2. Khi đòn đánh khiến hp giảm xuống 0, đặt freeze = 12.
  3. Trong phần cập nhật, khi freeze lớn hơn 0, giảm giá trị này đi 1 và bỏ qua phần còn lại của lần cập nhật. Giữ nguyên phần vẽ.

Nhấn Chơi và đánh kẻ địch ba lần: trò chơi sẽ dừng lại trong chốc lát. Sau đó nhấn Kiểm tra.

Tự làm thử

import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Training Dummy")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)

hit_sound = pygame.mixer.Sound("assets/sounds/hit.ogg")
explosion_sound = pygame.mixer.Sound("assets/sounds/explosion.ogg")
enemy = pygame.Rect(100, 150, 60, 60)
enemy_speed = 2
hp = 3
flash = 0
defeated = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and hp > 0:
            hp -= 1
            flash = 6
            if hp == 0:
                explosion_sound.play()
            else:
                hit_sound.play()

    enemy.x += enemy_speed
    if enemy.left < 40 or enemy.right > 440:
        enemy_speed = -enemy_speed
    if flash > 0:
        flash -= 1
    if hp == 0:
        defeated += 1
        hp = 3
        enemy.x = 100

    screen.fill((30, 30, 46))
    if flash > 0:
        pygame.draw.rect(screen, (255, 255, 255), enemy)
    else:
        pygame.draw.rect(screen, (220, 80, 80), enemy)
    label = font.render(f"HP: {hp}   Defeated: {defeated}", True, (240, 240, 240))
    screen.blit(label, (20, 20))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Tất cả bài học trong Âm thanh và cảm giác chơi

Tự luyện tập: Playground Pygame