Rozdział 20 · Tworzenie gier z Pygame

Projekt końcowy: „Skacząca Piłka”

Ta sama piłka co w sekcji 20.5 — ale teraz z architekturą, która przetrwa rozwój projektu do ponad jednego pliku.

Wróćmy ostatni raz do odbijającej się piłki z sekcji 20.5, ale teraz ją złóżmy na nowo Ponowne wykorzystanie wszystkiego, co rozdział dodał po drodze: architektury klas Game (Rozdział 20.26), ruch przez delta time (Rozdział 20.16) oraz jawne stany gry (Rozdział 20.25).

myach : BouncingBallGamestate = SostoyanieIgry.IGRAx, y = 38.7, 328.8vx, vy = -182.5,…-122,9 # pikseli wdrugiotskokov = 7schet = 70
Rzeczywisty stan działającej gry w konkretnym momencie czasu — to, co faktycznie jest przechowywane w pamięci między klatkami. Zwróć uwagę na dwie prawidłowości: wynik zawsze jest równy liczbie odbić pomnożonej przez 10, a długość wektora prędkości pozostaje równa 220 pikseli na sekundę — odbicie zmienia kierunek, ale nie zmienia wielkości.

Co się zmieniło w porównaniu z wersją 20.5

bouncing_ball_basic.py (20.5)bouncing_ball.py (ta wersja, Pro)
Organizacja KodeksuZmienne globalne, funkcje płaskieGame klas z handle_events/update/render/run metodami
Wniosekx += dx na klatkę – zależy od FPSx += vx * dt — nie zależy od FPS (rozdział 20.16)
PauzaTakZjada, zatrzymuje update(), nie tylko renderowanie
RestartNie, musisz zrestartować programKlucz, bez restartowania procesu
OcenaTakLiczba punktów i licznik odbić
Interakcja mysząTakKliknięcie myszką — opcjonalny obrót piłki w stronę kliknięcia
bouncing_ball_pro_fragment.py
class BouncingBallGame:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((SHIRINA, VYSOTA))
        self.clock = pygame.time.Clock()
        self.state = SostoyanieIgry.IGRA
        self.running = True
        self._reset_myach()

    def update(self, dt):
        if self.state is not SostoyanieIgry.IGRA:
            return
        self.x += self.vx * dt
        self.y += self.vy * dt
        if self.x - RADIUS < 0 or self.x + RADIUS > SHIRINA:
            self.vx = -self.vx
            self.otskokov += 1
        if self.y - RADIUS < 0 or self.y + RADIUS > VYSOTA:
            self.vy = -self.vy
            self.otskokov += 1
Real Window: Czerwona piłka na górnej krawędzi ciemnoniebieskiego boiska, tekst w lewym górnym rogu „Score: 10 Zbiórki: 1”
Rzeczywiste okno: finalna Pro-wersja podczas gry — wynik i liczba odbić rosną razem, jak powinny zgodnie z regułą punktacji: jedno odbicie to dziesięć punktów.
Prawdziwe okno: ta sama piłka i wynik, z żółtym napisem „PAUSE – P to continue”
Realne okno: stan PAUZY – nakład na zamrożoną klatkę, dokładnie w tej samej pozycji co przed naciskiem pauzy.

Kompletny, już zeskanowany plik – osobno:

projects/pygame/bouncing-ball/bouncing_ball.py

★★ Zadanie samodzielne
Zderzenie piłka z piłką

Dodaj drugą kulę i zderzenie między tymi dwoma kulami na colliderect() (Rozdział 20.21), nie tylko ścianami.

Challenge
Menu i Game Over

Dodaj stany MENU i GAME_OVER (sekcja 20.25): gra zaczyna się w MENU po naciśnięciu klawisza, a po określonej liczbie odbić przechodzi do GAME_OVER z końcowym wynikiem na ekranie.

Praktyka: Składanie wersji Pro-
Pygame otwiera natywne okno Python – uruchomione lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Otwórz praktykę →

Podsumowanie rozdziału

Czego nauczyliśmy się w tym rozdziale

  • Pygame jest biblioteką, a nie silnikiem: zapewnia okno, renderowanie, wejście i dźwięk, a strukturę gry budujesz samodzielnie (Rozdział 20.8).
  • Tworzenie gier — cały świat ról, gatunków i platform, a Pygame pewnie obsługuje przede wszystkim desktop, a web i mobile — przez oddzielne narzędzia społeczności (rozdziały 20.6–20.13, 20.29–20.31).
  • W tym rozdziale zbudowaliśmy pętlę gry według podstawowego wzoru Input → Update → Render, powtarzanego dziesiątki razy na sekundę (Rozdział 20.14).
  • Ruch piksel na klatkę zależy od czyjegoś sprzętu; ruch przez delta time nie jest (Rozdział 20.16).
  • pygame.Rect i colliderect() — podstawa kolizji, a hitbox nie musi pokrywać się z obrazkiem (rozdział 20.21).
  • Jawne stany gry (enum) oraz separacja handle_events(), update(dt), render() i run() to prosta i użyteczna architektura dla projektów Pygame- oraz dobra podstawa do kolejnego rozdziału (sekcje 20.25–20.26).