SDL - kurze Übersicht(Grafik, Sound)
Ich habe mich entschlossen ein kleines Tutorial zu schreiben, weil viele Fragen im Forum über SDL in letzter Zeit kamen. Ich würde die Mods mal bitten dieses Turorial in die Sektion "Tutorial" zu verschieben, wenn ihr es als angemessen betrachtet.
Was ist SDL?
SDL ist eine Medienbibliothek, mitdem man Medien (wie Musik, Bilder,...) wiedergeben kann. Ein großer Vorteil von SDL ist das es auf vielen Plattformen läuft und damit flexibel ist, dazu ist SDL sehr einsteigerfreundlich.
In diesem Tutorial werde ich näher auf die Video- und Soundschnittstelle einegehen.
Hinweis: ich benutze den Compiler Visual Studio .NET 2003 und SDL Version 1.2.0.11 (Stand: Juni 2006).
Vorbereitung
Falls ihr SDL noch nicht habt, am Ende dieses Tutorials habe ich ein paar Links, auch zum Download von SDL.
Zudem solltet ihr nicht vergessen die LIB-Datei ihn euren Projekt zu linken und die SDL.dll muss in eurem Projektordner(also da wo die ausführbare Datei ist) sein.
Jetzt komme ich auf den Videobereich von SDL zu sprechen. Bevor man überhaupt eine Bitmap laden oder irgendeine Szene zeichnen kann, muss man SDL initialisieren. Dies geschieht mit der Funktion:
|
C-/C++-Quelltext
|
1
|
int SDL_Init(Uint32 flags)
|
Flags:
[list]
SDL_INIT_VIDEO Initialiseren von der Videoschnittstelle
SDL_INIT_EVERYTHING Initialiseren aller Schnittstellen von SDL
[/list]
Grafik
Um die Videoschnittstelle aufzubauen, brauchen wir nicht mehr als die Funktion
|
C-/C++-Quelltext
|
1
|
SDL_Surface* SDL_SetVideoMode(int Width, int Heigth, int bpp, Uint32 flags);
|
Verschieden Flags:
[list]
SDL_HWSURFACE Erstellt ein Hardwaresurface
SDL_SWSURFACE Erstellt ein Softwaresurface
SDL_DOUBLEBUF Surface mit Front- und Backbuffer
SDL_FULLSCREEN Vollbildmodus
[/list]Es gibt den Frontbuffer, dies ist die Fläche, welche man sieht. Da wir das Flag SDL_DOUBLEBUF benutzen haben wir nicht nur den sichtbaren Buffer, sondern noch einen zweiten, genannt Backbuffer. In den Backbuffer zeichnen wir die Bilder mit SDL_BlitSurface.
Danach werden die beiden Buffer geflippt, d.h. das was im Inhalt des Backbuffer ist, kommt in den Frontbuffer und wird somit sichtbar.
Den Backbuffer setzt man dazu ein, um alle Bitmaps gleichzeitig zu zeichnen.
Damit ist auch das eigentliche Prinzip um Bitmaps zu laden und zeichnen schon erklärt, man lädt eine Bitmap in den Backbuffer und flippt diesen dann, ein Beispiel folgt jetzt.
Bitmaps laden und zeichnen
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
#include <SDL.h>
#include <windows.h>
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
SDL_Surface* screen; // unser Bildschirm/Zeichenfläche/Frontbuffer
SDL_Surface* image; // unsere Bitmap
SDL_Rect src_bmp; // Maße der Bitmap
SDL_Rect dest_scr; // Maße der Bitmap auf dem Bildschirm
// SDL initialisieren
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
// Fehlerbehandlung
return 1;
}
// Videomodus setzten(640*480*32) und abspeichern
screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
if(!screen)
{
// Fehlerbehandlung
return 1;
}
// Bitmap laden und abspeichern
image = SDL_LoadBMP("C:/Test.bmp");
if(!image)
{
// Fehlerbehandlung
return 1;
}
// Werte für unsere Bitmap setzten
src_bmp.w = image->w; // Ganze Breite der Bitmap, die wir von unseren Surface beziehen
src_bmp.h = image->h; // Ganze Höhe der Bitmap, die wir von unseren Surface beziehen
src_bmp.x = src_bmp.y = 0; // Ganze Bitmap zeichen, also von obenan zeichnen (0;0)
dest_scr = src_bmp; // Ziel auf dem Bildschirm = Maße der Bitmap
// Colorkey setzen, also die Farbe, die transparent wird, hier rosa
SDL_SetColorKey(image, SDL_SRCCOLORKEY, 0xFF00FF);
// Bild auf den Backbuffer blitten(zeichnen)
SDL_BlitSurface(image, &src_bmp, screen, &dest_scr);
// Jetzt vom Backbuffer auf dn Frontbuffer
SDL_Flip(screen);
// Jetzt Aktion...
SDL_Delay(3000); // 3 Sekunden warten
// Surface löschen
SDL_FreeSurface(image);
SDL_FreeSurface(screen);
// SDL herunterfahren
SDL_Quit();
return 0;
}
|
Erklärung
Bei diesem Beispiel wird eine Bitmap mit der Funktion SDL_LoadBMP() geladen, danach wird das Image mithilfe der Funktion SDL_BlitSurface() auf den Backbuffer geblittet/gezeichnet und danach einfach nur Backbuffer und Frontbuffer getauscht per SDL_Flip(), somit wird der Backbuffer sichtbar.
Sound mit SDL
Was ist ein Spiel ohne Sound? Richtig langweilig und ohne jegliche Spannung.
Mit SDL kann man "zwar" nur Wave-Dateien laden, aber dies reicht völlig für Soundeffekte aus.
Jetzt könnte man sagen, man kann Sounds mit sndPlaySound laden und abspielen, aber mit dieser FUnktion kann man weder den Sound mixen oder einfach nur laden um selbigen später abzuspielen.
Aufbau von SDL-Sound
Im wesentliches ist es wie die Grafikschnittstelle aufgebaut, d.h. laden und abspielen. Im wesentlichen muss man die Soundschnittstelle öffnen, die Wavedatei in ein Buffer laden und
den Sound abspielen.
Jetzt an einem Beispiel:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#include <SDL.h>
Uint32 audio_len; // Länge der Audiodatei
Uint8* audio_pos; // aktuelle Position
// Callbackfunktion
void audio_msg(void* pReserved, Uint8* stream, int len);
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
SDL_AudioSpec audio; // Buffer für Audiodatei
// leeren, da nicht alle Vaiablen gebraucht
ZeroMemory(&audio, sizeof(SDL_AudioSpec));
SDL_Init(SDL_INIT_AUDIO);
// Ausfüllen
audio.channels = 2; // Stereo = 2; Mono = 1
audio.format = AUDIO_S16; // Format
audio.freq = 44100; // 44 kHz
audio.samples = 1024; // 1024 Samples (PCM)
audio.callback = audio_msg; // Callback-Funktion
// Audioschnittstelle öffnen
if(SDL_OpenAudio(&audio, NULL) < 0)
{
// Fehlerbehandlung
return 1;
}
// Audiodatei laden
if(!SDL_LoadWAV("C:/WINDOWS/Media/Windows XP-Abmeldesound.wav", &audio, &audio_pos, &audio_len))
{
// Fehlerbehandlung
return 1;
}
SDL_PauseAudio(0);
// eigentlicher Code, irgendeine Aktion
SDL_Delay(2000);// 2 Sekunden warten, da die Wavedatei nicht besonders lang
SDL_Quit(); // Schnittstelle herunterfahren
return 0;
}
|
Lösungsvorschlag für Behandlungsroutine (Callbackfunktion)
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// Callbackfunktion
void audio_msg(void *pReserved, Uint8* stream, int len)
{
// Wenn kein Sound mehr, beenden
if(audio_len == 0)
return;
// Mixen
len = ( len > audio_len ? audio_len : len );
SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
audio_pos += len;
audio_len -= len;
}
|
Erklärung zu SDL-Sound
Als erstes wird die Soundschnittstelle mit unseren Parametern erstellt. Danach wird die eigentliche Audiodatei geladen und abgespielt. Die Callbackfunktion übernimmt hier die Funktion des Mixen. Wenn man die Funktion leert lassen würde oder audio_pos und audio_len nicht setzt/verändert würde der Sound immerwieder vom Anfang gespielt werden.
Weitere Links
SDL Dokumentation
SDL downloaden