Hlavní navigace

SDL: Hry nejen pro Linux (4)

15. 3. 2005
Doba čtení: 6 minut

Sdílet

V minulém dílu jsme si dopodrobna vysvětlili inicializaci SDL, ale ještě něco málo zbylo - nastavení vlastností a vytvoření okna. Jak brzy zjistíme, v porovnání např. s Win32 API je tato činnost v SDL mnohem jednodušší.

Vytvoření okna

V nejjednodušším a většinou zcela dostačujícím případě se jedná pouze o volání jediné jednoduché funkce. Ne nadarmo se říká, že SDL nechává programátora koncentrovat se na vývoj vlastní hry místo toho, aby se staral o složité detaily operačního systému…

SDL_Surface *SDL_SetVideoMode(int width, int height,
                 int bpp, Uint32 flags);

Návratovou hodnotou funkce je při chybě NULL, v ostatních případech ukazatel na SDL_Surface. Tato struktura v SDL představuje základní a v podstatě jediný prostředek pro ukládání pixelů obrázku a informací o něm. V tomto případě se jedná o okno (frame buffer) aplikace. Všechny funkce, které SDL poskytuje pro 2D grafiku, jsou realizovány nad touto strukturou.

Parametry width a height určují šířku klientské oblasti okna, bpp specifikuje barevnou hloubku v bitech. Pokud se vloží hodnota 0, bude použita barevná hloubka aktuálně nastavená v systému. Parametr flags specifikuje vlastnosti okna a lze předat některou z následujících symbolických konstant nebo jejich kombinaci (binární OR).

SDL_SWSURFACE, SDL_HWSURFACE
Vytvoří surface v systémové nebo video paměti. Pokud nebudou pixely surface často modifikovány, je lepší je uložit přímo do video paměti, protože se pak bude využívat hardwarové akcelerace.
SDL_ASYNCBLIT
Povolí asynchronní aktualizaci surface. Tímto se sice na jednoprocesorových systémech blitting (kreslení jednoho obrázku do druhého) většinou zpomalí, ale na SMP systémech dojde ke zrychlení.
SDL_ANYFORMAT
Obyčejně, pokud není požadovaná barevná hloubka video surface dostupná, SDL přistoupí k emulaci. Předáním SDL_ANYFORMAT se tomu předejte – SDL použije video surface s jakoukoli z dostupných barevných hloubek, ale bez emulace.
SDL_HWPALETTE
Poskytne SDL exkluzivní přístup k paletě. Bez tohoto flagu nemusí vždy jít získat barva požadovaná přes SDL_SetColors() nebo SDL_SetPalette().
SDL_DOUBLEBUF
Povolí hardwarový double buffering. Veškeré kreslení se pak bude provádět na skrytém/nezobra­zeném bufferu. Po jeho ukončení se buffery zamění voláním SDL_Flip(). Tento parametr je validní pouze spolu se SDL_HWSURFACE.
SDL_FULLSCREEN
Aplikace nepoběží v okně, ale v celoobrazovkovém režimu. Pokud není z jakéhokoli důvodu změna hardwarového rozlišení možná, bude použito následující vyšší rozlišení a scéna se vycentruje na černém pozadí.
SDL_OPENGL
Vytvoří okno s podporou OpenGL. Před vlastním voláním SDL_SetVideoMode() by měly být již nastaveny atributy přes SDL_GL_SetAttri­bute(), pozdější změna již není možná. Použití OpenGL bude věnován některý z budoucích dílů.
SDL_OPENGLBLIT
Má stejný význam jako předchozí parametr, ale s tím rozdílem, že bude zároveň možné provádět SDL blitting. Scéna (2D) může mít alfa kanál a pro aktualizaci musí být použito SDL_UpdateRects().
SDL_RESIZABLE
Bude možná změna velikosti okna. Při roztahování se bude generovat událost SDL_VIDEORESIZE a může být opět zavoláno SDL_SetVideoMode() s novými rozměry.
SDL_NOFRAME
Pokud je to možné, vytvoří okno bez titulku a rámu. V celoobrazovkovém režimu se nastavuje automaticky.

Pozn.: Pokud je funkcionalita poskytovaná daným parametrem z nějakého důvodu důležitá, lze otestovat flagy z vráceného surface.

Získání video surface

Ukazatel na aktuální zobrazený surface lze získat pomocí následující funkce. V případě, že SDL provádí nějaké konverze formátu, bude vrácen veřejně viditelný surface, ne opravdový.

SDL_Surface *SDL_GetVideoSurface(void);

Zjištění dostupnosti video formátu

Před samotným vytvořením okna může být dobré nejdříve zjistit, zda jsou požadované parametry vůbec dostupné.

int SDL_VideoModeOK(int width, int height,
                 int bpp, Uint32 flags);

Funkce vrací hodnotu barevné hloubky pro nejbližší dostupný mód v závislosti na předané šířce, výšce a vlastnostech, parametry jsou tedy stejné jako u funkce SDL_VideoMode(). Jediným rozdílem je, že nulová barevná hloubka (aktuálně nastavená v systému) není pro tuto funkci validní! Pokud není mód podporován pod žádnou barevnou hloubkou, je vrácena nula.

Seznam dostupných rozměrů okna

Pomocí funkce SDL_ListModes() je programátor schopen nagrabovat všechna dostupná rozlišení pro daný formát pixelů a vlastnosti.

SDL_Rect **SDL_ListModes(SDL_PixelFormat *format, Uint32 flags);

Návratovou hodnotou je ukazatel na pole obdélníků, které budou navíc seřazeny od největších rozměrů po nejmenší. V případě, že bude vrácen NULL, nejsou dostupná žádná rozlišení a (SDL_Rect **)-1 oznamuje, že jakékoli rozlišení je v pořádku.

Pokud se za parametr format předá NULL, bude seznam vztáhnut vzhledem k SDL_GetVide­oInfo()->vfmt (viz dále). Při zjišťování jsou důležité spíše flagy než formát pixelů. Pokud by bylo například předáno SDL_HWSURFACE, hledalo by se pouze v hardwarově podporovaných módech.

Struktura obdélníku je definována následovně. Atributy x a y specifikují pozici levého horního rohu, w a h rozměry. Jednotkami jsou pixely.

typedef struct
{
    Sint16 x, y;
    Uint16 w, h;
} SDL_Rect;

Protože bychom zbytečně zabředli do v tuto chvíli ne zrovna životně důležitých detailů, bude struktura SDL_PixelFormat popsána až někdy v budoucnu.

Zjištění informací o grafickém hardware

Funkce SDL_GetVideoInfo() vrátí read only ukazatel na strukturu SDL_VideoInfo, která obsahuje informace o grafickém hardware. Pokud bude volána před SDL_SetVideoMode(), bude atribut vfmt obsahovat formát pixelů „nejvhodnějšího“ video módu. V případě volání po SDL_SetVideoMode() bude obsahovat aktuální formát.

SDL_VideoInfo *SDL_GetVideoInfo(void);

Struktura SDL_VideoInfo se používá pouze při volání této funkce a je deklarována takto:

typedef struct
{
    Uint32 hw_available :1; /* Lze vytvořit hardwarové surface? */
    Uint32 wm_available :1; /* Lze komunikovat se správcem oken? */
    Uint32 blit_hw      :1; /* Akcelerovaný blitting HW --> HW */
    Uint32 blit_hw_CC   :1; /* Akcelerovaný blitting s Colorkey */
    Uint32 blit_hw_A    :1; /* Akcelerovaný blitting s Alpha */
    Uint32 blit_sw      :1; /* Akcelerovaný blitting SW --> HW */
    Uint32 blit_sw_CC   :1; /* Akcelerovaný blitting s Colorkey */
    Uint32 blit_sw_A    :1; /* Akcelerovaný blitting s Alpha */
    Uint32 blit_fill    :1; /* Akcelerované vyplňování barvou? */
    Uint32 video_mem;       /* Celkové množství video paměti v kB */
    SDL_PixelFormat *vfmt;  /* Formát grafického surface */
} SDL_VideoInfo;

Pozn.: Pokud bude pod X11 paměť nulová a žádné hardwarové akcelerace nebudou dostupné, změňte grafický ovladač z X11 např. na DGA (pouze fullscreen a X11). V konzoli definujte systémovou proměnnou SDL_VIDEODRIVER ($ export SDL_VIDEODRIVER=dga) a spusťte program. Podrobnosti lze nalézt v SDL FAQ, sekce Development.

Zjištění video ovladače

Do řetězce specifikovaného parametrem namebuf bude uloženo maximálně maxlen znaků (včetně NULL) se jménem inicializovaného video driveru. Jedná se o jednoduché slovo jako x11, dga, directx nebo windib.

char *SDL_VideoDriverName(char *namebuf, int maxlen);

Pokud ještě nebyla grafika inicializována (SDL_Init()), bude vráceno NULL.

Gamma funkce obrazovky

SDL, pokud to hardware počítače umožňuje, umí změnit „gamma funkci“, která kontroluje jas a kontrast barev zobrazených na obrazovce. Vztažná hodnota je 1.0, tzn. nebudou se provádět žádné změny. Menší než jedna představuje ztmavení, větší než jedna zesvětlení. Meze jsou přibližně 0.1 a 10.0.

int SDL_SetGamma(float redgamma, float greengamma, float bluegamma);
int SDL_SetGammaRamp(Uint16 *redtable, Uint16 *greentable, Uint16 *bluetable);
int SDL_GetGammaRamp(Uint16 *redtable, Uint16 *greentable, Uint16 *bluetable);

Pomocí druhé uvedené funkce lze pro každý kanál barev předat kompletní tabulku. Jedná se o pole 256 Uint16 čísel, které reprezentuje mapování mezi vstupem a výstupem. Vstup je indexem do pole a výstup udává šestnáctibitovou hodnotu gammy na daném indexu, jejíž velikost je změněna na výstupní přesnost. Pokud se za kanál předá NULL, zůstane nezměněn. Vrácení –1 znamená, že funkce nejsou podporovány.

Ukázkové programy

Vytvoření okna „jednoduchým“ způsobem

Kód ukazuje pravděpodobně nejjednodušší (a také nejpoužívanější) vytvoření okna. Tento postup není zrovna flexibilní, ale bývá většinou zcela dostatečný. (Zdrojový kód se zvýrazněním syntaxe.)

Vytvoření okna s ověřováním vlastností

Druhý příklad je už o něco složitější. Pokud nejsou některé parametry vytvářeného okna validní, program se je pokouší upravovat tak dlouho, dokud nejsou použitelné nebo nejdou dále upravit. Zároveň s testy vypisuje na konzoli informace o tom, jaké modifikace právě provádí. Můžete zkusit zadávat různé flagy, záporné velikosti okna a podobně. (Zdrojový kód se zvýrazněním syntaxe.)

CS24_early

Vypsání informací o grafickém hardware

Program nevytvoří žádné okno, ale po spuštění pouze vypíše různé informace o grafickém hardware a pak se ukončí. (Zdrojový kód se zvýrazněním syntaxe.)

Download

Pokračování

Příště se konečně začneme věnovat grafice, takže se těšte…

Byl pro vás článek přínosný?

Autor článku

Backend programátor ve společnosti Avast, kde vyvíjí a spravuje BigData systém pro příjem a analýzu událostí odesílaných z klientských aplikací založený na Apache Kafka a Apache Hadoop.