35. Skor dan teks

Hampir setiap game menampilkan informasi di layar: skor, timer, pesan saat pemain menang atau kalah. pygame bisa merender teks menggunakan font sistem atau font bawaan. Bab ini membahas menampilkan teks, melacak skor, dan membangun kondisi menang/kalah sederhana.

Memuat font

Sebelum merender teks apa pun, buat objek font. Dua cara:

# Use a system font by name (Arial is available on Windows/Mac/most Linux)
font = pygame.font.SysFont("arial", 32)

# Use pygame's built-in default font (no name needed, always available)
font = pygame.font.Font(None, 32)

Argumen kedua adalah ukuran dalam poin. Buat objek font sekali, sebelum game loop — membuatnya di dalam loop setiap frame itu lambat.

Merender teks ke Surface

font.render(text, antialias, color) mengonversi string menjadi Surface (gambar kecil dari teks tersebut):

surface = font.render("Hello, world!", True, (255, 255, 255))
  • text — string yang akan digambar. Harus berupa string; konversi angka dengan str() atau gunakan f-string.
  • antialiasTrue untuk tepi halus, False untuk tepi piksel tajam. True terlihat lebih baik pada ukuran yang lebih besar.
  • color — tuple RGB untuk warna teks.

font.render mengembalikan sebuah Surface. Gambar di layar dengan screen.blit.

Blitting (menggambar) sebuah surface

screen.blit(source_surface, (x, y)) menyalin sebuah surface ke screen di posisi (x, y). Posisi adalah sudut kiri atas dari gambar yang ditempelkan:

text_surface = font.render("Score: 0", True, (255, 255, 255))
screen.blit(text_surface, (10, 10))

Ini menggambar "Score: 0" di dekat sudut kiri atas jendela.

Panggil blit di dalam bagian gambar game loop, setelah screen.fill dan sebelum pygame.display.flip.

Menampilkan skor

Pola standar: render Surface baru setiap frame dari nilai skor saat ini.

import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Score")
clock = pygame.time.Clock()
font  = pygame.font.SysFont("arial", 28)

score = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                score += 1   # increase score on spacebar

    screen.fill((20, 20, 40))

    # Render and blit the score each frame
    score_surf = font.render(f"Score: {score}", True, (255, 255, 255))
    screen.blit(score_surf, (10, 10))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Merender Surface baru setiap frame dari f-string adalah cara idiomatik pygame. Surface itu kecil dan murah untuk dibuat. Jangan di-cache — selalu render ulang agar tampilan sesuai dengan nilai saat ini.

Melacak skor dengan tabrakan

Dalam game, skor biasanya bertambah saat pemain mengumpulkan sesuatu. Kombinasikan tampilan skor dengan pola tabrakan dari bab 34:

import pygame
import random

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Collect")
clock = pygame.time.Clock()
font  = pygame.font.SysFont("arial", 28)
W, H  = 800, 600

player = pygame.Rect(370, 270, 50, 50)
coin   = pygame.Rect(random.randint(0, W-30), random.randint(0, H-30), 30, 30)
score  = 0
speed  = 5

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= speed
    if keys[pygame.K_RIGHT]:
        player.x += speed
    if keys[pygame.K_UP]:
        player.y -= speed
    if keys[pygame.K_DOWN]:
        player.y += speed

    player.clamp_ip(pygame.Rect(0, 0, W, H))

    if player.colliderect(coin):
        score += 1
        coin.x = random.randint(0, W - coin.width)
        coin.y = random.randint(0, H - coin.height)

    screen.fill((20, 20, 40))
    pygame.draw.circle(screen, (255, 220, 0),
                       coin.center, coin.width // 2)
    pygame.draw.rect(screen, (100, 200, 255), player)

    score_surf = font.render(f"Score: {score}", True, (255, 255, 255))
    screen.blit(score_surf, (10, 10))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Kondisi menang dan kalah

Kondisi menang memeriksa apakah pemain telah mencapai tujuan. Saat kondisi terpenuhi, hentikan pembaruan game dan tampilkan pesan.

WIN_SCORE = 10

# In the update section:
if score >= WIN_SCORE:
    game_over = True
    message = "You win!"

Pendekatan sederhana: gunakan boolean game_over. Saat True, lewati pembaruan gerakan dan tabrakan tapi terus gambar, dan gambar pesan di atasnya.

game_over = False
message   = ""

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False

    if not game_over:
        # ... movement and collision ...
        if score >= WIN_SCORE:
            game_over = True
            message   = "You win! Press Escape to exit."

    screen.fill((20, 20, 40))
    # ... draw player, coins, score ...

    if game_over:
        msg_surf = font.render(message, True, (255, 220, 0))
        screen.blit(msg_surf, (200, 250))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Pola yang sama berfungsi untuk kondisi kalah: jika timer <= 0, atur game_over = True dan pesan "Time's up!".

Memusatkan teks

Untuk memusatkan teks secara horizontal, cari lebarnya dan kurangi separuh dari pusat x jendela:

msg_surf = font.render("Game Over", True, (255, 255, 255))
text_x   = (800 - msg_surf.get_width())  // 2
text_y   = (600 - msg_surf.get_height()) // 2
screen.blit(msg_surf, (text_x, text_y))

get_width() dan get_height() mengembalikan dimensi piksel Surface teks yang dirender.

Buka exercises/35/01-click-score.py. Setiap klik mouse kiri menambah penghitung skor. Tampilkan skor di layar di (10, 10). Saat skor mencapai 5, tampilkan pesan "Done!" di tengah jendela.

Pekerjaan Rumah

Soal 1 — Tampilan skor

Buka exercises/35/homework/01-score-display.py. Gambar angka di layar yang dimulai dari 0. Tekan panah Atas untuk menambahnya, panah Bawah untuk menguranginya (minimum 0). Angka harus langsung diperbarui di layar.

Soal 2 — Timer hitung mundur

Buka exercises/35/homework/02-countdown.py. Tampilkan timer yang menghitung mundur dari 10 ke 0. Gunakan clock.tick(60) untuk mengontrol kecepatan, dan lacak waktu yang telah berlalu dengan menambahkan 1/60 ke akumulator float setiap frame. Saat hitungan mencapai 0, tampilkan "Time's up!" dan hentikan penghitungan.

Soal 3 — Kumpulkan dan skor

Buka exercises/35/homework/03-collect.py. Gunakan penggerak tombol panah dan pola tabrakan. Setiap kali pemain menyentuh target, tambahkan satu ke skor dan posisikan ulang target. Tampilkan skor di bagian atas layar.

Tantangan — Tiga nyawa

Buka exercises/35/homework/04-three-lives.py. Pemain mengumpulkan koin (skor += 1 per koin). Satu set kotak merah bergerak menuju pemain (kamu bisa memilih arah gerakan sederhana per kotak). Jika pemain menyentuh kotak merah, lives -= 1 dan kotak tersebut muncul kembali. Tampilkan "Score: X" dan "Lives: X" di layar. Saat nyawa mencapai 0, tampilkan "Game Over" dan hentikan game.

Macet atau sudah selesai? Buka halaman solusi pekerjaan rumah.