Multimediaentwicklung mit SDL
Input-Handling in der Praxis: Maus
Eine kurze Anmerkung zuvor:
Die folgende Applikation ist natürlich noch bei weitem nicht optimiert. Die langsame Geschwindigkeit des blit von Bild und Hintergrund bemerkt man noch sehr stark. Codeoptimierung (z.B. RLE oder Surfaceformatierung) wird aber noch in späteren Kapiteln besprochen.
#include <stdlib.h>
#include <iostream.h>
#include "SDL.h"
#include "SDL_image.h"
int main()
{
// Die zwei bereits bekannten Surfaces deklarieren
SDL_Surface *display;
SDL_Surface *image;
SDL_Surface *hintergrund;
SDL_Event event;
int quit = 0;
SDL_Rect drect;
SDL_Rect srect;
if ( SDL_Init( SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "SDL konnte nicht initialisiert werden: %s\n",
SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
display = SDL_SetVideoMode( 800, 600, 16, SDL_SWSURFACE);
if ( display == NULL )
{
fprintf(stderr, "Konnte kein Fenster: Auflösung 800x600 oeffnen: %s\n",
SDL_GetError());
exit(-1);
}
// Bild laden
image = IMG_Load("tux-transparent.png");
if (image == NULL)
{
fprintf(stderr, "Das Bild konnte nicht geladen werden: %s\n",
SDL_GetError());
exit(-1);
}
// Hintergrundbild laden
hintergrund = IMG_Load("hintergundbild.jpg");
if (hintergrund == NULL)
{
fprintf(stderr, "Das Bild konnte nicht geladen werden: %s\n",
SDL_GetError());
exit(-1);
}
// Mauszeiger verstecken
SDL_ShowCursor(0);
// Kompletten Hintergrund aufbauen
SDL_BlitSurface( hintergrund, 0, display, 0 );
SDL_Flip( display );
// Event-Handling
while( quit == 0)
{
while( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_MOUSEMOTION:
printf( "Mausposition: x: %i und y: %i\n", event.motion.x,
event.motion.x);
// alte stelle wieder fuellen
SDL_BlitSurface(hintergrund, &drect, display, &drect);
SDL_UpdateRects(display,1,&drect);
// Setzen des Quellbereichs
srect.x = 0;
srect.y = 0;
srect.w = image->w; // das gesamte Bild
srect.h = image->h; // das gesamte Bild
// Setzen des Zielbereichs
drect.x = event.motion.x;
drect.y = event.motion.y;
drect.w = image->w;
drect.h = image->h;
// kopiere surface auf display-surface
SDL_BlitSurface(image, &srect, display, &drect);
// den veränderten Bildschirm-Bereich auffrischen
SDL_UpdateRects(display,1,&drect);
break;
case SDL_MOUSEBUTTONDOWN: // Quit beim Druecken des
// Mousebuttons
quit = 1;
break;
default:
break;
}
}
}
// Das Bitmap-Surface löschen
SDL_FreeSurface(image);
exit(0);
}
Detail:
Die komplette Initialisierung ist wie gehabt. Wir nutzen dieses Mal ein transparentes PNG für unser Bild. In einem späteren Kapitel werde ich auch zeigen, dass wir auch Farbwerte als Transparenzfarbe angeben können und somit den selben Effekt auf normale Bilder erzeugen. Danach laden wir ein Hintergundbild, welches wir einfach direkt und komplett auf das display-surface blitten und mit SDL_Flip auch komplett neu zeichnen. Oft stört der Mauszeiger: SDL_ShowCursor(0) schaltet den Mauscursor aus. Setzt mal den Parameter wieder auf 1, so wird der Zeiger wieder eingeschaltet.
Nun folgt das eigentliche Eventhandling. Auch hier sieht es aus wie bei unserem Tastaturbeispiel. Es im Prinzip auch gleich. Wir unterscheiden nur den event.type. Die Struktur des MouseMotionEvents ist so, dass die Elemente x und y die Position hält. Diese Werte nutzen wir, und setzen in der Schleife das SDL_Rect des Zielbereichs (hier also drect).
Quellen
Über den Autor
Marco Kraus betreut libSDL.de und ist unter marco@libsdl.de zu erreichen.
Er freut sich über jegliche Form von Feedback.

