Lekce 3 - Pygame - Pong - Příprava
V minulé lekci, Pygame - Kreslení a pohyb, jsme probrali herní cyklus, kreslení základních tvarů a ukázali si, jak objekty pohybovat.
Těžko bychom si pro náš první projekt mohli vybrat lepší hru, než legendární Pong:
Plánujeme hru
Začít programovat cokoliv, než víme, co přesně chceme, není úplně dobrý nápad. Proto, než začneme, bylo by dobré si chvíli sednout, připravit si šálek kávy či čaje a promyslet, co je naším cílem. Odborně se této fázi procesu vývoje software říká analýza.
Po vysoce osvěžujícím šálku teplého nápoje a chvíli přemýšlení můžeme dojít k následujícím požadavkům:
- na obrazovce budou nalevo a napravo obdélníky, které reprezentují hráče
- hráči se mohou pohybovat nahoru a dolů
- mezi nimi bude létat čtverec, představující míč
- míč bude postupem času zrychlovat
- pokud míč narazí do vrchní či spodní části obrazovky nebo hráče, odrazí se
- pokud míč narazí do levé nebo pravé části obrazovky, přičte bod protilehlému hráči
- skóre se zobrazuje nahoře uprostřed obrazovky
- (nastavitelné) druhý hráč může být ovládán počítačem
Stavy hry
Když tedy již zhruba tušíme, jak bude naše hra vypadat, nejspíše jsme došli k závěru, že naše hra bude mít celkem tři stavy:
- Začátek hry, výběr, jestli chceme hrát s druhým hráčem, nebo proti počítači
- Začátek kola, hra je pozastavena, aby se měli hráči čas nachystat
- Samotná hra, která je ukončena až chybou jednoho z hráčů
Zároveň by také nebylo špatné, kdyby naše hra běžela pokaždé se stejným poměrem stran, nezávisle na velikosti obrazovky uživatele.
Co je pro nás nového?
Určitě jste si všimli, že pár věcí jsme se ještě neučili. Jedná se převážně o tato témata.
Kreslení textu
Pokud si chceme na obrazovku vykreslit text, musíme si nejdříve vytvořit písmo.
Systémové písmo
Pokud chceme použít systémové písmo, použijeme:
font = pygame.font.SysFont(font_name, size)
, kde font_name
je jméno nainstalovaného písma a
size
je poté velikost v pixelech.
Seznam všech dostupných systémových písem získáme pomocí
pygame.font.get_fonts()
.
Vlastní písmo
Pokud nechceme použít nějaké již nainstalované písmo, ale místo toho raději nějaké vlastní písmo, které sami přibalíme k našemu programu, nahrajeme jej pomocí:
font = pygame.font.Font(path, size)
Parametr size
zůstává stejný, ale místo jména
systémového písma nyní vkládáme cestu k .ttf
souboru s
naším písmem. Pokud jako path
vložíme None
,
použije se výchozí písmo.
Vykreslení písma
Jakmile máme takto vytvořené písmo, vyrenderujeme jej pomocí:
text = font.render(txt, True, color)
, kde txt
je string, který chceme vyrenderovat;
True
je parametr pro antialiasing, který zaoblí rohy písma
(což je obecně žádoucí) a color
je barva písma.
Nyní bychom měli v proměnné text
uložený povrch, který
nám ještě zbývá vykreslit na obrazovku. Takže pokud bychom chtěli
vykreslit červený text na pozici (10, 10)
, mohl by náš kód
vypadat nějak takto:
font = pygame.font.Font('myfont.ttf', 30) # nahraje písmo uložené v souboru myfont.ttf text = font.render("Cerveny text", True, (255, 0, 0)) screen.blit(text, (10, 10))
Zachování velikosti při libovolné velikosti obrazovky
Doteď jsme si vždy vytvořili proměnnou
screen = pygame.display.set_mode(...)
. Takto jsme museli nastavit
pevné rozměry, nebo zjišťovat rozměry při vykreslení na celou obrazovku.
Mnohem snadnější přístup by ale byl, pokud bychom mohli vykreslovat pouze
pro jedno rozlišení a pak celou obrazovku automaticky převést na jiné.
Tohoto efektu můžeme dosáhnout následovně:
# povrch screen bude mít rozlišení, na které cílíme screen = pygame.Surface((1920, 1080)) # displej bude mít libovolné rozlišení (např. fullscreen) display = pygame.display.set_mode((0, 0)) # klasicky kreslíme vše na screen pygame.draw.rect(screen, (255, 255, 255), pygame.Rect((10, 10), (100, 100))) # ale v závěru kreslící funkce převedeme celý screen na velikost displeje pygame.transform.scale(screen, display.get_size(), display) # a zobrazíme provedené změny na monitoru pygame.display.flip()
Pohybování obdélníky
Pro kreslení obdélníků jsme zadali souřadnice x
a
y
, čímž jsme v každém cyklu vytvořili nový obdélník na
nové pozici. Samotný obdélník v pygame je ale
mnohem mocnější. Pro začátek nám bude stačit znát funkci
rect.move_ip(dx, dy)
, která posune obdélníkem o dx
pixelů doprava a o dy
pixelů dolů. Existuje také funkce
rect.move(dx, dy)
, která ale místo posunutí původního
obdélníku vrátí nový obdélník s posunutím.
Kolize obdélníků
Obdélníky v pygame se za nás také postarají o zjištění kolizí, tedy zda se střetávají s nějakým jiným objektem. Hlavní funkce, které by nás mohly zajímat, jsou:
rect.collidepoint((x, y))
- vracíTrue
, pokud se bod(x, y)
nachází uvnitř obdélníkurect.colliderect(rect2)
- vracíTrue
, pokud mají dva obdélníky průnikrect.collidelist(lst)
- vracíTrue
, pokud alespoň jeden z obdélníků uvnitř seznamu má průnik s hlavnímrect.collidelistall(lst)
- vracíTrue
, pokud všechny z obdélníků uvnitř seznamu mají průnik s hlavním
Matematika
Velká část herního vývoje se bez použití matematiky neobejde. Vezměme si například balón. Ten v naší hře létá pod určitým úhlem a může se odrážet, přičemž úhel odrazu se rovná úhlu dopadu. Abychom byli schopni něco takového vytvořit, potřebujeme znát alespoň základní goniometrické funkce, jednotkovou kružnici a mít povědomí o převodu mezi jednotkami stupňů a radiány.
Jak vidíme, vždy je nejdříve nutné se podívat, co budeme v našem plánovaném programu potřebovat. Pokud vám tato lekce připadala trochu sušší, tak se nebojte, příští lekce bude především o praxi.
V příští lekci, Pygame - Pong - Prostředí a herní objekty, si do hry Pong přidáme hráče, míč a nastavíme herní cyklus.