Direkt auf den Bildschirm zeichnen
Ein Hinweis gleich vorweg. Dieses Kapitel ist nur für denjenigen gedacht, der seine eigenen Funktionen (Bibliothek) zum Zeichnen von Linien, Kreise oder Rechtecke erstellen will. Das Zeichnen eines Pixels stellt dabei immer die Grundlage für das Zeichnen anderer grafischer Primitiven da. Dies kann sich bezüglich der Performance positiv auswirken - doch es werden dabei ein wenig mehr geometrische Kenntnisse abverlangt. Wie dem auch sei, wer sich dafür interessiert, bekommt hiermit die Grundlagen des Setzens eines Pixels. Alle anderen, die erst mal nur die SDL-Funktionen verwenden wollen, können dieses Kapitel überfliegen.Für das Zeichnen von grafischen Primitiven wie Linien, Kreise oder Polygone können Sie die Bibliothek sdl_gfx verwenden. Diese Bibliothek stellt Ihnen Basiszeichenfunktionen, welche alle auf das Zeichnen eines Pixels aufbauen, zur Verfügung. Um einen rechteckigen Bereich mit einer Farbe auszufüllen, wird der (Standard-)Bibliothek von SDL die Funktion SDL_FillRect() mitgeliefert.
Um ein Pixel zeichnen zu können, benötigen Sie wieder das Surface. In der Struktur SDL_Surface finden Sie eine Strukturvariable void *pixel. In dieser Variable werden die Farbwerte der einzelnen Pixel gespeichert. Diese Strukturvariable benötigen Sie zum Manipulieren eines Pixels. Nun sind allerdings die Strukturvariablen alle mit dem Read-only- (nur zum Lesen) Attribut ausgestattet. Dass Surface (einfach an eine Zeichen-Oberfläche denken), welches sich ja im Grafikspeicher befindet und dessen Inhalt Sie auf dem Bildschirm wiedergegeben bekommen, muss jetzt verändert werden. Sie müssen somit direkt in den Grafikspeicher schreiben - was zum derzeitigen Zeitpunkt Ihrer Kenntnisse unweigerlich zum Segmentation fault führen würde. Der Grafikspeicher ist ein recht empfindlicher Teil der Hardware. Um das Schreiben zu realisieren, müssen Sie den Speicherbereich der Grafikkarte für andere Anwendungen sperren. Sperren können Sie das Surface mit folgender Funktion:
int SDL_LockSurface(SDL_Surface *surface);
Nachdem Sie die Sperre für das Surface gesetzt haben, haben Sie direkten Zugriff auf das Pixel. Zwischen dem Aufruf von SDL_LockSurface() und dem Aufheben der Sperre mit SDL_UnlockSurface() können Sie etwas in surface->pixel schreiben und auch wieder etwas daraus lesen, ohne dass es Probleme gibt. Da nicht alle Surfaces eine Sperre benötigen, können Sie das Makro SDL_MUSTLOCK(surface) verwenden, um zu überprüfen, ob eine Sperre nötig ist oder nicht. Gibt das Makro 0 zurück, können Sie auf dem Surface lesen und schreiben, wie es Ihnen in den Kram passt. Ansonsten müssen Sie das Surface sperren.
Ab Version 1.1.8 der SDL-Bibliothek wird das Sperren rekursiv ausgeführt. Das sollten Sie beachten, weil dies die Reihenfolge des Freigebens der Sperren beeinträchtigt (Stack!).
Bei Erfolg gibt die Funktion SDL_LockSurface() 0 und bei einem Fehler -1 zurück. Um die Sperre wieder aufzuheben, müssen Sie die Funktion SDL_UnlockSurface() verwenden.
void SDL_UnlockSurface(SDL_Surface *surface);
Ein Surface sollte so schnell wie möglich wieder freigegeben werden. Natürlich sollten Sie auch hier mit dem Makro SDL_MUSTLOCK() überprüfen, ob ein Sperren zuvor überhaupt nötig war, um nicht ein nicht gesperrtes Surface freizugeben. Der Pixel alleine macht noch keinen Indian-Summer auf Ihren Bildschirm. Sie brauchen Farbinformationen. Farben werden hierbei nach dem üblichen RGB-Schema erstellt. Zum Glück stimmen hierbei mal die englischen Anfangsbuchstaben mit den Deutschen überein - RGB für Rot, Grün, Blau. Aus diesen drei Farben können Sie je nach Mischung jede andere Farbe erzeugen. der maximale Wert ist 255 und der kleinste 0. Geben Sie bspw. allen drei Werten den Wert 255, erzeugen Sie die Farbe weiß. Bei Vergabe von 0 an alle drei Werte haben Sie Schwarz. Gelb würden Sie mit der Mischung (255, 255, 0) erreichen. Sie können anschließend gerne selbst damit experimentieren.
Natürlich können Sie bei der Angabe der Farben auch einen Hexwert (0x00 = 0 und 0xFF = 255) verwenden, wenn Sie damit besser vertraut sind.
Wenn Sie jetzt der Funktion die Farbwerte für Rot, Grün und Blau übergeben haben, müssen Sie daraus noch einen 32 Bit-Wert machen - was den internen Wert von SDL für RGB wiedergibt. Diesen Wert können Sie sich mit der Funktion SDL_MapRGB() zurückgeben lassen.
Uint32 SDL_MapRGB( SDL_PixelFormat *format,
Uint8 r, Uint8 g, Uint8 b );
Der Parameter SDL_PixelFormat ist ein Mitglied der Struktur SDL_Surface und wird mit surface->format angesprochen. Die anderen drei Parameter sind die 8 Bit RGB-Werte.
Wenn Sie jetzt den Wert der Strukturvariable pixel an die Struktur SDL_Surface mit entsprechenden Informationen übergeben haben, fehlt noch eine Funktion, ohne die gar nichts auf dem Bildschirm passieren würde.
void SDL_UpdateRect( SDL_Surface *screen,
Sint32 x, Sint32 y,
Sint32 w, Sint32 h );
Damit geben Sie einen bestimmten Bereich des Surfaces an, welcher neu gezeichnet werden soll. Geben Sie für x, y, w und h den Wert 0 an, wird der komplette Bildschirm neu gezeichnet.
Wichtig ist es, dass Sie noch vor Verwendung der Funktion die Sperre für das Surface wieder freigeben.
