Vytvo°enφ SDL okna

Na ·vod bych cht∞l pod∞kovat Bernymu za sebe i za vÜechny, kter²m tento Φlßnek velice pomohl, a kte°φ si myslφ, ₧e d∞lat programy v²hradn∞ pro komerΦnφ Wokna nenφ tou sprßvnou cestou.

Woq m∞ po₧ßdal, abych napsal tutorißl pro pou₧φvßnφ OpenGL pod knihovnou SDL. Je to m∙j prvnφ tutorißl, tak₧e doufßm, ₧e se bude lφbit. Zkusφme vytvo°it k≤d, kter² bude odpovφdat druhΘ lekci "normßlnφch" tutorißl∙. Zdrojov² k≤d je "oficißlnφ" NeHe port druhΘ lekce do SDL. Pokusφm se popsat, jak se vytvß°φ okno a v∞ci okolo.

Nejd°φve n∞co o tom, co je SDL. SDL, univerzßlnφ knihovna, slou₧φ pro tvorbu her. Znßte-li Allegro, tak SDL je mu trochu podobnΘ. Bylo napsßno v C(/C++) a jeho domovskΘ prost°edφ bylo Linux. Nynφ ale existuje i pod BeOS, MacOS, Windows, QNX, AmigaOS, PS2,.... Obsahuje zßkladnφ API pro vytvo°enφ okna, 2D grafiku, vφcevlßknovΘ programovßnφ, obsluhu klßvesnice, krysy a joysticku, p°ehrßvßnφ videa a zvuk∙. Ke knihovn∞ jsou jeÜt∞ podp∙rnΘ knihovniΦky pro naΦφtßni rozmanit²ch grafick²ch formßt∙, pro lepÜφ ozvuΦenφ (mp3, ogg,..) a sφ¥ovΘ slu₧by pro multiplayer. P°φmo podporuje vyu₧itφ OpenGL, kterΘ samo o sob∞ manipulaci s okny, komunikaci se systΘmem a vÜechnu prßci okolo neumφ a tudφ₧ ned∞lß. K≤d kter² vytvo°φte v SDL m∙₧ete velice snadno p°enΘst jinam jednoduch²m p°ekompilovßnφm (bude to fungovat, pokud nepφÜete jako Φu≥ata). SDL nenφ jen n∞jakß malß knihovniΦka, ale pou₧φvajφ ji i komerΦnφ hry. V∞tÜina her od Lokisoft (portujφ hry pod Linux) je nad SDL a Unreal Tournament 2003 takΘ. NejlepÜφ bude, pokud navÜtφvφte domovsk² web - http://www.libsdl.org/. Jsou tam vÜemo₧nΘ helpy, nßvody, manußly a takΘ vystaveny prßce lidφ, kte°φ SDL pou₧φvajφ; pßr dφlek i z ╚R.

Ne₧ zaΦneme, ujist∞te se, ₧e mßte knihovnu SDL. Pokud ne, navÜtivte v²Üe uvedenou adresu a stßhn∞te si soubory pro vaÜi konkrΘtnφ platformu.

A te∩ u₧ se vrhneme na programovßnφ. Nejd°φve vlo₧φme hlaviΦkovΘ soubory. Mo₧nß se to zdß na prvnφ pohled jako Üφlenost, ale vy°eÜφme p°enßÜenφ k≤du na r∙znΘ OS. Proto doporuΦuji toto vklßdßnφ nechat tak, jak je.

#ifdef WIN32 // Pokud se bude kompilovat program po Windows

#define WIN32_LEAN_AND_MEAN

#include <windows.h> // HlaviΦkov² soubor pro Windows

#endif

#if defined(__APPLE__) && defined(__MACH__) // Pokud se bude kompilovat program pro Apple

#include <OpenGL/gl.h> // HlaviΦkov² soubor pro OpenGL32 knihovnu v Applu

#include <OpenGL/glu.h> // HlaviΦkov² soubor pro GLu32 knihovnu v Applu

#else

#include <GL/gl.h> // HlaviΦkov² soubor pro OpenGL32 knihovnu

#include <GL/glu.h> // HlaviΦkov² soubor pro GLu32 knihovnu

#endif

#include "SDL.h" // HlaviΦkov² soubor pro SDL

Vytvo°φme funkci na inicializaci OpenGL (smφchanΘ InitGL() a ResizeGLScene() z klasick²ch tutorißl∙). NaÜφm cφlem nenφ rozebφrat OpenGL, ale spφÜe vysv∞tlit SDL. Pro detaily se podφvejte do druhΘ lekce.

void InitGL(int Width, int Height) // Tuto funkci volßme hned po vytvo°enφ okna pro inicializace OpenGL

{

glViewport(0, 0, Width, Height);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // ╚ernΘ pozadφ

glClearDepth(1.0); // Povolφme mazßnφ pozadφ

glDepthFunc(GL_LESS); // Vybereme typ Depth Testu

glEnable(GL_DEPTH_TEST); // Povolφme Depth Test

glShadeModel(GL_SMOOTH); // Povolφme Smooth Color Shading

glMatrixMode(GL_PROJECTION);

glLoadIdentity(); // Resetujeme projekΦnφ matici

gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // VypoΦφtßme pom∞r okna

glMatrixMode(GL_MODELVIEW);

}

Vykreslovßnφ...

void DrawGLScene() // Hlavnφ vykreslovacφ funkce

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Vymazßnφ obrazovkovΘho a hloubkovΘho bufferu

glLoadIdentity(); // Reset matice pohledu

glTranslatef(-1.5f,0.0f,-6.0f); // Posun o 1.5 doleva a o 6 do hloubky

// Nakreslφ troj·helnφk

glBegin(GL_POLYGON);

glVertex3f(0.0f, 1.0f, 0.0f);

glVertex3f(1.0f,-1.0f, 0.0f);

glVertex3f(-1.0f,-1.0f, 0.0f);

glEnd();

glTranslatef(3.0f,0.0f,0.0f); // Posuneme se o 3 doprava

// Nakreslφ Φtverec

glBegin(GL_QUADS);

glVertex3f(-1.0f, 1.0f, 0.0f);

glVertex3f( 1.0f, 1.0f, 0.0f);

glVertex3f( 1.0f,-1.0f, 0.0f);

glVertex3f(-1.0f,-1.0f, 0.0f);

glEnd();

Na konci provedeme drobnou zm∞nu. Zavolßme funkci SDL_GL_SwapBuffers(), kterß zajistφ, ₧e se na obrazovce objevφ vÜe, co jsme ve funkci DrawGLScene() nakreslili. V klasick²ch tutorißlech najdete SwapBuffers() ve WinMain() po volßnφ tΘto funkce.

SDL_GL_SwapBuffers(); // Prohozeni bufferu, aby se zobrazilo, co jsme nakreslili

}

Äe se funkce main() provßdφ po spuÜt∞nφ programu jako prvnφ doufßm vφte :-] Le₧φ zde v∞tÜina SDL k≤du. Nejprve provedeme inicializaci a pak cyklujeme dokola v jednoduchΘ smyΦce zprßv. Dßvejte si pozor, aby deklarace main() byla p°esn∞ takovß, jak mß b²t - nikdy nevynechßvat argumenty a nßvratovou hodnotu.

int main(int argc, char **argv) // Prost∞ main() :-)

{

int done; // UkonΦovacφ prom∞nnß

Inicializace knihovny se musφ zavolat jako prvnφ p°ed vÜφm ostatnφm. SDL_INIT_VIDEO znamenß, ₧e budeme chtφt inicializovat v²stup na obrazovku. M∙₧e se kombinovat i s dalÜφmi jako t°eba timerem, audiem,... Knihovna SDL nßm umo₧≥uje pou₧φvat stdout a stderr pro textov² v²stup. V Linuxu vypisuje na terminßl, ve windows vytvo°φ soubory stdout.txt a stderr.txt (v p°φpad∞, ₧e do nich nic nezapφÜete je pak op∞t sma₧e).

if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) // Inicializace SDL s grafick²m v²stupem

{

fprintf(stderr, "Selhala inicializace SDL: %s\n", SDL_GetError());

exit(1);

}

Te∩ m∙₧eme vytvo°it okno aplikace. Mßme k tomu funkci SDL_SetVideoMode. Prvnφ dva parametry jsou rozm∞ry okna, dalÜφ parametr urΦuje barevnou hloubku (0 zachovßvß souΦasnou). Poslednφ parametr je kombinacφ r∙zn²ch flag∙. Pokud chceme po₧φvat OpenGL, musφme zadat SDL_OPENGL (nebo SDL_OPENGLBLIT). Pokud chcete fullscreen, m∙₧ete p°idat flag SDL_FULLSCREEN. V X11 (Linuxu) m∙₧ete p°epφnat mezi fullscreenem a oknem svobodn∞ kdykoliv se vßm zachce volßnφm funkce SDL_WM_ToggleFullScreen(), ale ve Windows si v SDL_SetVideoMode() jednou vyberete a to vßm pak z∙stane. Proto₧e jsme inicializovali SDL, musφme ho v p°φpad∞ erroru takΘ ukonΦit. Mß to na starosti funkce SDL_Quit().

if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL) // Vytvo°enφ OpenGL okna 640x480

{

fprintf(stderr, "Neni mozne vytvorit OpenGL okno: %s\n", SDL_GetError());

SDL_Quit(); // UkonΦenφ SDL

exit(2);

}

Nastavφme titulek okna. M∙₧eme p°idat i ikonku, ale proto₧e ₧ßdnou nemßme, pou₧ijeme NULL.

SDL_WM_SetCaption("Jeff Molofee's GL Code Tutorial ... NeHe '99", NULL); // Titulek okna

InitGL(640, 480); // Inicializace OpenGL

Hlavnφ cyklus programu. Pro opuÜt∞nφ programu pou₧ijeme prom∞nnou done (deklarovanß na zaΦßtku main(), kterou testujeme v ka₧dΘm pr∙b∞hu hlavnφm cyklem.

done = 0; // JeÜt∞ nekonΦit

while (!done) // Hlavnφ cyklus programu

{

DrawGLScene(); // Vykreslenφ scΘny

Obsluha udßlostφ by m∞la p°ijφt do zvlßÜtnφ funkce (analogie WndProc() z Windows), ale nebudeme jednoduch² k≤d komplikovat. Nejprve vytvo°φme prom∞nou typu SDL_Event. Pak pro naΦtenφ zprßv volßme v cyklu SDL_PollEvent(). Dokud p°ichßzejφ udßlosti, tak se jimi zab²vßme. Tentokrßt zareagujeme pouze na po₧adavek ukonΦenφ pomocφ klßvesy ESC. P°esuny okna, zm∞na jeho velikosti ap. se d∞jφ automaticky.

SDL_Event event; // Prom∞nnß zprßvy

while (SDL_PollEvent(&event)) // Zpracovßvat zprßvy

{

if (event.type == SDL_QUIT) // Zprßva o ukonΦenφ

{

done = 1; // UkonΦit hlavnφ cyklus

}

if (event.type == SDL_KEYDOWN) // Zprßva o stisku klßvesy

{

if (event.key.keysym.sym == SDLK_ESCAPE) // Klßvesa ESC

{

done = 1; // UkonΦit hlavnφ cyklus

}

}

}

}

Na konci u₧ jen ukonΦφme SDL.

SDL_Quit(); // UkonΦenφ SDL

return 1;

}

Pro kompilaci tutorißlu v Linuxu m∙₧eme pou₧φt p°φkaz

gcc -Wall lesson02.c `sdl-config --libs --cflags` -o lesson02

Ve Windows a Visual C++ je zprovozn∞nφ maliΦko komplikovan∞jÜφ. Vychßzφm z jednoho Φlßnku o SDL, kter² napsal FrantiÜek Jahoda, a kter² jsem kdysi stßhl z http://www.builder.cz/. Pov∞tÜinou CTRL+C & CTRL+V :-] V prost°edφ Microsoft Visual C++ postupujte takto:

  1. rozbalte SDL do urΦitΘho adresß°e nap°. C:\SDL\
  2. nahrajte SDL.dll do C:\Windows\System nebo ho v₧dy p°idejte do adresß°e projektu
  3. p°idejte v Tools\Options\Directories\Include files\ cestu k adresß°i INCLUDE v naÜem p°φpad∞ C:\SDL\INCLUDE
  4. vytvo°te nov² prßzdn² Win32 projekt: tedy File\New\Projects\Win32 Application, zvolte si jmΘno projektu a lokaci ulo₧enφ, pak klikn∞te na OK a zvolte An empty project a nakonec zvolte Finish
  5. v Project\Settings\ C\C++ \Code Generation\ navolte Multi-threaded. Toto nastavenφ prove∩te u ka₧dΘho projektu, jinak vßm to p°i kompilaci bude psßt chybu !!! (M∞ psalo, a proto jsem navolil "Multithreaded DLL").
  6. vytvo°te nov² soubor main.cpp a p°idejte ho do projektu (zdrojßk v²Üe)
  7. p°idejte do projektu SDL.lib a SDLmain.lib. Pokud nechcete pracovat p°es nabφdky jako jß, vlo₧te nßsledujφcφ k≤d za vÜechna #include.

    #pragma comment (lib,"opengl32.lib")

    #pragma comment (lib,"glu32.lib")

    #pragma comment (lib,"glaux.lib")

    #pragma comment (lib,"sdl.lib")

    #pragma comment (lib,"sdlmain.lib")

  8. nakonec nahrajte do adresß°e s programem soubor README-SDL.txt (copyright SDL)

napsal: Bernard Lidick² - Berny
maliΦko poupravoval, p°epsal do HTML a dopsal zßv∞r pro zprovozn∞nφ ve Windows: Michal Turek - Woq

ZdrojovΘ k≤dy