6. diel - Skákačka v Pygame - Plánujeme hru
V nasledujúcom tutoriále Pygame zahájime väčší
projekt. Ukážeme si postupne, ako naprogramovať prvú poriadnu hru pomocou
knižnice Pygame
– Skákačku. V tejto lekcii sa zameriame na
zložkovú štruktúru a hernú slučku. Hra
bude vyzerať takto:
Plánujeme Skákačku v
Pygame
Pred každým veľkým projektom je najskôr potrebné ujasniť si naše predstavy o ňom. Najprv si teda rozoberieme, čo vlastne definuje takú „poriadnu“ hru:
- herný engine, čo riadi celú hru,
- grafické objekty ako múr alebo figúrka hráča, schopné detekovať kolízie s inými objektmi, či pohybovať sa,
- rôzne ťažké levely,
- hudba v pozadí.
Game
. Ten bude obsahovať hernú slučku, ktorá bude
operovať s
Pygame `eventy. Se zvukem jsme již také pracovali. V knihovně `Pygame
s ním operuje modul pygame.mixer
a jeho podtrieda
pygame.mixer.Sound
, ktorým musíme odovzdať zdrojový súbor
zvuku. Čo pridáme nanovo, budú grafické objekty a levely.
Grafika
Grafické objekty sú v niečom podobné zvukom. V Pygame
ich
síce nereprezentuje samotná trieda, ale rovnako ako pri
pygame.mixer.Sound
je na ich operovanie potrebná tá grafická
časť – obrázok v pamäti. Pretože ich budeme musieť ovládať sami,
zaslúži si vlastnú triedu. Najlepšie jednu pre obrázky všeobecne a potom
pre každý typ jednu podtriedu, ktorá bude dediť z triedy sebe
nadradené.
Levely
Čo sa levelov týka, tie si tiež budeme musieť uložiť externe mimo kódu. Aby sa nám jednotlivé úrovne dobre vymýšľali, hodilo by sa ich mať graficky. Lenže to by sa zase veľmi zle čítalo počítaču. Zvoľme preto kompromis a spracujme ich ako text. Zavedieme kľúčové slová/znaky pre jednotlivé objekty, z ktorých sa bude skladať daná herná plocha. Na prenos tohto typu dát sa momentálne používajú tri formáty.
CSV a XML
CSV je skratka z anglického comma separated values, čiže čiarkami
oddelenej hodnoty. Názov je v tomto prípade veľmi výstižný: čiarkami
oddelenej hodnoty sú totiž zhruba všetko, čo v tomto formáte nájdeme. Keby
sme si teda chceli uložiť náš level, vyzeralo by to napríklad takto:
zeď, hráč, vzduch, vzduch, cíl
.
No dobrá, ale čo keby sme chceli viacriadkové levely? A ako by sme úrovne vôbec odlíšili od seba? CSV je skvelé, keď potrebujeme prenášať obrovské množstvo dát, pretože jediné, čo obsahuje, sú dáta samotné. To sa nám ale príliš nehodí.
Naproti tomu XML toto má vyriešené pekne. Používa totiž hierarchickú
štruktúru podobnú HTML. Vďaka tomu však znateľne narastá objem dát. Už
len na uloženie jedného prvku by sme potrebovali tri „slová“:
počiatočný tag, vlastný prvok a koncový tag. My však nebudeme potrebovať
toľko hierarchických oddielov, aby sa nám XML
vyplatilo. Takže
čo s tým?
JSON
JSON je formát, ktorý kombinuje prednosti CSV aj XML – má dobre vyvinutú hierarchiu a nie je tak pamäťovo rozsiahly. Ponúka sa otázka, prečo sa teda nepoužíva iba JSON. Je to preto, že obe z týchto výhod robí o niečo horšie ako pôvodné formáty. Na naše účely je však JSON ideálnym kompromisom. Dáta totiž radia do štruktúr podobných slovníkom a zoznamom v Pythone. To nám výrazne uľahčí vytváranie ich alternatív v programe.
Logovanie
Formáty všetkého máme rozhodnuté, zostáva teda už len posledný krok
do začiatku programovania. Púšťame sa do veľkého projektu av tých je
občas zložité sa vyznať. Preto do nášho kódu zahrnieme aj knižnicu
logging
. Tá umožňuje programu poslať upozornenie, že nastala
určitá situácia. Tá býva obvykle popísaná, pričom tento popis môže
obsahovať aj hodnoty premenných. Navyše táto knižnica umožňuje zaviesť
samostatný súbor, kam sa tieto správy budú ukladať, či rozlíšiť
dôležitosť a úroveň hlásenia.
Štruktúra
Poďme si teda pripraviť štruktúru nášho kódu. Vytvoríme si zložku
nášho projektu a pomenujeme ju Skakacka/
. V nej vytvoríme súbor
main.py
, ktorý bude prvé, čo sa spustí. Pre ďalší kód
pridáme podpriečinky engine/
a game_scr/
, kde budú
zdroje objektov hry, a res/
(skratka z resources), kam budeme
ukladať všetky nekódové časti našej hry – obrázky, zvuky, alebo aj
fonty. Podľa týchto zdrojov vytvoríme aj podzložky v res/
:
fonts/
, imgs/
, sounds/
a
music/
. Rozlíšime tak zároveň aj zvuky, čo sa prehrajú raz
pri nejakej akcii (sounds) a hudbu, čo bude hrať v pozadí (music).
Herná slučka
Teraz už sa môžeme vrhnúť na samotné programovanie. V priečinku
engine/
vytvoríme súbor game.py
. Tu bude hlavná
časť celého programu - trieda Game. Naimportujeme sem teda knižnicu Pygame a
vytvoríme zatiaľ prázdnu triedu Game
. V jej konštruktore
zároveň zinicializujeme samotnú inštanciu pygame
:
import pygame class Game: def __init__(self): pygame.init()
Do konštruktora tiež pridáme parameter self._is_running
,
ktorý tu nastavíme na True
. Pretože tento parameter by sa mal
ovplyvňovať iba cez metódy triedy (keďže má podčiarknutie na začiatku
názvu – v Pythone nám to síce nikto nezakáže, ale je to programátorská
konvencia), zodpovedajúcu metódu musíme vytvoriť. Vzhľadom na to, že
self._is_running
nám hovorí, či hra beží alebo nie, našu
metódu pomenujeme end()
, aby bolo jasné, že našu hru
ukončuje:
class Game: def __init__(self): self._running = True pygame.init() def end(self): self._running = False
Posledná metóda, ktorú si v tejto lekcii vytvoríme, bude
run()
. Ako už názov napovedá, v tejto metóde pobeží samotná
hra. Bude sa tu teda nachádzať naša stará známa herná slučka. Tá ako
obvykle pobeží, pokiaľ bude self._is_running
rovné
True
a pre každý priechod slučkou načíta zoznam
vygenerovaných eventov. Ak jeden z nich bude pygame.QUIT
, potom
zavolá self.end()
a zatvorí pygame
:
class Game: def __init__(self): self._running = True pygame.init() def end(self): self._running = False def run(self) -> None: while self._running: for event in pygame.event.get(): if event.type == pygame.QUIT: self.end() pygame.quit()
Ak by sme si teraz vytvorili inštanciu Game
a zavolali na nej
metódu run()
, dôjdeme k zaujímavému záveru: nič sa nestane:-)
To preto, že knižnica pygame
sa iba úspešne zinicializovala a
nič iné podľa programu robiť nemala. Aby sme sa však uistili, že všetko
robíme správne, vytvoríme si ešte okno, ktoré na nás po začiatku hry
vyskočí. Do konštruktora triedy Game
pridáme teda
self.display: pygame.Surface = pygame.display.set_mode((600, 600))
a do našej slučky pod for
cyklus pridáme
pygame.display.flip()
. Celý program teda momentálne vyzerá
takto:
import pygame class Game: def __init__(self): self._running = True pygame.init() self.display: pygame.Surface = pygame.display.set_mode((600, 600)) def end(self): self._running = False def run(self) -> None: while self._running: for event in pygame.event.get(): if event.type == pygame.QUIT: self.end() pygame.display.flip() pygame.quit() game = Game() game.run()
Tento program po spustení vytvorí čierne okno, ktoré budeme môcť zavrieť. Nabudúce sa v tvorbe našej hry zase posunieme o kus ďalej. Zdrojový kód vrátane adresárovej štruktúry Skákačky nájdete na konci lekcie.
V ďalšej lekcii Skákačka v Pygame - Logging zistíme, ako si udržať prehľad o priebehu
projektu našej Skákačky pomocou knižnice logging
.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 11x (4.7 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python