Menu
CoddyTech

受击停顿

本课属于 Coddy Pygame 学习旅程的“音效与游戏体验”单元。第 14 课,共 23 课。

如果游戏暂停一瞬间,重击会显得更有力。格斗和动作游戏经常这样做:受到重击时,所有内容都会冻结几帧,然后继续。这叫作受击停顿。

再次使用计数器,记录还要冻结多少帧。当它大于 0 时,将它递减,并跳过整个更新过程。继续绘制画面,这样冻结的瞬间就会留在屏幕上:

if freeze > 0:
    freeze -= 1
else:
    enemy.x += enemy_speed
    # ……其余更新操作

只在重要的命中时设置它。这里第三次命中会击败敌人,所以这次命中将 freeze = 12,也就是五分之一秒。每次受到小伤害都冻结,会让游戏感觉迟滞,而不是有力。

闪光计数器也是更新的一部分,所以它也会暂停:敌人会在整个冻结期间保持白色,爆炸声会持续响起,然后游戏继续。冻结期间事件仍会运行,所以玩家这时按下按键不会被忽略;这里仅当 hp > 0 时,空格键才会造成命中。

challenge icon

挑战

中等

在造成击败效果的一击后,让游戏暂停片刻。

  1. 在循环之前设置 freeze = 0。
  2. 当这一击让 hp 变为 0 时,设置 freeze = 12。
  3. 在更新逻辑中,当 freeze 大于 0 时,将它减 1,并跳过更新的其余部分。保持绘制逻辑不变。

按“开始”,击中敌人三次:游戏会暂停片刻。然后点击“检查”。

亲手试试

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

音效与游戏体验中的所有课

自己练习: Pygame 在线编辑器