Prościej już być nie może, niż na GameCreatorze! ;-)
Pierwsze co musisz zrobić, by skorzystać z biblioteki SDL, to oczywiście dołączyć jej plik nagłówkowy, by zapoznać kompilator z zawartością tej biblioteki:
#include <SDL.h>
Program używający SDL zaczyna się w normalnej, standardowej funkcji main
;-) Jest tak nawet gdy tworzysz projekt dla systemu Windows, bo wtedy SDL realizuje windowsową funkcję WinMain
gdzieś w swoim wnętrzu. Takie rozwiązanie jest konieczne, by można było przenosić kod pomiędzy różnymi platformami systemowymi bez żadnych zmian [inne systemy niż Windows nie używają przecież tej niestandardowej funkcji WinMain
:-P].
#include <SDL.h> //Tu zaczyna się nasz program używający SDL int main() { //Tu będzie jego treść... }
Biblioteka SDL składa się z 8 podsystemów, z których każdy odpowiada za coś innego. Przypomina tym trochę bibliotekę DirectX, jednak jak pewnie wiesz, są między nimi pewne różnice ;-J Poniżej masz listę tych podsystemów wraz z opisem, czym się zajmuje każdy z nich:
VIDEO | Podsystem odpowiedzialny za wyświetlanie grafiki 2D |
---|---|
AUDIO | Podsystem odpowiedzialny za podstawową obsługę dźwięku |
EVENTS | Podsystem odpowiedzialny za obsługę zdarzeń |
CDROM | Podsystem odpowiedzialny za odtwarzanie muzyki CD-Audio i obsługę CD-ROMu |
JOYSTICK | Podsystem obsługi joysticka |
TIMER | Podsystem odmierzania czasu |
THREADS | Podsystem odpowiedzialny za obsługę wątków |
FILES | Podsystem wejścia/wyjścia plikowego |
Aby rozpocząć zabawę z SDL, trzeba ją najpierw zainicjalizować [przygotować do pracy]. Zanim wywołasz jakąkolwiek funkcję z biblioteki SDL, musisz więc najpierw wywołać funkcję SDL_Init
, której nagłówek prezentuje się tak:
int SDL_Init(Uint32 flags);
Pozwala Ci ona wybrać podsystemy, z których masz zamiar korzystać i przygotowuje je do pracy. Automatycznie przygotowuje trzy podsystemy: EVENTS, THREADS i FILES. Możesz wybrać dodatkowe podsystemy, podając jej odpowiednie parametry, które poznasz lada moment.
Jak widzisz, funkcja SDL_Init
pobiera tylko jeden parametr, jednak jego typ może wydawać ci się dziwny :-P Biblioteka SDL wprowadza kilka nowych, własnych typów danych, by zapewnić jednakowy rozmiar danych w pamięci na różnych platformach. Typ Uint32
możesz rozumieć jako typ unsigned int
z gwarancją, że zajmie 32 bity w pamięci.
Parametr ten służy głównie do wybierania, które podsystemy mają być dodatkowo zainicjalizowane, jednak ma też kilka innych możliwości. Możesz w nim przekazać jedną z poniższych stałych:
SDL_INIT_VIDEO |
Podsystem graficzny |
SDL_INIT_AUDIO |
Podsystem dźwięku |
SDL_INIT_TIMER |
Podsystem odmierzania czasu |
SDL_INIT_CDROM |
Podsystem obsługi CD-ROMu |
SDL_INIT_JOYSTICK |
Podsystem obsługi joysticka |
SDL_INIT_EVERYTHING |
Inicjalizuje wszystkie podsystemy |
SDL_INIT_NOPARACHUTE |
SDL nie będzie za ciebie obsługiwać wyjątków |
SDL_INIT_EVENTTHREAD |
Do odbierania zdarzeń zostanie utworzony osobny wątek |
Powyższe stałe są flagami bitowymi, więc możesz je łączyć operatorem |
. Przykładowo inicjalizacja podsystemów VIDEO i TIMER mogłaby wyglądać tak:
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
Funkcja zwraca 0
gdy inicjalizacja się powiodła. W przeciwnym razie zwraca -1
.
Czasami nie da się zainicjalizować od razu wszystkiego. Przykładowo chcesz najpierw wyświetlić menu gry, z którego użytkownik wybierze czy chce skorzystać z joysticka. Dopiero wtedy można zainicjalizować podsystem joysticka. Co zrobić w takiej sytuacji? Jak uruchomić podsystem JOYSTICK, skoro funkcja SDL_Init
była już wywołana?! :-/
Twórcy biblioteki przygotowali ją na takie sytuacje ;-) Możesz włączyć dodatkowe podsystemy w późniejszym czasie. Służy do tego funkcja SDL_InitSubSystem
i pobiera ona dokładnie te same parametry, co SDL_Init
. Tak wygląda jej nagłówek:
int SDL_InitSubSystem(Uint32 flags);
Gdy wszystko poszło dobrze, zwraca 0
. W przypadku błędu zwraca -1
.
Gdy dany podsystem przestaje ci być potrzebny, możesz wyłączyć tylko ten jeden podsystem, pozostawiając resztę. Robi się to funkcją SDL_QuitSubSystem
. Pobiera ona te same parametry, co poprzednie funkcje. Nie zwraca jednak żadnej wartości. To zresztą logiczne, bo jeśli chcesz wyłączyć jakiś podsystem i miałoby się to nie udać, naraziłoby cię na kolejne błędy :-P Musi się udać zawsze.
void SDL_QuitSubSystem(Uint32 flags);
Ostateczne zakończenie całego SDL wymaga funkcji SDL_Quit
. Nie pobiera ona żadnych parametrów i nic nie zwraca. Zamyka ona wszystkie podsystemy [włącznie z tymi trzema domyślnymi] i zwalnia zasoby przydzielone dla SDL. Jej nagłówek to:
void SDL_Quit(void);
Tą funkcję będziesz wywoływać, gdy zechcesz zakończyć pracę z SDL. Jeśli obawiasz się, że zapomnisz po sobie posprzątać, możesz na przykład ustawić tą funkcję jako handler w wywołaniu atexit
gdy tylko inicjalizacja SDL zakończy się sukcesem, np. tak:
if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0 ) { //Coś poszło nie tak. Wyświetl komunikat o błędzie i zakończ z kodem błędu cout << "Błąd inicjalizacji SDL!" << endl; return -1; } //Inicjalizacja się powiodła, więc ustawiamy handler atexit() atexit(SDL_Quit);
Przy okazji warto zauważyć, że w systemie Windows bibliotka SDL przekierowuje standardowe kanały wyjściowe do plików mająych nazwy stdout.txt
i stderr.txt
. Gdyby tak nie robiła, głupawy Windows tworzyłby ci dodatkowe okno konsoli gdy tylko coś wypiszesz na stdout [ach te Windowsy.. ;-P].
Najdziwniejszą funkcją inicjalizacji SDL jest SDL_WasInit
. Sprawdza ona, które podsystemy zostały zainicjalizowane, a które nie. Oto jej nagłówek:
Uint32 SDL_WasInit(Uint32 flags);
Co ciekawe, możesz zapytać ją o konkretny zestaw podsystemów, podając odpowiednie flagi SDL_INIT_*
w parametrze. Funkcja weźmie te twoje flagi i sprawdzi tylko te podsystemy, o które pytasz. Jako wynik zwróci wartość, która jest połączeniem flag bitowych tylko uruchomionych podsystemów, i tylko spośród tych, o które pytasz. Mówiąc prościej: z podanych przez Ciebie flag wywala te, których podsystemy były wyłączone, i zwraca to co zostało.
Najprostszy sposób użycia tej funkcji to pytanie o to, czy jeden konkretny podsystem już działa. Wykorzystujemy wtedy fakt, że jeśli żaden z podanych przez ciebie podsystemów nie pracuje, wynikiem funkcji będzie 0
:
if ( SDL_WasInit(SDL_INIT_AUDIO) ) //Podsystem AUDIO działa... else //Podsystem AUDIO nie działa...
Wiele funkcji SDL w przypadku błędu zwraca po prostu -1
. Ta wartość niewiele jednak mówi o przyczynie błędu. W tym celu istnieje funkcja SDL_GetError
.
bla bla bla
#include <SDL.h> #include <iostream> using namespace std; int main() { cout << "Startujemy SDL..." << endl; // Przygotuj podsystemy: domyślne, VIDEO i AUDIO. if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0 ) { cout << "Błąd inicjalizacji SDL: " << SDL_GetError() << endl; return -1; } cout << "SDL gotowy do pracy!" << endl; // Tu będzie normalne działanie programu... cout << "Kończymy pracę SDL..." << endl; // Wyłączamy wszystkie podsystemy SDL. SDL_Quit(); cout << "Program zakończony" << endl; }