Python - zajęcia 11

Python - zajęcia 11
Photo by David Clode / Unsplash

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()