Menu
CoddyTech

Điểm số cao nhất

Thuộc phần Luật chơi trong hành trình Pygame của Coddy. Bài học 19 trên 30.

Điểm số có ý nghĩa hơn khi đặt cạnh điểm cao nhất từ trước đến nay. Lưu điểm cao nhất trong biến riêng và cập nhật ngay khi trò chơi kết thúc:

if lives <= 0:
    state = "over"
    best = max(best, score)

max giữ lại số lớn hơn. Trò chơi có kết quả tốt hơn sẽ nâng best; kết quả kém hơn thì giữ nguyên giá trị.

Vị trí bạn đặt best = 0 rất quan trọng. reset() chạy khi bắt đầu mỗi trò chơi, vì vậy nếu đặt giá trị cao nhất ở đó, mỗi lần nhấn R, giá trị sẽ bị xóa. Hãy đặt giá trị này một lần trước vòng lặp. Nó tồn tại chừng nào chương trình còn chạy.

Hiển thị giá trị này trên màn hình kết thúc trò chơi, bên dưới hai dòng còn lại:

best_text = font.render(f"Best: {best}", True, WHITE)
screen.blit(best_text, best_text.get_rect(center=(240, 240)))
challenge icon

Thử thách

Dễ

Giữ điểm cao nhất của phiên chơi.

  1. Đặt best = 0 một lần, sau state = "menu".
  2. Khi trò chơi kết thúc, đặt best = max(best, score).
  3. Trên màn hình kết thúc trò chơi, hiển thị Best: 12 (cùng với điểm cao nhất) ở giữa tại (240, 240).

Nhấn Chơi rồi để thua: màn hình kết thúc trò chơi hiển thị điểm cao nhất của bạn. Sau đó nhấn Kiểm tra.

Tự làm thử

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((480, 360))
pygame.display.set_caption("Meteor Dodge")
clock = pygame.time.Clock()
heart = pygame.image.load("assets/images/heart.png").convert_alpha()
heart_empty = pygame.image.load("assets/images/heart_empty.png").convert_alpha()
font = pygame.font.Font("assets/fonts/pixel.ttf", 24)
big_font = pygame.font.Font("assets/fonts/pixel.ttf", 48)
WHITE = (240, 240, 240)
PLATE = (60, 60, 90)
POINT = pygame.USEREVENT + 1
SPAWN = pygame.USEREVENT + 2


def reset():
    global player, rocks, score, lives
    player = pygame.Rect(220, 300, 40, 40)
    rocks = []
    score = 0
    lives = 3
    pygame.time.set_timer(POINT, 1000)
    pygame.time.set_timer(SPAWN, 800)


def draw_menu():
    screen.fill((30, 30, 46))
    title = big_font.render("Meteor Dodge", True, WHITE)
    title_rect = title.get_rect(center=(240, 140))
    pygame.draw.rect(screen, PLATE, title_rect.inflate(24, 12))
    screen.blit(title, title_rect)
    hint = font.render("Press Enter to play", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


def draw_game():
    screen.fill((30, 30, 46))
    pygame.draw.rect(screen, (255, 196, 0), player)
    for rock in rocks:
        pygame.draw.rect(screen, (235, 80, 80), rock)
    score_text = font.render(f"{score:05}", True, WHITE)
    score_rect = score_text.get_rect(topright=(470, 10))
    pygame.draw.rect(screen, PLATE, score_rect.inflate(12, 8))
    screen.blit(score_text, score_rect)
    for i in range(3):
        if i < lives:
            screen.blit(heart, (10 + i * 40, 10))
        else:
            screen.blit(heart_empty, (10 + i * 40, 10))


def play_frame():
    global rocks, lives, state
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= 6
    if keys[pygame.K_RIGHT]:
        player.x += 6
    player.clamp_ip(screen.get_rect())

    kept = []
    for rock in rocks:
        rock.y += 3
        if rock.colliderect(player):
            lives -= 1
        elif rock.top <= 360:
            kept.append(rock)
    rocks = kept
    if lives <= 0:
        state = "over"
    draw_game()


def draw_over():
    draw_game()
    message = big_font.render("Game over", True, WHITE)
    screen.blit(message, message.get_rect(center=(240, 160)))
    hint = font.render("Press R to play again", True, WHITE)
    screen.blit(hint, hint.get_rect(center=(240, 200)))


reset()
state = "menu"

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == POINT and state == "play":
            score += 1
        if event.type == SPAWN and state == "play":
            rocks.append(pygame.Rect(random.randint(0, 456), -24, 24, 24))
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN and state == "menu":
                reset()
                state = "play"
            elif event.key == pygame.K_r and state == "over":
                reset()
                state = "play"

    if state == "menu":
        draw_menu()
    elif state == "play":
        play_frame()
    else:
        draw_over()
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Tất cả bài học trong Luật chơi

Tự luyện tập: Playground Pygame