SDL 2.0-Unterrichtszyklus: Lektion 5 - Schneiden eines Sprite-Blattes

Bild

Von einem Übersetzer:

Dies ist eine Fortsetzung einer Reihe von Übersetzungen von Twinklebear-Tutorials, die hier im Original verfügbar sind . Die Übersetzung ist teilweise kostenlos und kann geringfügige Änderungen oder Ergänzungen des Übersetzers enthalten. Übersetzung der ersten beiden Lektionen - AutorenschaftInvalidPointerund der dritte und vierte für k1-801.


Liste der Lektionen:



Sprite-Blatt schneiden


In 2D-Spielen verwenden sie häufig ein großes Bild, um mehrere kleinere Bilder zu speichern, z. B. Kacheln in Kachelsätzen anstelle vieler kleiner Bilder für jede Kachel. Ein solches Bild wird als Sprite-Blatt bezeichnet und ist sehr praktisch für die Arbeit, da wir die zu zeichnende Textur nicht ändern müssen, sondern nur angeben, welcher Teil der Textur verwendet werden soll.

In diesem Tutorial erfahren Sie , wie Sie Teile einer Textur mit SDL_RenderCopy auswählen und wie Sie bestimmte Tastenanschlagereignisse erkennen, mit denen Sie auswählen, welcher Teil der Textur gezeichnet werden soll. Auf dem Sprite-Blatt befinden sich vier bunte Kreise:

Bild


In diesem Tutorial besteht ein Sprite-Blatt aus vielen Sprites derselben Größe. In diesem Fall ist das Schneiden nicht schwierig. Andernfalls benötigen wir für Sprites unterschiedlicher Größe eine Metadatendatei mit Informationen zum Speicherort der Teile. Für dieses Tutorial verwenden wir 4 Sprites der Größe 100x100. Der Code für diese Lektion basiert auf Lektion 4. Wenn Sie noch keinen Code zum Schreiben haben, können Sie ihn von Github erhalten .

Teileauswahl


Mit der SDL können Sie ganz einfach den Teil der Textur auswählen, den Sie zeichnen möchten. In Lektion 4 geben die verbleibenden SDL_RenderCopy- Parameter mit einem NULL-Wert die Koordinaten des Rechtecks ​​an, die bestimmen, welchen Teil der Textur wir zeichnen möchten. Wenn Sie einen NULL-Wert übergeben, geben Sie an, dass wir die gesamte Textur benötigen. Sie können jedoch problemlos die Parameter des Rechtecks ​​hinzufügen und nur einen Teil der Textur zeichnen. Nehmen Sie dazu Änderungen an der Funktion renderTexture vor, damit sie einen rechteckigen Bereich einnehmen kann, behalten Sie jedoch der Einfachheit halber eine kurze Version der Syntax der alten Version bei.

Ändern Sie renderTexture


Um nicht mehr und mehr Parameter an unsere renderTexture-Funktion zu binden und gleichzeitig die Bequemlichkeit der Standardwerte beizubehalten, werden wir sie in zwei Funktionen unterteilen. Der erste ist fast identisch mit dem Aufruf von SDL_RenderCopy, bietet jedoch einen Parameter für den Beschneidungsbereich mit dem Wert nullptr. Diese Version von renderTexture erhält den Speicherort in Form eines rechteckigen Bereichs, den wir selbst konfigurieren oder eine unserer anderen speziellen renderTexture-Funktionen verwenden können. Die neue grundlegende Renderfunktion wird sehr einfach.

/**
*  SDL_Texture  SDL_Renderer   .
*     
* @param tex  ,   
* @param ren ,    
* @param dst     
* @param clip     ( )
*                 nullptr   
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst,
        SDL_Rect *clip = nullptr)
{
        SDL_RenderCopy(ren, tex, clip, &dst);
}

Der Einfachheit halber schreiben wir eine weitere Funktion, bei der wir nicht SDL_Rect für den Speicherort erstellen müssen, sondern nur x und y angeben und unsere Anzeigefunktion die Breite und Höhe der Textur ausfüllen lassen. Wir werden eine überladene Version von renderTexture erstellen, die dies mit einigen Einstellungen für das Clipping erledigt. Fügen Sie ein Schnittrechteck als Parameter mit dem Standardwert nullptr hinzu. Falls der Schnitt übergeben wurde, verwenden wir die Breite und Höhe des Schnitts anstelle der Breite und Höhe der Textur. Daher werden wir das kleine Sprite beim Zeichnen nicht auf die Größe seines möglicherweise sehr großen Sprite-Blattes dehnen. Diese Funktion ist eine Modifikation der ursprünglichen renderTexture-Funktion und sieht sehr ähnlich aus.

/**
*  SDL_Texture  SDL_Renderer   x, y, 
*          
*    ,       
*          
* @param tex  ,   
* @param ren ,    
* @param x  x,    
* @param y  y,    
* @param clip     ( )
*                 nullptr   
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y,
        SDL_Rect *clip = nullptr)
{
        SDL_Rect dst;
        dst.x = x;
        dst.y = y;
        if (clip != nullptr){
                dst.w = clip->w;
                dst.h = clip->h;
        }
        else {
                SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
        }
        renderTexture(tex, ren, dst, clip);
}

Definieren Sie Beschneidungsrechtecke


In unserem Fall ist es sehr einfach, Schnittrechtecke mit der Methode zu berechnen, die der Kachelmethode aus Lektion 3 sehr ähnlich ist. Anstatt jedoch Zeile für Zeile zu gehen, werden wir Spalte für Spalte gehen. Somit ist das erste Stück grün, das zweite rot, das dritte blau und das vierte gelb. Die Idee des Rechnens ist dieselbe wie in Lektion 3, aber wir durchlaufen die Spalten anstelle von Zeilen. Unsere y-Koordinaten werden also berechnet, indem der Rest beim Teilen des Kachelindex durch die Anzahl der Kacheln (2) und die x-Koordinate durch Teilen des Index durch die Anzahl der Kacheln erhalten werden. Diese x- und y-Koordinaten sind x- und y-Indizes, daher übersetzen wir sie in echte Pixelkoordinaten, indem wir sie mit der Breite und Höhe des Ausschnitts multiplizieren, die für alle Kacheln gleich ist (100 x 100). Wählen Sie schließlich das zu zeichnende Stück aus, in diesem Fall das erste.

Wir möchten unsere Teile auch in die Mitte des Bildschirms zeichnen, daher berechnen wir diese x- und y-Koordinaten anhand der Breite und Höhe der Kachel anstelle der Breite und Höhe der Textur.

//iW  iH    
//   ,     ,     
int iW = 100, iH = 100;
int x = SCREEN_WIDTH / 2 - iW / 2;
int y = SCREEN_HEIGHT / 2 - iH / 2;

//    
SDL_Rect clips[4];
for (int i = 0; i < 4; ++i){
        clips[i].x = i / 2 * iW;
        clips[i].y = i % 2 * iH;
        clips[i].w = iW;
        clips[i].h = iH;
}
//     
int useClip = 0;

Wenn wir stattdessen ein komplexeres Sprite-Blatt mit gedrehten Sprites unterschiedlicher Größe verwenden würden, müssten wir Informationen über ihre Position und Drehung in einer Metadatendatei speichern, damit wir Teile leicht finden können.

Ändern Sie Bilder basierend auf der Eingabe


Um alle Teile des von uns erstellten Bildes zu überprüfen, fügen Sie die Tastatureingabeverarbeitung zur Ereignisverarbeitungsschleife hinzu und wählen Sie den angezeigten Teil mit den Tasten 1 bis 4 aus. Um festzustellen, ob eine Taste gedrückt wurde, können Sie überprüfen, ob das Ereignis vom Typ SDL_KEYDOWN ist. Wenn ja, können Sie herausfinden, welche Taste gedrückt wurde, indem Sie den Schlüsselcode innerhalb des Ereignisses mit e.key.keysym.sym überprüfen. Eine vollständige Liste der Ereignistypen , Schlüsselcodes und anderer Informationen zu SDL_Event finden Sie im Wiki.

Wenn die Taste gedrückt wird, müssen wir den Wert von useClip in die Nummer des Teils des Bildes ändern, den wir zeichnen möchten. Mit diesen Änderungen sieht die Ereignisschleife folgendermaßen aus:

while (SDL_PollEvent(&e)){
        if (e.type == SDL_QUIT)
                quit = true;
        //       
        if (e.type == SDL_KEYDOWN){
                switch (e.key.keysym.sym){
                        case SDLK_1:
                                useClip = 0;
                                *break;
                        case SDLK_2:
                                useClip = 1;
                                *break;
                        case SDLK_3:
                                useClip = 2;
                                *break;
                        case SDLK_4:
                                useClip = 3;
                                *break;
                        case SDLK_ESCAPE:
                                quit = true;
                                *break;
                        default:
                                *break;
                }
        }
}

Zeichnen Sie ein zugeschnittenes Bild


Als letztes müssen Sie den richtigen Teil des Bildes auf dem Bildschirm anzeigen! Dazu rufen wir unsere bequemere Version von renderTexture auf, um einen Teil des Bildes ohne zusätzliche Skalierung zu zeichnen und den Teil zu übertragen, den wir verwenden möchten (den in useClip verwendeten).

SDL_RenderClear(renderer);
renderTexture(image, renderer, x, y, &clips[useClip]);
SDL_RenderPresent(renderer);

Ende von Lektion 5


Wenn Sie das Programm starten, sollten Sie Teil 0 (grüner Kreis) in der Mitte des Bildschirms sehen und in der Lage sein, verschiedene Teile des Bildes mit den Zifferntasten auszuwählen. Wenn Sie auf Probleme stoßen, überprüfen Sie Ihren Code und / oder senden Sie eine E-Mail oder einen Tweet an den ursprünglichen Autor.

All Articles