Satyria

SDL-Programmierung / Ellipsen

int ellipseColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
int ellipseRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int aaellipseColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
int aaellipseRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int filledEllipseColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
int filledEllipseRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
rendererRenderer des Fensters
xx-Position
yy-Position
rxRadius X-Achse
ryRadius Y-Achse
colorDie Farbe des Pixels (Format 0xRRGGBBAA)
rRotanteil
gGrünanteil
bBlauanteil
aalphablendig (Deckung zum Hintergrund)

Beispiel:

Sourcen: ellipse.c

<Kreise | GFX Übersicht | Dreiecke >

SDL-Programmierung / Kreise

int circleColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
int circleRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int arcColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
int arcRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int aacircleColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
int aacircleRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int filledCircleColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
int filledCircleRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int pieColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
int pieRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int filledPieColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
int filledPieRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
rendererRenderer des Fensters
xx-Position
yy-Position
radRadius
startBeginn des Ausschnittes (in Grad)
endEnde des Ausschnittes (in Grad)
colorDie Farbe des Pixels (Format 0xRRGGBBAA)
rRotanteil
gGrünanteil
bBlauanteil
aalphablendig (Deckung zum Hintergrund)

Beispiel:

Sourcen: kreis.c

<Rechtecke | GFX Übersicht | Ellipsen >

SDL-Programmierung / Rechtecke

int rectangleColor (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
int rectangleRGBA (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int roundedRectangleColor (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
int roundedRectangleRGBA (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int boxColor (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
int boxRGBA (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
int roundedBoxColor (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
int roundedBoxRGBA (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
rendererRenderer des Fensters
x, x1, x2x-Position
y, y1, y2y-Position
radRadius Ecke
colorDie Farbe des Pixels (Format 0xRRGGBBAA)
rRotanteil
gGrünanteil
bBlauanteil
aalphablendig (Deckung zum Hintergrund)

Beispiel:

Sourcen: rechteck.c

<Linien | GFX Übersicht | Kreise >

SDL-Programmierung / Linien

int hlineColor     (SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)    
 int hlineRGBA      (SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)    
 int vlineColor     (SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)    
 int vlineRGBA      (SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)    
 int lineColor      (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)    
 int lineRGBA       (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)    
 int aalineColor       (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)       
 int aalineRGBA     (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)    
 int thickLineColor (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)    
 int thickLineRGBA  (SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
rendererRenderer des Fensters
x, x1, x2x-Position
y, y1, y2y-Position
colorDie Farbe des Pixels (Format 0xRRGGBBAA)
rRotanteil
gGrünanteil
bBlauanteil
aalphablendig (Deckung zum Hintergrund)
widthDicke der Linie

Beispiel:

Sourcen: line.c

<Punkte | GFX Übersicht | Rechtecke >

SDL-Programmierung / Punkte

int pixelColor (SDL_Renderer *renderer, Sint16 x, Sint16 y, Uint32 color)
int pixelRGBA (SDL_Renderer *renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
rendererRenderer des Fensters
xx-Position
yy-Position
colorDie Farbe des Pixels (Format 0xRRGGBBAA)
rRotanteil
gGrünanteil
bBlauanteil
aalphablendig (Deckung zum Hintergrund)

Beispiel:

Sourcen: pixel.c

< GFX Übersicht | Linien >

SDL-Programmierung / gfx_Programmierung

Auf den Bildschirm zeichnen

Eine kleine Info: Das Zeichnen mit SDL kann auch direkt in SDL2 erfolgen. Dies würde laut Literatur auch Performance bringen. Hier in dieser Beschreibung verzichte ich allerdings darauf. Ich verwende dazu die Funktionen aus der SDL_gfx Libary.

Die SDL_gfx Libary bietet hier einige Funktionen an. Darunter das Zeichnen von Punkten, Quadraten, Kreise usw. Aber fangen wir erstmal klein an, mit den Pixeln.

Als Ausgang verwenden wir den Source Code 3.c. Allerdings modifizieren wir es ein wenig, da wir auf das Laden eines Bildes verzichten.

Damit zerstören wir die Anzeige des Bildes, welches uns für diese Versuche stören würde.

Zunächst müssen wir es dem Kompiler mitteilen, dass wir die SDL_gfx Libarys benötigen und laden die entsprechenden Headers.

Die Funktion, die wir als erstes verwenden, ist pixelRGBA(). In dieser wird zunächst angegeben, auf welchem Ziel der Pixel gezeichnet werden soll -> renderer. Der Pixel wird dann an die Position x und y gemalt in der Farbe (Rot (255), Grün (0), Blau(0)) und mit voller Deckung (255).

Sourcecode: 4.c

Da wir wieder eine zusätzliche Bibliothek verwenden, müssen wir dies auch wieder bei der Kompilierung berücksichtigen:

Für 32-Bit

gcc -o 4.exe 4.c -Ic:/msys32/mingw32/include -Lc:/msys32/mingw32/lib -lmsys-2.0 -lSDL2_gfx -lSDL2_image -lSDL2main -lSDL2 -mwindows

Und für 64-Bit:

gcc -o 4.exe 4.c -Ic:/msys64/mingw64/include -Lc:/msys64/mingw64/lib -lmsys-2.0 -lSDL2_gfx -lSDL2_image -lSDL2main -lSDL2 -mwindows

Das Zeichnen eines Kreises

Hier nochmal kurz eine andere Funktion als Beispiel. Wir zeichnen einen Kreis.


  circleRGBA(render, x, y, 30, R, G, B, 255);
… 

Sourcecode: 5.c

Eine gesamte Auflistung aller Befehle findest Du in meiner SDL_gfx Aufstellung.

<< Übersicht | < Bilder anzeigen und speichern | Auf Eingaben reagieren >

Bilder anzeigen und speichern

In diesem Kapitel möchte ich ein Bild anzeigen lassen. Als Grundprogramm verwenden wird den Sourcecode „2.5.c„.

Da wir bereits ein Fenster anzeigen lassen konnten, werden wir dies nun einfach mit der Anzeige eines Bildes erweitern. Es gibt hierzu eine zusätzliche Bibliothek, SDL_Image, die wir dazu verwenden werden.
SDL selbst benötigt dazu einen Renderer. Dies ist eine Struktur, die viele Informationen über das Bild enthält, die SDL intern benötigt. Diese hängt an dem Fenster, welches wir erzeugt haben. Da wir diese Struktur später für vieles brauchen, legen wir dies global an. Das gleiche machen wir auch für das Bild, welches wir anzeigen möchten. Dieses wird allerdings in eine Texture abgelegt

Während der Initialisierung müssen wir noch ein paar Dinge tun. Zunächst initialisieren wir SDL_Image, da wir ein Bild laden wollen und diese Bibliothek uns hier in vieler Hinsicht unterstützt. Dies machen wir direkt nach der SDL-Initialisierung.

Damit der entsprechende Renderer da ist, müssen wir ihn mit CreateRender() mit Bezug auf unser Fenster erstellen.

Damit haben wir schon das System soweit vorbereitet und kommen auf das laden des Bildes.
Dazu erstellen wir zunächst eine neue Funktion „LadeBild“. In dieser Funktion laden wir das Bild mit der Funktion IMG_LoadTexture() und geben ihr das Ziel (bild) mit den Infos aus renderer und den Dateinamen an. Wenn es nicht funktioniert hat, wird NULL zurückgegeben und wir geben eine Fehlermeldung raus.

Kommen wir nun zum main(). Nach der Initialisierung laden wir zunächst das Bild. Danach wird es mit SDL_RenderCopy in den renderer kopiert und mit SDL_RenderPresent angezeigt. Das war es schon.

Sourcecode: 3.c
Bild: blume.png

Das Kompilieren des Programms

Da wir nun hier eine neue Bibliothek verwenden, müssen wir es beim Kompilieren auch angeben, dass es so ist. Dies wird mit diesem Aufruf gemacht:

gcc -o 5.exe 5.c -Ic:/msys64/mingw64/include -Lc:/msys64/mingw64/lib -lmsys-2.0 -lSDL2_image -lSDL2main -lSDL2 -mwindows

oder hier 32-Bit:

gcc -o 5.exe 5.c -Ic:/msys32/mingw32/include -Lc:/msys32/mingw32/lib -lmsys-2.0 -lSDL2_image -lSDL2main -lSDL2 -mwindows

Übrigens: Jetzt können Bilder in den Formaten: GIF, JPG, LBM, PCX, PNG, PNM, TGA, TIF, XCF, XPM und XV mit den entsprechenden Funktionen geladen werden.

Das Speichern eines Bildes

Da SDL eigentlich für die Programmierung von Spielen erstellt wurde, gibt es von SDL selbst nur ein speichern in unkomprimierten BMP-Format. SDL_Image bietet hier mehr Formate an, welches ich hier mal beschreibe. Nachteil ist immer der, dass es nur „Screenshots“ sind und wenig mit Grafikprogrammen zu tun hat. Aber wenigstens gibt es dazu einen Weg.

Wenn wir die Funktionen „IMG_Save…“ anschauen, benötigen wir ein surface. Dies ist eine alte Methode, die unter SDL1 Verwendung fand. SDL2 unterstützt es weiterhin, aber hier im Kurs haben wir nur Renderer und Texturen benutzt. Also brauchen wir ein Surface, auf dem die Pixel des Bildes abgelegt sind. Zunächst erzeugen wir mit SDL_CreateRGBSurfaceWithFormat ein entsprechendes Surface, welches unserem Fenster entspricht. Danach kopieren wir die Daten aus dem Renderer in dieses Surface mit SDL_RenderReadPixels. Jetzt sind die Daten dort, wo wir sie auch brauchen und können es mit z.B. IMG_SavePNG abspeichern.

Sourcecode: 3.5.c
Bild: blume.png

Als JPG speichern

Auch hier werden wir von SDL_Image unterstützt und wir verwenden die Funktion IMG_SaveJPG. Diese können wir einfach für IMG_SavePNG ersetzen. Allerdings wird hier ein weiterer Parameter übergeben, der die Komprimierung angibt. Dieser bedeutet bei einem Wert von 100, keine Komprimierung und je kleiner der Wert wird, um so höher wird sie. Allerdings verliert das Bild seine Qualität.

Sourcecode: 3.6.c
Bild: blume.png

<< Übersicht | < Das erste Programm | Zeichnen >

Das erste Programm

Mit diesem Tutor möchte ich Euch ein wenig das SDL (Simple DirectMedia Layer) Programmieren zeigen. Wie ich bereits zuvor geschrieben habe, benutzen wir hierfür eine Windowsumgebung und MSYS2.
Aber fangen wir gleich an, damit wir auch was sehen, hier das erste Beispiel:

Sourcecode: 1.c

Kompiliert wird es mit:

gcc -o 1.exe 1.c -Ic:/msys64/mingw64/include -Lc:/msys64/mingw64/lib -lmsys-2.0 -lSDL2main -lSDL2 -mwindows

und ausgeführt wird es mit:

./1

Bei diesem Programm wird ein SDL-Fenster für 2000 Millisekunden geöffnet.

Zunächst muss man den Kompiler mitteilen, welche Header benötigt werden. die geschieht mit #include <SDL2/SDL.h>. Danach definiere ich zwei Konstanten, die mir die Fenstergröße festlegen. Der globale Variable fenster wird das SDL_Window zugewiesen. Diese wird später das Fenster beherbergen. Da C alle Funktionen bekannt sein müssen, wird hier die Funktion Initialisierung() bekannt gemacht. Was darin steht, kommt später.

Im eigentlichen Hauptprogramm (main) steht dann allerdings relativ wenig. Zunächst wird die Funktion der Initialisierung ausgeführt und anschließend wird mit SDL_Delay 2000 Millisekunden gewartet. Danach wird das Programm beendet.

In der Funktion Initialisierung() steht da schon mehr. Zunächst muss man SDL Initialisieren, damit überhaupt SDL funktioniert. Dies geschieht mit SDL_Init. Hier wird noch angegeben, was wir den von SDL benötigen. In unserem Fall einfach nur die Grafikfunktion. Allerdings werden auch Events initialisiert, aber hierzu später.

Wenn es schief ging, wird eine Fehlermeldung herausgegeben. SDL_GetError gibt uns sogar einen genaueren Grund an, warum es nicht ging.

Mit SDL_CreateWindow wird dann das Fenster erzeugt, welches wir hier dann sehen. Der Funktion werden der Titelname, die Position und die Eigenschaft des Fensters übergeben.

Auch hier wird eine Fehlermeldung herausgegeben, wenn das Fenster nicht erzeugt werden konnte.

Reagieren auf eine Eingabe

Na ja, eigentlich kann man dieses Programm nicht wirklich als gut bezeichnen. Ein Fenster wird geöffnet und dann irgendwann wieder geschlossen.

Wir machen es nun ein bisschen spannender und reagieren zumindest mal auf das Schließsymbol.
Dazu müssen wir eine Abfrage erstellen, die dann entsprechend reagieren kann. Statt mit SDL_Delay auf das Ende zu warten, setzen wir hier eine neue Funktion ein, die wir einfach mal Eingabe() nennen. Da es zu fast unendlich vielen Eingaben kommen kann und wir alles irgendwie verarbeiten müssen, machen wir hier noch eine While-Schleife darum:

Unsere Eingabe()-Funktion hat folgendes aussehen:

Zunächst benötigen wir hier eine SDL_Event Variable, die wir event nennen. Dort werden die „Events“ abgelegt, wenn es welche gibt.

In der while-schleife fragen wir mit SDL_PoolEvent die Warteschleife der Events ab und legen das Ereignis nach &event. Über switch(event.type) fragen wir dann dieses Event ab.

Zunächst reagieren wir nur auf „SDL_QUIT„, was das schließen des Fensters bedeutet und beenden das Programm.

Sourcecode: 2.c

Programm sauber beenden

Das Programm, welches bisher geschrieben wurde, ist bisher sehr einfach geschrieben worden. Damit aber ein SDL-Programm sauber läuft, sollten noch ein paar Dinge beachtet werden.

Am Anfang des Programms wird SDL Initialisiert und sperrt einige Ressourcen des Betriebssystems. Wird Das Programm allerdings nicht sauber beendet, wird dem Betriebssystem einige Ressourcen nicht zurückgegeben. Bei den heutigen Rechnern ist das kleine Programm noch kein Problem, aber wenn diese größer werden, kann es irgendwann zu Problemen führen. Deshalb werden wir dieses Programm etwas verändern und die entsprechenden Ressourcen, auch bei einem Fehler, wieder dem System zurückgeben.

Wie gesagt, wird zunächst SDL Initialisiert und anschließend ein Fenster geöffnet. Wenn es nun beim Fenster öffnen zu einem Fehler kommt, müssen wir die Initialisierung wieder rückgängig machen. Dies geschieht ganz einfach mit SDL_Quit(). Also nach dem öffnen des Fensters ändern wir die Fehlerbehandlung:

Unser Loop, also unser Eingabefunktion, hat nun einen gravierenden Fehler. Es ist eine Endlosschleife, wenn es da nicht diesen harten Ausgang hätte…
Aber hier müssen wir auch irgendwie reagieren, wenn das Programm geschlossen wird. Dies sollte im Hauptprogramm „main()“ erfolgen. Dazu schreiben wir unseren Loop um. Allerdings müssten wir hier noch aus der Eingabe-Funktion wissen, ob nun das Programm beendet werden soll. Dazu ändern wir zunächst diese Eingabe-Funktion, mit der Möglichkeit, dass wir Werte daraus zurückgeben:

Zunächst setzen wir die Variable „done“ auf „0“. Diese Zahl halten wir, solange das Programm, oder später eventuell kein Fehler, passierte. Mit return(done) geben wir diesen Code zurück.
Wenn nun das Fenster geschlossen wird, wird done mit 1 belegt und am Ende dann per return(done) zurückgegeben.

In unserem Hauptprogramm fragen wir genau diesen Wert ab:

Auch hier verwenden wir eine Variable „done„. Die Schleife wird sooft wiederholt, wie done = 0 ist. Sobald die Funktion Eingabe eine 1 zurückgibt, wird done mit 1 belegt und die Schleife beendet.
Jetzt können wir dem System nun alles freigeben. dies geschieht mit SDL_DestroyWindow und SDL_Quit.
Unser Programm wird beendet

Sourcecode: 2.5.c

< Übersicht | Bilder anzeigen und speichern >

SDL Programmierung (Start)

Vorab: Es wäre schön, wenn Ihr einen Link auf www.satyria.de in Euren Projekten hinterlasst und eventuell mir per E-Mail (SDL@satyria.de) bescheid gebt. Über jedes Interesse daran würde mich freuen.

Ich selbst beschreibe es hier in einer Windowsumgebung. Wie wir GCC und SDL zum Programmieren einrichten, beschreibe ich unter SDL-Biblothek unter Windows. Dies installiert MSYS2, welches wir hier verwenden. Es kann aber auch relativ einfach nach Linux portiert werden. Wie diese Sourcen auszusehen haben und wie hier Kompiliert wird, beschreibe ich unter SDL für Linux.

Über SDL

Simple DirectMedia Layer ist eine plattformübergreifende Entwicklungsbibliothek, die über OpenGL und Direct3D Zugriff auf Audio-, Tastatur-, Maus-, Joystick- und Grafikhardware auf niedriger Ebene bietet. Es wird von Videowiedergabesoftware, Emulatoren und beliebten Spielen verwendet, einschließlich Valves preisgekröntem Katalog und vielen Humble Bundle– Spielen.
SDL unterstützt offiziell Windows, Mac OS X, Linux, iOS und Android. Unterstützung für andere Plattformen finden Sie im Quellcode.
SDL ist in C geschrieben, funktioniert nativ mit C ++ und es sind Verbindungen für mehrere andere Sprachen verfügbar, einschließlich C # und Python.
SDL 2.0 wird unter der Lizenz zlib vertrieben . Mit dieser Lizenz können Sie SDL in jeder Software frei verwenden.

Übersetzt aus http://libsdl.org/

Besser kann man das eigentlich nicht beschreiben!

Inhalt

Weitere Infos erhaltet Ihr bei: http://de.wikibooks.org/wiki/SDL oder https://wiki.libsdl.org

« Zurückblättern - Weiterblättern »