Tworzenie gier w Pythonie z Pygame Zero

11 października 2021

Magia Pythona polega na tym, że w większym lub mniejszym stopniu można go wykorzystać do programowania praktycznie wszystkiego. Czy w takim razie w Pythonie można tworzyć gry? Oczywiście, że tak!

Konieczność poznania wielu nowych pojęć, a także wymóg kontroli nad całym cyklem życia aplikacji sprawia, że tworzenie gier może wydawać się skomplikowane. Jest jednak wiele narzędzi, dzięki którym możemy odłożyć ten (czasem przykry) moment na nieokreśloną przyszłość ;)

 

Python to język, którego nadzwyczajną siłą są tworzone przez miłośników tego języka biblioteki, czyli moduły dołączane do aplikacji. Wykorzystanie odpowiedniego modułu skraca długość pisanego przez nas kodu do minimum, dzięki czemu nie wynajdujemy koła na nowo. Biblioteki te dostarczają nowych funkcji i pozwalają robić rzeczy, o których wcześniej nikomu się nie śniło!

 

Biblioteka Pygame

Najpopularniejszą biblioteką do tworzenia gier w Pythonie jest Pygame. To tak naprawdę cross-platformowy zestaw modułów/bibliotek Pythona, pomocny szczególnie przy tworzeniu gier. Przydają się one głównie przy obsłudze aspektów graficznych oraz audio-wizualnych, które można wykorzystać w miarę przystępny sposób dzięki składni i specyfice Pythona. Jednak pythonowe zen zostaje nieco zaburzone poprzez konieczne do umieszczenia w kodzie elementy opisujące cykl życia gry. Po zainstalowaniu na komputerze (z wykorzystaniem instalatora pakietów Python pip: pip install pygame) modułu Pygame oraz zaimportowaniu go w standardowy sposób do projektu należy ręcznie w kodzie zainicjalizować wszystkie dodatkowe moduły poleceniami:

 

import pygame

pygame.init()

 

natomiast na koniec gry musimy ją zakończyć, wywołując funkcję:

 

pygame.quit()

 

Jakby tego było mało, pisany kod zajmuje trochę miejsca (ustawianie wymiarów planszy: pygame.display.set_mode([800,600]) ), a na koniec, po narysowaniu należy jeszcze ręcznie nadpisać elementy wyświetlane na ekranie funkcją pygame.display.update().

Bez tego ostatniego nie wyświetlą nam się żadne zaktualizowane elementy, czyli nawet prosta animacja obrazka przesuwającego się po ekranie nie będzie działać.

Cała gra jest zamknięta w pętli while, do której musimy dodać opcję jej przerwania (czyli wyjścia z pętli i przejścia bezpośrednio do polecenia pygame.quit()). Poniżej przedstawiamy przykładową pętlę gry:

 

done = False

while not done:

    for zdarzenie in pygame.event.get(): 

        if zdarzenie.type == pygame.QUIT: 

            done = True

 

Jest trochę pisania, prawda? A co by było, gdyby nie trzeba było tego wszystkiego robić?

 

Proste jest lepsze niż złożone

Z pomocą przychodzą autorzy biblioteki Pygame Zero, która jest nakładką na Pygame. Powstała ona właśnie po to, aby obniżyć wysoki próg wejścia w programowanie gier w Pygame, i aby można było się skupić na rzeczach faktycznie istotnych w programowaniu gier: logice i wyświetlaniu elementów. Instalacja może się odbyć zarówno przez narzędzie pip (pip install pgzero), jak i poprzez instalację narzędzia Mu Code. W Mu Code jest ono wgrane domyślnie i nie trzeba się martwić o ręczną instalację potrzebnych modułów poprzez linię komend, ani o to, która wersja Pythona jest zgodna z biblioteką. Na Raspberry Pi Pygame Zero jest ona wgrana domyślnie od 2015 roku, razem z systemem Raspbian Jessie. 

 

Czym zatem różni się Pygame Zero? Chociażby tym, że nawet jeśli nie napiszemy w naszym kodzie nic, jest to dalej działający kod pgzero! Jeśli uruchamiamy kod przez konsolę, wystarczy, że użyjemy polecenia pgzrun moj_program.py. Jeśli korzystamy z IDLE lub innego IDE, które samo uruchamia pliki poprzez polecenie python moj_program.py, powinniśmy dodać na początku pliku:

 

import pgzrun

 

natomiast na samym jego końcu:

 

pgzrun.go()

 

W Mu Code nie musimy dopisywać tych linii, wystarczy, że wybierzemy tryb Pygame Zero.

Zacznijmy jednak od tworzenia planszy. Ustawienie szerokości (np. na 800 pikseli) i wysokości (np. na 600 pikseli) określa się następująco:

 

WIDTH = 800

HEIGHT = 600

 

I to wystarczy! Co się dzieje z pętlą gry? Typowa pętla gry wygląda następująco:

 

while gra_trwa():

    input_użytkownika()

    update()

    rysowanie_elementow()

 

Oznacza ona, że dopóki gra trwa, pobieramy dane od użytkownika poprzez klawiaturę,mysz lub inne urządzenia wejścia, następnie wykonujemy update, w którym dzieje się cała logika naszej gry (zmiany pozycji elementów, strzały itd.), oraz wszystkie elementy rysujemy na ekranie.

 

W Pygame Zero wszystko, co dzieje się w głównej pętli gry, zostało rozbite na poszczególne funkcje. I tak mamy: funkcję update(), w której trzymamy logikę gry, oraz funkcję draw(), w której rysujemy wszystkie elementy na ekranie, a input użytkownika możemy rozbić na funkcje w zależności od rodzaju, np.: on_mouse_down() – działające przez naciśnięcie myszy, on_mouse_move() – przesunięcie myszy, on_key_down() – naciśnięcie klawisza.

 

Gdy uruchomimy program z zadeklarowaną szerokością i wysokością planszy, pokaże nam się czarna plansza o zadeklarowanych wymiarach. Aby wypełnić ją innym kolorem, musimy użyć funkcji draw

 

def draw():

    screen.fill((255,0,0))

 

Tym razem tło jest czerwone. Możemy tutaj używać kolorów z palety RGB, tak jak właśnie zrobiliśmy, możemy też użyć już zadeklarowanych kolorów. Wtedy nasze polecenie wewnątrz funkcji draw będzie wyglądać tak: screen.fill('red').

 

Tworzenie i rysowanie obiektu

Zanim narysujemy obiekt (postać, duszek jak w Scratch), musimy go utworzyć. Wszystkie obiekty, których używamy, muszą się znaleźć w podfolderze /images/. Aby utworzyć duszka z pliku o przykładowej nazwie alien.png, korzystamy z klasy Actor.

 

alien = Actor('alien')

 

Nie musimy pamiętać, jakie rozszerzenie ma nasz obrazek! Biblioteka automatycznie wyszukuje pliki o zadanej nazwie we wspomnianym wyżej katalogu. To jednak nie wystarczy, żeby duszek wyświetlił się na ekranie. Wracamy do funkcji draw i dodajemy tam polecenie: 

 

alien.draw()

 

Teraz wszystko jest OK :) Duszek wyświetla się domyślnie w lewym górnym rogu – punkcie (0,0) naszej planszy. Spróbujmy narysować go gdzieś indziej. Możemy zmienić atrybut pozycji duszka.

 

alien = Actor('alien')

alien.pos = 50, 200

 

Wróćmy do pozycji (0,0) i spróbujmy zaanimować duszka tak, aby spadał po planszy w dół. Potrzebujemy do tego funkcji update, która podobnie jak draw działa co klatkę.

 

def update():

    alien.left += 2

    alien.top += 2

    if alien.top > HEIGHT:

        alien.pos = (0,0)

 

Nasz alien będzie spadał” w prawo, czyli przesuwał się o dwa piksele w dół, i o dwa piksele w prawo co każdą klatkę. Kiedy wypadnie poza planszę, resetujemy go z powrotem na pozycję (0,0).

 

Podsumowanie

Pierwsza animacja w Pygame Zero gotowa! To dopiero przedsmak tego, co was czeka, gdy spróbujecie pisania gier z tą biblioteką. Powodzenia w programowaniu i odkrywaniu pełni możliwości języka i jego niesamowitych bibliotek!

 

----

 
Autor: Iza Saniewska
Materiały dodatkowe / w sieci: