Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

2. diel - Pygame - Kreslenie a pohyb

V minulej lekcii, Pygame - Úvod & inštalácia , sme si pygame predstavili a nainštalovali. V dnešnej lekcii sa naučíme, ako kresliť tvary na obrazovku a ako s nimi pohybovať. Zároveň si tiež povieme niečo málo o tom, ako má vyzerať herný cyklus.

Spätná kompatibilita

Aby sme zachovali spätnú kompatibilitu so všetkými verziami pygame, budeme importovať pygame nasledujúcim spôsobom:

try:
    # noinspection PyUnresolvedReferences
    import pygame_sdl2

    pygame_sdl2.import_as_pygame()
except ImportError:
    pass
import pygame

Tento postup nám zaručí, že nech už máme nainštalovanú akúkoľvek verziu pygame, budeme sa na ňu môcť odkazovať iba pomocou pygame.

Otvárame naše prvé okno

Keď chceme pygame používať, musíme ho najskôr inicializovať. K tomu slúži funkcia pygame.init().

Akonáhle máme inicializácii dokončenú, vytvoríme si okno hry. Okno sa vytvára pomocou funkcie pygame.display.set_mode(). Funkcia berie ako svoj prvý parameter tuple s rozmermi vytvoreného okna:

pygame.init()
screen = pygame.display.set_mode((800, 600))  # vytvoří okno o velikosti 800x600

Ak chceme okno maximalizovať cez celú obrazovku, ako hodnoty použijeme 0. Zároveň, ak by sme chceli odstrániť všetky okná, ako druhý parameter použijeme pygame.FULLSCREEN.

pygame.init()
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN) # vytvoří fullscreen okno

Upozornenie: Vytváranie okna vo fullscreen bez predchádzajúcej implementácia ukončenia pygame spôsobí, že sa objavia čierne okno cez celú obrazovku, ktoré zachytáva všetky klávesy. Dostať sa z takéhoto okna je vysoko ťažké.

Vďaka tomuto máme v premennej screen uložený objekt typu Surface, čo je v pygame reprezentácie akejkoľvek grafiky.

Keď nás potom naše okno prestane baviť, použijeme funkciu pygame.quit(), ktorá ukončí celé pygame.

Kreslíme tvary

Ak chceme v pygame maľovať rôzne tvary, ponúka nám jednoduchú možnosť skrze svoj podmodul pygame.draw.

Ukážeme si najčastejšie príklady:

  • kruh: pygame.draw.circle(povrch, barva, (x, y), poloměr) - (x, y) udáva stred
  • obdĺžnik: pygame.draw.rect(povrch, barva, obdélník), kde obdĺžnik je objekt triedy Rect. Ten ide vytvoriť ako pygame.Rect(x, y, sirka, vyska). x a y udáva pozíciu ľavého horného rohu.
  • polygón: pygame.draw.polygon(povrch, barva, body), kde body je zoznam tuple vo formáte (x, y)
  • čiara: pygame.draw.line(povrch, barva, start_pozice, konec_pozice)

Farba je tuple vo formáte (červená, modrá, zelená, [průhlednost]), kde všetky hodnoty sú int z rozsahu 0 - 255.

Všetky tieto funkcie majú tiež voliteľný parameter width. U čiary určuje jej hrúbku, u ostatných tvarov určuje hrúbku ich výplne. Ak je width nastavený na 0, čo je predvolená hodnota, tvar je plne vyplnený.

Povrch je ľubovoľný objekt triedy Surface, takže ním môže byť akýkoľvek obrázok, alebo dokonca aj naše okno.

Kruh

Poďme si naše novo nadobudnuté vlastnosti hneď vyskúšať a Namaľujte si modrý kruh!

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.draw.circle(screen, (0, 0, 255), (400, 300), 150)

Skúste si tento kód spustiť. Čo sa stane?

Herné cyklus

V predchádzajúcom príklade sa nám okno otvorilo iba na chvíľu a hneď sa zavrelo. A ani ten kruh nebol vidieť. Čo sa stalo zle?

Odpoveď je jednoduchá: Interpreter došiel na koniec kódu a ukončil teda jeho implementácie. Zároveň sme nevideli ani na chvíľu náš kruh, pretože sme nepoužili funkciu na vykreslenie nového obsahu do okna. Poďme to teda hneď napraviť.

Definujme si nový pojem - krok. Krok je všetok kód, ktorý chceme, aby sa periodicky vykonával vnútri našej hry. V našom doterajšom kóde máme iba jeden krok, po ktorom sa vykonávania celej našej hry ukončí. Tomu zamedzíme tým, že všetok kód, ktorý sa má vykonávať, uzavrieme do slučky while True. Na koniec slučky potom ešte nesmieme zabudnúť pridať pygame.display.flip(), čo spôsobí aktualizáciu obrazovky:

pygame.init()

while True:
    screen = pygame.display.set_mode((800, 600))
    pygame.draw.circle(screen, (0, 0, 255), (400, 300), 150)
    pygame.display.flip()

výsledok:

Náhľad okná pygame v Pythone - Pygame

Používame udalosti

Možno ste si všimli, že okno pygame nešlo zavrieť inak, než za použitia Ctrl + C v termináli. To je spôsobené tým, že nijako neodchytáváme udalosť žiadosti o zatvorenie okna. Takéto správanie nie je príliš intuitívne a tak by bol dobrý nápad ho napraviť.

Zoznam všetkých udalostí získame pomocou zavolanie funkcie pygame.event.get(), cez ktorej výsledok môžeme iterovat a porovnávať ho. Medzi často používané typy udalostí patria:

  • pygame.QUIT - je zavolaná, keď sa niekto pokúsi ukončiť okno hry
  • pygame.MOUSEBUTTONDOWN - pri stlačení tlačidla myši
  • pygame.MOUSEBUTTONUP - pri uvoľnení tlačidla myši
  • pygame.KEYDOWN - pri stlačení nejakej klávesy
  • pygage.KEYUP - pri uvoľnení nejakej klávesy

Malá poznámka: V Pygame_SDL2 sa môže stať, že vám nebude fungovať rozpoznávanie stlačení klávesov šípok. Preto sa vo všetkých kurzoch šípkam radšej vyvarujeme a budeme namiesto nich používať známe W A S D. Zároveň som tiež narazil na problém s pygame.KEYDOWN vo verzii 1.9.6., Takže namiesto neho budeme nateraz radšej používať pygame.KEYUP.

Povedzme, že budeme chcieť ukončiť hru v dvoch prípadoch: Je o ukončení požiadané alebo bola stlačená klávesa Esc. Keďže nám teraz kód beží vnútri cyklu while True, nedá sa z neho tak ľahko vyskočiť. Preto si definujme radšej premennú running = True a budeme kontrolovať jej stav. Potom nám len stačí pridať krátky for cyklus, v ktorom otestujeme, či náhodou nie je niektorá z aktívnych udalostí tá, ktorá nás zaujíma.

Po týchto úpravách bude náš kód vyzerať zhruba nasledovne:

pygame.init()
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
           running = False

    screen = pygame.display.set_mode((800, 600))
    pygame.draw.circle(screen, (0, 0, 255), (400, 300), 150)
    pygame.display.flip()

Teraz by už naše okno malo ísť zavrieť ako pomocou krížika, tak pomocou stlačenia (resp. Uvoľnenie) klávesy Esc.

Kreslíme obdĺžnik

Obdĺžnik, resp. pygame.Rect, je vysoko užitočná trieda vnútri pygame, pretože je možné s jej pomocou vyriešiť napríklad kolízie. Aby sme si to v rýchlosti ukázali, nakreslíme si ku kruhu ešte aj zelený obdĺžnik:

pygame.init()
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
           running = False

    screen = pygame.display.set_mode((800, 600))
    pygame.draw.circle(screen, (0, 0, 255), (400, 300), 150)
    pygame.draw.rect(screen, (0, 255, 0), pygame.Rect(10, 10, 100, 200))
    pygame.display.flip()

výsledok:

náhľad obrazovky - Pygame

Pohybujeme sa

Záverom tejto lekcie sa naučíme, ako sa sebou môžeme hýbať pomocou stlačenia klávesov. Mohli by sme si zaznamenávať pomocou udalostí, ktoré klávesy používateľ stlačil a ktoré potom pustil. Našťastie má ale pygame priamo už zabudovanú funkciu pygame.key.get_pressed(), ktorá vráti n-ticu všetkých práve stlačených kláves. Indexy v tejto n-ticu zodpovedajú hodnotám konštánt pygame.K_.

Povedzme si teda, že chceme hýbať naším kruhom pomocou klávesov W A S D. K tomu si potrebujeme ukladať pozíciu kruhu, ku ktorej budeme pridávať hodnoty podľa toho, ktoré klávesy sú zrovna stlačené:

player_x = 400
player_y = 300
while running:
        # ...
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_w]:  # Nahoru
            player_y -= 5
        if pressed[pygame.K_s]:  #Dolů
            player_y += 5
        if pressed[pygame.K_a]:  # Doleva
            player_x -= 5
        if pressed[pygame.K_d]:  # Doprava
            player_x += 5

Teraz by nám mala fungovať zmena súradníc, ako si želáme. Ešte ale musíme upraviť vykresľovanie kruhu:

while running:
    # ...
    pygame.draw.circle(screen, (0, 0, 255), (player_x, player_y), 150)

Teraz máme kruh, ktorý môžeme ovládať pomocou klávesov. Skúste si kód spustiť a chvíľu sa s ním hrať. Možno sa vám zdá, že modrý kruh behá trochu rýchlejšie, než ste si predstavovali. A áno, máte pravdu. To je preto, že sme nedali žiadne obmedzenie maximálnej rýchlosti programu, takže sa všetky kroky uskutočňujú tak rýchlo, ako len môžu. To nie je úplne žiaduce správanie, pretože by potom každému užívateľovi behala hra inak rýchlo a tiež by veľmi záležalo na vyťaženie procesora.

Preto má pygame ľahkú cestu, ako obmedziť maximálnu rýchlosť programu na určitý počet FPS (= frames per second = snímok za sekundu). Normálna hodnota FPS býva 30, 60 alebo 120, čo sú všetko hodnoty, pri ktorých si už ľudské oko nevšimne žiadneho trhania.

Pre obmedzenie maximálneho FPS na 30 teda použijeme inštanciu triedy pygame.time.Clock:

clock = pygame.time.Clock()  # vytvoříme nové pygame hodiny
while True:
    # ...
    clock.tick(30)  # umístíme na konec cyklu

Máme hotovo!

Výborná práca, teraz máme hotové všetky základy, ktoré potrebujeme na vytvorenie našej prvej hry. Tú si spoločne vytvoríme nabudúce.

Ešte pre zopakovanie si ale ukážeme kompletný kód (bez importu), ktorý by sme mali mať po konci tejto lekcie:

pygame.init()
running = True
clock = pygame.time.Clock()
player_x = 400
player_y = 300

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
           running = False

    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_w]:  # Nahoru
        player_y -= 5
    if pressed[pygame.K_s]:  # Dolů
        player_y += 5
    if pressed[pygame.K_a]:  # Doleva
        player_x -= 5
    if pressed[pygame.K_d]:  # Doprava
        player_x += 5

    screen = pygame.display.set_mode((800, 600))
    pygame.draw.circle(screen, (0, 0, 255), (player_x, player_y), 150)
    pygame.draw.rect(screen, (0, 255, 0), pygame.Rect(10, 10, 100, 200))
    pygame.display.flip()
    clock.tick(30)

Pokračovať budeme nabudúce, v lekcii Pygame - Pong - Príprava .


 

Predchádzajúci článok
Pygame - Úvod & inštalácia
Všetky články v sekcii
Pygame
Preskočiť článok
(neodporúčame)
Pygame - Pong - Príprava
Článok pre vás napísal Adam Hlaváček
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
vývoji užitečných aplikací zjednodušujících každodenní život
Aktivity