SDL: Hry nejen pro Linux (5)

22. 3. 2005
Doba čtení: 5 minut

Sdílet

Dnes se podíváme na grafické funkce poskytované knihovnou SDL. Vzhledem k rozsáhlosti tohoto tématu zde budou uvedeny pouze nejzákladnější věci, podrobnostem se budeme věnovat až v následujících dílech.

Návratové hodnoty funkcí

Většina SDL funkcí zabývajících se grafikou dodržuje pravidlo, že nulová návratová hodnota značí úspěch a mínus jednička neúspěch. Pokud tedy nebude uvedeno jinak, platí u funkcí vracejících int tyto hodnoty. Volání funkcí, které vracejí ukazatele, by měla být ošetřena klasicky na NULL.

Nahrávání obrázků z disku

SDL umí nahrávat pouze obrázky ve formátu BMP, ale díky knihovně SDL_image, která se už stala de facto jeho součástí, může programátor používat i PCX, GIF, JPG, PNG, TGA, TIFF a další méně známé formáty. Stejně jako celé SDL je i SDL_image šířena pod licencí GNU LGPL.

Po přilinkování knihovny a vložení hlavičkového souboru SDL_image.h je možné volat funkci IMG_Load(), která vrací surface nahrávaného obrázku. Formát je detekován automaticky podle přípony, hlaviček apod.

SDL_Surface *SDL_LoadBMP(const char *file);
SDL_Surface *IMG_Load(const char *file);

Ukládání obrázků

SDL kromě nahrávání surface z disku umožňuje i ukládání. Jedná se opět pouze o formát BMP, SDL_image ukládání bohužel neumožňuje.

int SDL_SaveBMP(SDL_Surface *surface, const char *file);

Uvolnění surface

Ke smazání surface lze použít následující funkci, která se o vše postará.

void SDL_FreeSurface(SDL_Surface *surface);

Konverze formátu surface

Není to podmínkou, ale pokud bude mít surface obrázku stejný formát, jako má okno, bude jeho zobrazení stát procesor mnohem méně výkonu. Nejlepší ze všeho je ihned po vytvoření surface zavolat funkci SDL_DisplayFormat() (resp. SDL_DisplayFor­matAlpha() pro surface s alfa kanálem), která se postará o konverzi. Parametrem je převáděný surface a vrácen je nový surface s požadovaným formátem nebo NULL při neúspěchu.

SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface);

Výše uvedené funkce využívají služeb SDL_ConvertSur­face(), která je jejich obecnější variantou.

SDL_Surface *SDL_ConvertSurface(SDL_Surface *src,
                SDL_PixelFormat *fmt, Uint32 flags);

První parametr opět představuje zdrojový surface, druhým je požadovaný pixel formát (většinou surface_vzoru->format) a třetím jsou flagy, které už byly probrány dříve (SDL_SWSURFACE, SDL_HWSURFACE apod.).

Vykreslování

Základem veškerého blittingu je v SDL funkce SDL_BlitSurface(), která vezme pixely ze zdrojového surface src a zkopíruje je do cílového surface dst, jímž je většinou, ale ne vždy, framebuffer okna. Funkce samozřejmě umožňuje specifikovat pozici a rozměry oblasti, díky čemuž nemusí být kopírován celý surface.

Pozn.: Termín blitting obecně označuje kopírování pixelů z jedné paměti do druhé. Nemusí se však jednat pouze o strohé přepsání dat, ale mohou se provádět různé další operace – např. přeskakovat pixely určité barvy, míchat zdrojový pixel s cílovým v závislosti na alfa kanálu (blending) a podobně. SDL_BlitSurface() vykonává všechny tyto operace.

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect,
                SDL_Surface *dst, SDL_Rect *dstrect);

Pokud bude za některý z obdélníků předán NULL, bude se pracovat s celým objektem, u cílové oblasti se používá pouze pozice, žádné roztahování nebo zmenšování tedy není možné. Po návratu z funkce bude cílový obdélník obsahovat rozměry oblasti, se kterými se při blittingu pracovalo ve skutečnosti, tato hodnota se bude hodit při aktualizaci okna (viz níže). Výsledek blittingu do značné míry závisí na vlastnostech surfaců, především na alfa kanálu a transparentní bar­vě.

Návratovou hodnotou je klasicky 0 (úspěch) a –1 (neúspěch). Pokud bude u hardwarového surface vráceno –2, byla jeho video paměť ztracena. V takovém případě by měl být surface znovu nahrán/vytvořen. Stává se to během přepínání z celoobrazovkového režimu do okna, pokud SDL využívá služeb DirectX 5.0. Pro podrobnosti odkazuji na SDL manuál.

Pozn.: Možná to bude jen přežitek starších verzí, protože SDL v současnosti přepínání aplikace mezi fullscreenem a oknem pod operačním systémem MS Windows vůbec neumožňuje.

Aktualizace obsahu okna

Aby se zobrazila právě vykreslená scéna, je potřeba vykonat ještě jednu operaci – aktualizovat oblast okna, na kterou se kreslilo. V parametrech funkce se předává neplatný obdélník, jehož žádná část by neměla přesahovat okraje okna – neprovádějí se žádné testy, a tedy ani ořezávání. Pokud budou předány samé nuly, aktualizuje se celé okno. Tyto funkce by nikdy neměly být volány na zamknutý surface.

void SDL_UpdateRect(SDL_Surface *screen,
                Sint32 x, Sint32 y, Sint32 w, Sint32 h);
void SDL_UpdateRects(SDL_Surface *screen,
                int numrects, SDL_Rect *rects);

Co se týká druhé uvedené funkce, má stejný význam jako první, kromě toho, že lze specifikovat více obdélníků najednou. Tyto obdélníky však nejsou testovány na vzájemné přesahy, jejich aktualizace probíhají nezávisle.

V případě, že okno používá double buffering (SDL_DOUBLEBUF předaný do SDL_SetVideoMo­de()), buffery se prohodí voláním SDL_Flip(). Hardware pak počká na vertikální zatmění stínítka monitoru a až poté provede požadovanou operaci.

int SDL_Flip(SDL_Surface *screen);

Pokud hardware double buffering nepodporuje nebo není zapnutý, je SDL_Flip() ekvivalentní volání SDL_UpdateRec­t(screen, 0, 0, 0, 0), čili překreslí se celé okno.

Ukázkové programy

Jelikož by se mnoho kódu z příkladů pokaždé opakovalo, budou obecně použitelné funkce umisťovány do souborů functions.h a functions.cpp. Prozatím bude obsahovat pouze pomocnou funkci na nahrávání obrázků z disku a funkci pro výpočet počtu snímků za sekundu. Animace a pohyby v programu díky FPS poběží stejně rychle na každém počítači. (Zdrojový kód se zvýrazněním syntaxe.)

Hello, SDL graphic!

Asi nejjednodušší program, jaký lze vytvořit na demonstraci použití SDL grafiky. Vykresluje se v něm jednoduchý obrázek, který byl nahrán z disku za použití knihovny SDL_image. Na své centrované pozici zůstává i při roztahování okna. (Zdrojový kód se zvýrazněním syntaxe.)

Hello, SDL graphic!

Objekt odrážející se od okrajů

Druhý příklad je o něco složitější než ten první. Místo statického obrázku je vykreslován dynamický objekt, který se pohybuje po přímce oknem a odráží se od okrajů. Díky tomu, že obsahuje i alfa kanál, jím může prosvítat pozadí. (Zdrojový kód se zvýrazněním syntaxe.)

bitcoin_skoleni

Objekt odrážející se od okrajů

Ve vnitřním fungování programů existuje jeden rozdíl. U prvního má okno pouze jeden buffer a scéna se po vykreslení aktualizuje pomocí funkce SDL_UpdateRect(). Druhý příklad využívá double buffering (je-li podporován) a scéna se musí aktualizovat voláním SDL_Flip(). SDL_UpdateRect() by v tomto případě nemělo žádný efekt.

Download

Pokračování

Tento článek obsahoval pouze základní úvod do kreslení pomocí knihovny SDL, další podrobnosti přijdou v následujících dílech.

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.