Python - zajęcia 11
1) Python a gry
Python nie jest najlepszy do zrobienia gier, bo jest dość wolny.
Wielu twórców świadomie korzysta z Pythona, na przykład:
Dodatkowo, niektóre silniki do tworzenia gier, takie jak Godot, oferują skrypty bardzo podobne do Pythona.
Na zajęciach będziemy używać biblioteki PyGameZero.
2) PyGameZero
Tworzenie gier wymaga zaplanowania wielu aspektów, takich jak:
- Wyświetlanie grafiki i jej obsługa (np. przesuwanie)
- Odtwarzanie muzyki i efektów dźwiękowych
- Wykrywanie kolizji
- Uruchamianie pętli
- Obsługa urządzeń wejścia/wyjścia
Korzystając z dedykowanych bibliotek lub silników, większość tych podstawowych (i często trudnych) kwestii możemy rozwiązać łatwiej, używając gotowych rozwiązań.
PyGame Zero jest rozszerzeniem PyGame, które upraszcza wiele aspektów, takich jak właściwe zarządzanie pętlą programu.
PyGame Zero Documentation - Installation Guide
Instalacja jest prosta – wystarczy użyć polecenia:
pip install pgzero
Jednak, żeby nie było zbyt łatwo, edytory tekstu mogą nie rozpoznawać wszystkich dodatkowych zależności zainstalowanych wraz z PyGame Zero.
3) Alternatywy dla Pygame
a) Python Arcade
https://api.arcade.academy/
- Biblioteka do gier 2D oparta na Pyglet.
b) RenPy
https://www.renpy.org/
- Zestaw narzędzi do tworzenia powieści wizualnych.
c) Pyglet
https://pyglet.org/
- Biblioteka do tworzenia gier i aplikacji.
Warto pamiętać, że język skryptowy w Godot Engine przypomina Pythona. Wiele dostępnych bibliotek i frameworków oferuje także wsparcie dla Pythona (np. Ogre3D, który ma wiązania Pythonowe. Więc można ją obsłużyć Pythonem).

4) Wstęp do - Poodbijaj.to
Piszemy gre, która wygląda jak to logo DVD, które pojawiało się na ekranie w trybie oczekiwania - tak się odbijało.
import pgzrun
WIDTH = 800
HEIGHT = 600
pgzrun.go()
To fragment kodu, który pojawi się w naszej aplikacji na samym końcu – pgzrun.go()
odpowiada za uruchomienie głównej pętli gry i wyświetlenie wszystkiego, co trzeba. Na tym etapie nie mamy co wyświetlić.
pip install pgzero
5) Niezbędne funkcje i klasy
a) Funkcja draw()
draw.circle(pos, radius, (r, g, b))
W naszym kodzie na pewno będziemy potrzebować funkcji draw
. Odpowiada ona za rysowanie obiektów na ekranie.
import pgzrun
from pgzero_api_stub import *
WIDTH = 800
HEIGHT = 600
def draw():
screen.clear()
screen.draw.circle((400, 300), 30, "white")
pgzrun.go()
400 i 300 to X i y odpowiedzialne za pozycję koła. 30 to promień koła.
b) Funkcja update()
Jeśli mamy obiekty, których stan będzie się zmieniał, potrzebna będzie funkcja update
. To tutaj umieścimy logikę, np. sterowanie, uruchamianie dźwięków przy kolizjach itp.
c) Klasa Actor
Wszędzie tam, gdzie obiekty wchodzą w interakcje, pomocna będzie klasa Actor
. Zapewnia obsługę kolizji, dba o poprawne rozmieszczenie obrazków itp.
d) Metoda .draw.text
z ekranu
Służy do wyświetlania tekstu w grze.
import pgzrun
from pgzero_api_stub import *
WIDTH = 800
HEIGHT = 600
def draw():
screen.clear()
screen.draw.text("Tekst", (100, 100), fontsize=30)
pgzrun.go()
6) Czemu pozycja nie zaczyna się od 0?

7) Ropakowywanie krotki na zmienne
#Definicja krotki
moja_krotka = (1, 2)
#Wyświetlenie całej krotki
print(moja_krotka) # (1, 2)
#Rozpakowanie krotki na zmienne
a, b = moja_krotka
#Wyświetlenie poszczególnych wartości
print(a) # 1
print(b) # 2
8) Cwiczenie - gra Poodbijaj.to
mport pgzrun
from pgzero_api_stub import *
WIDTH = 800
HEIGHT = 600
class PlywajacyTekst:
def __init__(self, tekst :str ="DVD" , wsp_x: int = 0 , wsp_y: int = 0):
self.x = wsp_x
self.y = wsp_y
self.tekst = tekst
self.przesuniecie = 5
def przemieszczenie_tekstu(self):
self.x = self.x + self.przesuniecie
if self.x >= WIDTH or self.x < 0:
self.przesuniecie = self.przesuniecie *-1
else:
self.przesuniecie = self.przesuniecie *1
self.y = self.y + self.przesuniecie
if self.y >= HEIGHT or self.y < 0:
self.przesuniecie = self.przesuniecie *-1
else:
self.przesuniecie = self.przesuniecie *1
def rysuj_tekst(self):
screen.draw.text(self.tekst, (self.x, self.y), fontsize=30)
moj_tekst1 = PlywajacyTekst("tekst1" , wsp_x=10, wsp_y=40 )
def draw():
screen.clear()
moj_tekst1.rysuj_tekst()
def update():
moj_tekst1.przemieszczenie_tekstu()
pgzrun.go()
9) Jak uzupełnić o randomowy ruch
Trzeba skorzystać z biblioteki random i użyć random.randint ( , )
import random
(...)
moj_tekst1 = PlywajacyTekst(wsp_x = random.randint(1, WIDTH),
wsp_y = random.randint(1, HEIGHT )
10) Teraz 10 napisów DVD na raz się przemieszcza
import pgzrun
from pgzero_api_stub import *
import random
WIDTH = 800
HEIGHT = 600
class PlywajacyTekst:
def __init__(self, tekst :str = "DVD" , wsp_x: int = 0 , wsp_y: int = 0):
self.x = wsp_x
self.y = wsp_y
self.tekst = tekst
self.przesuniecie = 5
def przemieszczenie_tekstu(self):
self.x = self.x + self.przesuniecie
if self.x >= WIDTH or self.x < 0:
self.przesuniecie = self.przesuniecie *-1
else:
self.przesuniecie = self.przesuniecie *1
self.y = self.y + self.przesuniecie
if self.y >= HEIGHT or self.y < 0:
self.przesuniecie = self.przesuniecie *-1
else:
self.przesuniecie = self.przesuniecie *1
def rysuj_tekst(self):
screen.draw.text(self.tekst, (self.x, self.y), fontsize=30)
teksty = []
for i in range(10): # Tworzymy 10 poruszających się tekstów
teksty.append(PlywajacyTekst(wsp_x = random.randint(1,WIDTH),wsp_y = random.randint(1,HEIGHT)))
def draw():
screen.clear()
for tekst in teksty:
tekst.rysuj_tekst()
def update():
for tekst in teksty:
tekst.przemieszczenie_tekstu()
pgzrun.go()
11) Gra z paletkami

Na początek potrzebujemy 3 obiekty - TablicaWynikow, Paletka i Pilka.
Paletka i Piłka dziedziczą po klasie Aktor.
W klasie Paletka - musimy mieć metody ruchu po osi y - przesun_gora(), przesun_dol(). W klasie Piłka mamy metode przemiesc_pilke(). Tablica wyników - licz_punkty
Oba powinny wyświetlić się jakimś obrazkiem adekwatnym.

a) Jak wyświetlam piłeczke
Metode draw od Aktora biore:
import pgzrun
from pgzero_api_stub import *
import random
WIDTH = 800
HEIGHT = 600
class MojaNiesamowitaKlasa(Actor):
def __init__(self, obrazek, polozenie):
super().__init__(obrazek, polozenie)
# Tworzymy obiekt na bazie klasy
moj_niesamowity_obiekt = MojaNiesamowitaKlasa("pilka.png", (300, 300))
def draw():
screen.clear()
moj_niesamowity_obiekt.draw()
pgzrun.go()