35. Skor dan teks — Solusi pekerjaan rumah
Soal 1 — Tampilan skor
Soal. Angka di layar yang berubah dengan tombol panah Atas/Bawah.
Cara memikirkannya. Satu variable integer, dua
pemeriksaan KEYDOWN. Render ulang Surface teks setiap
frame.
Solusi.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Score Display")
clock = pygame.time.Clock()
font = pygame.font.SysFont("arial", 48)
value = 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_UP:
value += 1
if event.key == pygame.K_DOWN:
value = max(0, value - 1)
screen.fill((20, 20, 40))
surf = font.render(str(value), True, (255, 255, 255))
screen.blit(surf, (10, 10))
pygame.display.flip()
clock.tick(60)
pygame.quit()max(0, value - 1) mencegah nilai turun di bawah 0 tanpa
memerlukan pemeriksaan if terpisah.
Kesalahan umum.
- Menggunakan
get_presseduntuk tombol panah di sini.get_pressedterpicu setiap frame saat ditahan, sehingga angka akan naik cepat.KEYDOWNterpicu sekali per penekanan, memberikan kontrol per-penekanan.
Soal 2 — Timer hitung mundur
Soal. Hitung mundur dari 10 ke 0 dan tampilkan
"Time's up!" di akhir.
Cara memikirkannya. Tambahkan 1/60 ke
akumulator setiap frame. Integer yang ditampilkan adalah
10 - int(accumulator), dibulatkan ke bawah ke 0. Saat
akumulator mencapai 10, hitungan mundur selesai.
Solusi.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Countdown")
clock = pygame.time.Clock()
font = pygame.font.SysFont("arial", 64)
small = pygame.font.SysFont("arial", 36)
elapsed = 0.0
DURATION = 10.0
done = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if not done:
elapsed += 1 / 60
if elapsed >= DURATION:
elapsed = DURATION
done = True
remaining = int(DURATION - elapsed)
screen.fill((20, 20, 40))
if done:
surf = small.render("Time's up!", True, (255, 100, 100))
screen.blit(surf, ((800 - surf.get_width()) // 2, 260))
else:
surf = font.render(str(remaining), True, (255, 255, 255))
screen.blit(surf, ((800 - surf.get_width()) // 2, 230))
pygame.display.flip()
clock.tick(60)
pygame.quit()clock.tick(60) mengembalikan jumlah milidetik sejak
panggilan terakhir — alternatif yang lebih akurat untuk timing adalah
clock.tick(60) / 1000.0 sebagai delta time. Untuk latihan
ini, asumsi tepat 60 fps dengan 1/60 sudah cukup.
Kesalahan umum.
- Menghitung
remainingsebagaiDURATION - elapsedsebagai float dan menampilkannya. Timer menampilkan detik pecahan, yang terlihat tidak rapi.int(...)memotong ke detik penuh.
Soal 3 — Kumpulkan dan skor
Soal. Pemain tombol panah, target diposisikan ulang saat disentuh, skor ditampilkan di atas.
Cara memikirkannya. Gabungkan pola kumpul dari bab
34 dengan font.render / screen.blit.
Solusi.
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)
target = pygame.Rect(random.randint(0, W-40), random.randint(0, H-40), 40, 40)
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(target):
score += 1
target.x = random.randint(0, W - target.width)
target.y = random.randint(0, H - target.height)
screen.fill((20, 20, 40))
pygame.draw.circle(screen, (255, 220, 0), target.center, target.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()Tantangan — Tiga nyawa
Soal. Kumpulkan koin (skor), hindari kotak merah (nyawa). Tampilkan keduanya. Game over saat nyawa 0.
Cara memikirkannya. Simpan list kotak merah. Setiap frame, gerakkan setiap kotak sejumlah tetap ke arah pemain (atau dalam arah tetap). Saat bertabrakan dengan pemain, kurangi nyawa dan posisikan ulang kotak. Saat bertabrakan dengan koin, tambah skor dan posisikan ulang koin.
Solusi.
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Three Lives")
clock = pygame.time.Clock()
font = pygame.font.SysFont("arial", 28)
large = pygame.font.SysFont("arial", 64)
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)
enemies = [pygame.Rect(random.randint(0, W-40), random.randint(0, H-40), 40, 40)
for _ in range(3)]
score = 0
lives = 3
speed = 4
enemy_speed = 2
game_over = False
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:
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))
for enemy in enemies:
if enemy.centerx < player.centerx:
enemy.x += enemy_speed
elif enemy.centerx > player.centerx:
enemy.x -= enemy_speed
if enemy.centery < player.centery:
enemy.y += enemy_speed
elif enemy.centery > player.centery:
enemy.y -= enemy_speed
if player.colliderect(enemy):
lives -= 1
enemy.x = random.randint(0, W - enemy.width)
enemy.y = random.randint(0, H - enemy.height)
if lives <= 0:
game_over = True
break
if not game_over and 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)
for enemy in enemies:
pygame.draw.rect(screen, (220, 50, 50), enemy)
pygame.draw.rect(screen, (100, 200, 255), player)
screen.blit(font.render(f"Score: {score}", True, (255, 255, 255)), (10, 10))
screen.blit(font.render(f"Lives: {lives}", True, (255, 200, 200)), (10, 44))
if game_over:
surf = large.render("Game Over", True, (255, 80, 80))
screen.blit(surf, ((W - surf.get_width()) // 2, (H - surf.get_height()) // 2))
pygame.display.flip()
clock.tick(60)
pygame.quit()Musuh bergerak satu langkah menuju pemain setiap frame. Saat musuh
bertabrakan dengan pemain, ia muncul kembali di posisi acak.
break setelah mendeteksi tabrakan mematikan keluar dari
loop musuh lebih awal sehingga hanya satu nyawa yang hilang per frame
meskipun beberapa musuh tumpang tindih dengan pemain.
Kesalahan umum.
- Memodifikasi list saat mengiterasi di atasnya. Solusi di sini hanya
memodifikasi posisi item list, bukan struktur list itu sendiri, jadi
mengiterasi dengan
for enemy in enemiesaman.
Selesai?
Bagian 7 diakhiri dengan dua mini-proyek — Coin Collector dan Collect-All-Coins — yang menggabungkan game loop, menggambar, gerakan, dan skor menjadi program yang bisa dimainkan.