IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

3. diel - SDĽ - Základy vykresľovanie

V dnešnom diele sa dozvieme niečo o vykresľovanie pomocou knižnice SDL. Povieme si základné pojmy a potom vykreslíme obdĺžnik, s ktorým budeme posúvať po obrazovke.

SDL_Rect

Predtým, než sa vrhneme na vykresľovanie, spomeniem štruktúru SDL_Rect. Už z názvu vyplýva, že reprezentuje obdĺžnik. Má len štyri atribúty, ktoré sú x a y (určenie pozície ľavého horného rohu), a ďalej w a h, ktoré určujú šírku a výšku obdĺžnika. SDL_Rect sa používa často na určenie zdrojového alebo cieľového obdĺžnika vykresľovanie. Vždy, keď nechceme vykresliť farbou celé okno, použijeme SDL_Rect.

SDL_Renderer, SDL_Texture a SDL_Surface

Jedná sa o tri štruktúry, ktoré sú svojim významom veľmi podobné, ale nie sú zhodné. Pretože budeme potrebovať všetky tri, každú si popíšeme.

SDL_Renderer je štruktúra, ktorá sa stará o samotnej vykresľovanie. Spravidla je zviazaná s určitým SDL_Window, do ktorého vykresľuje (môže byť zviazaný aj s SDL_Surface). S SDL_Renderer sú spojené funkcie vykresľujúca jednotlivé elementy (SDL_RenderDraw­Point, SDL_RenderDraw­Line, SDL_RenderDraw­Rect), ale aj funkcie, ktoré obsah kopírujú (SDL_RenderCopy). Najprv budeme využívať funkcie, ktoré vykresľujú len určité elementy, v ďalšom diele sa pozrieme na funkcie, ktoré obraz kopírujú. Vlastne sa jedná o sprostredkovateľa, skrze ktorého budeme vykresľovať.

SDL_Texture je štruktúra, ktorá ukladá obraz - informácie o jednotlivých pixeloch. Je hardwarovo špecifická a je uložená v pamäti grafickej karty. Tu sa dostávame k hardvérovo-akcelerovanému vykresľovanie. Samotné operácie, ktoré s ňou môžeme robiť, sú značne obmedzené, užíva sa predovšetkým ako zdroj pre ďalšie vykresľovanie. Do textúry môžeme napríklad uložiť obrázok pozadia. Pri každom vykreslenie potom prvý skopírujeme túto textúru do výsledného obrazu, a až potom začneme vykresľovať jednotlivé prvky scény.

SDL_Surface má podobnú funkciu ako SDL_Texture, ale v tomto prípade sa jedná o štruktúru softvérovú. Je uložená v RAM pamäti a môžeme s ňou viac pracovať. V premenných xay má uložené svoje rozmery, ukazovateľ pixels potom obsahuje adresu samotných pixelov. Odporúčam ale pixely neupravovať ručne. Vo väčšine prípadov to ani nie je nutné. SDL poskytuje viacero funkcií, ktoré nám dovoľujú s SDL_Surface manipulovať. Medzi najdôležitejšie by som zaradil SDL_FillRect, ktorá vykreslí obdĺžnik. Ďalšou veľmi dôležitou funkciou je SDL_BlitSurface, ktorá skopíruje údaje z jednej SDL_Surface do druhej. Posledný zaujímavou funkciou, ktorú by som spomenul, je SDL_SetColorKey. Tá nastaví farbu, ktorá sa nebude vykresľovať. Väčšina obrázkov (pozadia, postavy - stretneme sa s nimi neskôr) má určitú farbu pozadia. Ak túto farbu vo funkcii nastavíme, nebude sa vykresľovať. Napríklad nasledujúci obrázok má červenú farbu pozadia (získané tu).

Postava s pozadím - SDĽ

Spojitosť medzi SDL_Surface, SDL_Texture a SDL_Renderer

Hoci každá štruktúra slúži na iný účel, istá spojitosť medzi nimi je. Povedzme si o pár funkciách, ktoré budeme potrebovať.

Z SDL_Surface môžeme vytvoriť SDL_Texture pomocou funkcie SDL_CreateTex­tureFromSurfa­ce, ktorá prevedie SDL_Surface na SDL_Texture. Tým dostaneme obraz, ktorý bol v SDL_Surface do pamäte grafickej karty, ktorá s ním môže pracovať rýchlejšie. Využíva sa toho v prípadoch, keď vykresľujú niečo zložité, ale už to nepotrebujeme prekresľovať. Najprv vytvoríme SDL_Surface, kde všetko vykreslíme, a potom to prevedieme do SDL_Texture.

Môžeme tiež vytvoriť SDL_Renderer, ktorý bude naviazaný na určitý SDL_Surface. Využijeme na to funkciu SDL_CreateSof­twareRenderer, ktorá SDL_Renderer vytvorí. Všetky operácie sa potom budú vykonávať na SDL_Surface, ktorú sme odovzdali v parametri. Ak budeme chcieť, aby bol SDL_Renderer naviazaný na určitý SDL_Texture, využijeme funkcie SDL_SetRenderer­Target. V túto chvíľu bude SDL_Renderer vykresľovať na SDL_Texture. Nesmieme ale zabudnúť, že SDL_Renderer musí byť vytvorený s FLAG SDL_RENDERER_TARGETTEXTURE.

Zároveň stojí za pozornosť, že SDL_RenderCopy prijíma ako parameter SDL_Texture. Z toho vyplýva, že nie je možné vykresľovať na obrazovku z SDL_Surface. Ak budeme potrebovať, aby sa SDL_Surface vykreslila na obrazovku, musíme z nej vytvoriť SDL_Texture a následne vykresliť cez SDL_Renderer.

Posledná vec, ktorú spomeniem, je možnosť získať SDL_Surface zo SDL_Window. Potom akákoľvek úprava vykonaná na tento SDL_Surface bude vykonaná aj na obrazovke. Jediná vec, na ktorú nesmieme zabudnúť, je zavolať funkciu SDL_UpdateWin­dowSurface. Tá zobrazuje všetky zmeny, ktoré sme vykonali. Prečo vlastne máme dva spôsoby vykresľovanie? Štruktúra SDL_Surface je softvérová. Všetky operácie vykonáva procesor. Na rozdiel od toho SDL_Renderer a SDL_Texture sú štruktúry hardwarovo závislé a operácie prebiehajú v grafickej karte. To znamená, že sú rýchlejšie a efektívnejšie. Preto by sme mali používať hlavne hardvérovo-akcelerovanej funkcie, ktoré tak nezaťažujú procesor a sú na grafickej karte vykonané rýchlejšie.

Zobrazenie vykreslenie

Posledná časť teórie, ktorú budeme potrebovať, je funkcia pre zobrazenie vykreslenie. Obraz nemôže byť zároveň zobrazený a meniť sa - nemôžeme do neho vykresľovať. Obraz je preto v grafickej karte uložený dvakrát. Jeden je ten, ktorý sa zobrazuje, a druhý ten, na ktorý vykresľuje. Táto technika sa nazýva double buffering. Obrazy sa môžu radiť aj do fronty (triple buffering), ale SDL pre to podporu nemá. Nie je však ťažké túto techniku naimplementovať. O tieto priestory sa stará sám SDL_Renderer. Ona spomínaná funkcia je SDL_RenderPre­sent. Tá urobí iba to, že skopíruje obraz, ktorý sme menili, a vloží ho na miesto obrazu, ktorý je zobrazený na obrazovke. Potom môžeme ďalej meniť prvý obraz, bez toho aby sme narušovali zobrazovanie aktuálneho obrazu. Ak budeme chcieť docieliť vyššiu efektivitu, môžeme vytvoriť SDL_Renderer s FLAG SDL_RENDERER_PRESENTVSYNC, ktorý bude synchronizovať zmienenú operáciu tak, aby zodpovedala obnovovaciu frekvenciu monitora (spravidla 60Hz).

Vykreslenie obdĺžnika

Najprv budeme potrebovať obdĺžnik, ktorý budeme vykresľovať. Vytvoríme si teda SDL_Rect a nastavíme jeho premenné na ľubovoľnú veľkosť. Potom vytvoríme nový SDL_Renderer pre okno. Tieto dve operácie vykonáme ešte pred vstupom do hlavnej slučky, inak by sme ich vytvárali v každom priechode a by bolo zbytočné ..

SDL_Rect* rect = new SDL_Rect;
rect->x = rect->y = rect->w = rect->h = 100;
SDL_Renderer* renderer = SDL_CreateRenderer(MainWindow,-1,0);

Zo vstupu budeme zachytávať stisk klávesov. Pre začiatok nám bude stačiť reagovať iba na šípky. Šípkou nahor obdĺžnik posunieme hore a obdobne pre ostatné smery. Ak sa jednalo o stlačenie klávesy, bude táto štruktúra uložená v atribúte key, v nej sa pozrieme do informácií o klávesoch (keysym) a konkrétne nás bude zaujímať kód klávesy (sym). V ňom sú uložené hodnoty z SDL_Keycode. My budeme reagovať iba v prípade, keď sa jednalo o šípky (SDLK_RIGHT, SDLK_LEFT, SDLK_UP, SDLK_DOWN). Výsledný kód pre vstup bude vyzerať nasledovne:

while (SDL_PollEvent(event))                //načtení události z fronty
{
    if (event->type == SDL_QUIT)            //manipulace s událostí
        End = true;             //ukončení aplikace
    else if (event->type == SDL_KEYDOWN)        //reagování na stisk klávesy
    {
        switch (event->key.keysym.sym)
        {
        case SDLK_RIGHT:
            rect->x += 1; break;
        case SDLK_LEFT:
            rect->x -= 1; break;
        case SDLK_UP:
            rect->y -= 1; break;
        case SDLK_DOWN:
            rect->y += 1; break;
        }
    }
}

Nakoniec ešte obdĺžnik vykreslíme. Najprv nastavíme farbu, akú budeme obdĺžnik vykresľovať. Ja si zvolil červenú. Farbu nastavíme funkcií SDL_SetRender­DrawColor. Druhý až štvrtý parameter slúži na nastavenie farby klasicky vo formáte RGB, posledný je alfa kanál - teda transparentnosť. Všetky tieto parametre prijímajú hodnotu 0 až 255. Obdĺžnik vykreslíme funkcií SDL_RenderFillRec­t. Nakoniec musíme aktualizovať obraz, preto použijeme funkciu SDL_RenderPresent. To je všetko, teraz program spustíme.

SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, rect);
SDL_RenderPresent(renderer);
Vykreslený bez pozadia - SDĽ

Prečo nám obdĺžnik nemizne? Pretože vždy vykreslíme nový obdĺžnik, do už existujúceho obrazu. Ak chceme docieliť to, aby nám obdĺžnik zmizol, budeme musieť celú obrazovku prekresliť. V tomto prípade však nevyužijeme funkciu SDL_RenderFillRect, ale SDL_RenderClear, ktorá přemaluje celú plochu. Preto opäť nastavíme farbu (SDL_SetRenderDrawColor). Zvolíme napríklad na modrú a potom zavoláme SDL_RenderClear. Konečný kód pre vykreslenie je nasledovný:

SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, rect);
SDL_RenderPresent(renderer);
vykreslenie obdlžnika - SDĽ

Obdĺžnik mizne a pozadia máme modrej. Presne ako sme chceli.

To je pre tento diel všetko. Nabudúce sa pozrieme na prácu s obrázkami, prácu s textúrami a kopírovanie blokov pamäte.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 1062x (3.34 MB)

 

Predchádzajúci článok
SDĽ - Vytvorenie okná a vstup od užívateľa
Všetky články v sekcii
SDĽ
Preskočiť článok
(neodporúčame)
SDĽ - Práca s obrázkami
Článok pre vás napísal Patrik Valkovič
Avatar
Užívateľské hodnotenie:
1 hlasov
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity