33. Event dan input — Solusi pekerjaan rumah

Soal 1 — Pelapor tombol

Soal. Cetak tombol mana yang sedang ditahan ke terminal setiap frame; cetak "no key" saat tidak ada yang ditahan.

Cara memikirkannya. Periksa pygame.key.get_pressed() untuk setiap tombol yang kamu pedulikan. Gunakan variable flag untuk mengetahui apakah ada tombol yang cocok. Memeriksa setiap tombol yang mungkin tidak praktis, jadi periksa yang penting — tombol panah, spasi, escape.

Solusi.

import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Key Reporter")
clock = pygame.time.Clock()

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

    keys = pygame.key.get_pressed()
    held = []
    if keys[pygame.K_LEFT]:
        held.append("left")
    if keys[pygame.K_RIGHT]:
        held.append("right")
    if keys[pygame.K_UP]:
        held.append("up")
    if keys[pygame.K_DOWN]:
        held.append("down")
    if keys[pygame.K_SPACE]:
        held.append("space")
    if keys[pygame.K_ESCAPE]:
        running = False

    if held:
        print(", ".join(held))
    else:
        print("no key")

    screen.fill((30, 30, 30))
    pygame.display.flip()
    clock.tick(10)   # slow tick so terminal output is readable

pygame.quit()

clock.tick(10) memperlambat ke 10 fps agar terminal tidak banjir dengan 60 cetakan per detik.

Kesalahan umum.

  • Menggunakan event pygame.KEYDOWN alih-alih get_pressed. KEYDOWN hanya terpicu sekali per penekanan; get_pressed mengembalikan kondisi ditahan saat ini setiap frame.

Soal 2 — Penghitung klik

Soal. Hitung klik kiri dan cetak hitungannya setiap kali bertambah.

Cara memikirkannya. Variable penghitung dimulai dari 0. Pada MOUSEBUTTONDOWN dengan event.button == 1, tambah dan cetak.

Solusi.

import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Click Counter")
clock = pygame.time.Clock()

clicks = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                clicks += 1
                print(f"clicks: {clicks}")

    screen.fill((30, 30, 30))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Kesalahan umum.

  • Memeriksa event.button == 1 di dalam MOUSEBUTTONDOWN penting karena tombol 3 (klik kanan) juga akan memicu MOUSEBUTTONDOWN.

Soal 3 — Penggerak panah

Soal. Lingkaran yang bergerak dengan tombol panah; Escape mengakhiri; cetak "moved" setiap frame lingkaran sedang bergerak.

Cara memikirkannya. Gunakan get_pressed untuk gerakan. Lacak apakah ada tombol gerakan yang ditahan untuk memutuskan apakah perlu mencetak.

Solusi.

import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Arrow Mover")
clock = pygame.time.Clock()

cx, cy = 400, 300
speed = 4

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

    keys = pygame.key.get_pressed()
    moving = False
    if keys[pygame.K_LEFT]:
        cx -= speed
        moving = True
    if keys[pygame.K_RIGHT]:
        cx += speed
        moving = True
    if keys[pygame.K_UP]:
        cy -= speed
        moving = True
    if keys[pygame.K_DOWN]:
        cy += speed
        moving = True

    if moving:
        print("moved")

    screen.fill((30, 30, 30))
    pygame.draw.circle(screen, (255, 100, 100), (cx, cy), 30)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Kesalahan umum.

  • Menaruh pemeriksaan Escape di dalam get_pressed. Escape sebagai tombol keluar adalah aksi satu kali — taruh di KEYDOWN, bukan get_pressed. Keduanya secara teknis berfungsi, tapi KEYDOWN adalah pola yang benar untuk keluar.

Tantangan — Pengikut mouse

Soal. Gambar lingkaran yang mengikuti mouse. Ubah warnanya saat tombol kiri ditahan.

Cara memikirkannya. Lacak boolean button_held. Atur ke True pada MOUSEBUTTONDOWN dan kembali ke False pada MOUSEBUTTONUP. Gunakan untuk memilih warna gambar.

Solusi.

import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Mouse Follower")
clock = pygame.time.Clock()

button_held = False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                button_held = True
        if event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                button_held = False

    mx, my = pygame.mouse.get_pos()
    color = (255, 255, 0) if button_held else (200, 200, 200)

    screen.fill((30, 30, 30))
    pygame.draw.circle(screen, color, (mx, my), 15)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

pygame.mouse.get_pos() mengembalikan posisi kursor saat ini, diperbarui setiap frame. Lingkaran tetap terpusat di kursor.

Kesalahan umum.

  • Menggunakan pygame.mouse.get_pressed()[0] langsung alih-alih melacak MOUSEBUTTONDOWN/MOUSEBUTTONUP. Kedua pendekatan berfungsi. Pendekatan event ditampilkan di sini karena mengikuti pola yang digunakan di bab ini.

Selesai?

Bab 34 menggunakan posisi dan kecepatan untuk membuat objek bergerak di dalam game loop.