Menu
CoddyTech

Âm nhạc cho từng trạng thái

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 6 trên 23.

Mỗi trạng thái trong trò chơi có thể có nhạc riêng: giai điệu êm dịu ở menu, bản nhạc sôi động khi bạn chơi, giai điệu ngắn khi bạn thắng hoặc thua. Để chuyển nhạc, hãy tải bản nhạc mới rồi phát. Tải bản nhạc mới sẽ dừng bản nhạc cũ. Một hàm nhỏ giúp gộp hai dòng này lại:

def play_music(path, loops=-1):
    pygame.mixer.music.load(path)
    pygame.mixer.music.play(loops)

Chuyển nhạc vào thời điểm trạng thái thay đổi, trên dòng thiết lập state:

if player.colliderect(goal):
    state = "win"
    play_music("assets/music/win.ogg", 0)

Dòng đó chỉ chạy một lần, nên bản nhạc cũng chỉ bắt đầu một lần. Đừng chuyển nhạc bên trong if state == "win": ở phần vẽ: đoạn đó chạy ở mỗi khung hình và khởi động lại bản nhạc 60 lần mỗi giây.

Giai điệu thắng và thua ngắn, tự kết thúc nên chúng dùng loops bằng 0. Giai điệu chủ đề và bản nhạc của màn chơi lặp lại với -1.

challenge icon

Thử thách

Trung bình

Phát nhạc riêng cho từng trạng thái của trò chơi.

  1. Viết play_music(path, loops=-1) để tải và phát một bản nhạc; phát assets/music/theme.ogg trước vòng lặp.
  2. Khi trạng thái chuyển thành "play", phát assets/music/level.ogg.
  3. Khi trạng thái là "win", phát assets/music/win.ogg một lần (loops 0); khi trạng thái là "lose", phát assets/music/lose.ogg một lần.
  4. Khi nhấn Enter để quay lại "menu", phát lại theme.ogg.

Nhấn Chơi, nhấn Enter và đến đích màu xanh lá cây: nhạc sẽ thay đổi mỗi lần. 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("Lava Run")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)

player = pygame.Rect(40, 160, 30, 30)
goal = pygame.Rect(420, 160, 30, 30)
lava = pygame.Rect(0, 320, 480, 40)
state = "menu"

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_RETURN:
            if state == "menu":
                state = "play"
                player.topleft = (40, 160)
            elif state in ("win", "lose"):
                state = "menu"

    if state == "play":
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            player.x -= 4
        if keys[pygame.K_RIGHT]:
            player.x += 4
        if keys[pygame.K_UP]:
            player.y -= 4
        if keys[pygame.K_DOWN]:
            player.y += 4
        player.clamp_ip(screen.get_rect())
        if player.colliderect(goal):
            state = "win"
        elif player.colliderect(lava):
            state = "lose"

    screen.fill((30, 30, 46))
    if state == "menu":
        title = font.render("Press Enter to start", True, (240, 240, 240))
        screen.blit(title, title.get_rect(center=(240, 180)))
    else:
        pygame.draw.rect(screen, (230, 90, 40), lava)
        pygame.draw.rect(screen, (90, 200, 120), goal)
        pygame.draw.rect(screen, (80, 160, 255), player)
        if state == "win":
            message = font.render("You win!", True, (240, 240, 240))
            screen.blit(message, message.get_rect(center=(240, 100)))
        elif state == "lose":
            message = font.render("Game over", True, (240, 240, 240))
            screen.blit(message, message.get_rect(center=(240, 100)))
    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