Cycle de leçon SDL 2.0: Leçon 5 - Découpage d'une feuille Sprite

image

D'un traducteur:

Ceci est la suite d'une série de traductions de didacticiels Twinklebear, disponibles dans l'original ici . La traduction est partiellement gratuite et peut contenir des modifications ou des ajouts mineurs du traducteur. Traduction des deux premières leçons - paternitéInvalidPointeret les troisième et quatrième pour k1-801.


Liste des cours:



Tranchage de feuille de sprite


Souvent dans les jeux 2D, ils utilisent une grande image pour stocker plusieurs images plus petites, par exemple, des tuiles dans des ensembles de tuiles au lieu de nombreuses petites images pour chaque tuile. Une telle image s'appelle une feuille de sprite et elle est très pratique pour le travail, car nous n'avons pas besoin de changer la texture que nous voulons dessiner, mais seulement d'indiquer quelle partie de la texture utiliser.

Dans ce didacticiel, nous verrons comment sélectionner des parties d'une texture à l'aide de SDL_RenderCopy , ainsi qu'un peu de détection des événements de frappe spécifiques que nous utiliserons pour sélectionner la partie de la texture à dessiner. Il y aura quatre cercles colorés sur la feuille de sprite:

image


Dans ce didacticiel, une feuille de sprite se compose de nombreux sprites de la même taille, auquel cas le découpage n'est pas difficile. Sinon, pour les sprites de différentes tailles, nous aurions besoin d'un fichier de métadonnées avec des informations sur l'emplacement des pièces. Pour ce tutoriel, nous utiliserons 4 sprites de taille 100x100. Le code de cette leçon est basé sur la leçon 4, si vous n'avez pas encore de code à écrire, vous pouvez l'obtenir auprès de Github .

Sélection de pièces


En utilisant le SDL, il est très facile de sélectionner la partie de la texture que vous souhaitez dessiner. Dans la leçon 4, les paramètres SDL_RenderCopy restants avec une valeur NULL signifient les coordonnées du rectangle qui détermine quelle partie de la texture nous voulons dessiner. En passant la valeur NULL, nous indiquons que nous avons besoin de la texture entière, mais nous pouvons facilement ajouter les paramètres du rectangle et dessiner seulement une partie de la texture. Pour ce faire, nous apporterons des modifications à la fonction renderTexture afin qu'elle puisse prendre une zone rectangulaire, tout en conservant une version courte de la syntaxe de l'ancienne version pour plus de commodité.

Changer le renduTexture


Afin de ne pas attacher de plus en plus de paramètres à notre fonction renderTexture et en même temps garder la commodité des valeurs par défaut, nous allons le diviser en deux fonctions. Le premier est presque identique à l'appel de SDL_RenderCopy, mais il fournit un paramètre de région de découpage avec une valeur nullptr. Cette version de renderTexture recevra l'emplacement sous la forme d'une zone rectangulaire, que nous pouvons configurer nous-mêmes ou utiliser l'une de nos autres fonctions spécialisées de renderTexture. La nouvelle fonction de rendu de base devient très simple.

/**
*  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);
}

Pour plus de commodité, nous allons écrire une autre fonction où nous n'aurions pas besoin de créer SDL_Rect pour l'emplacement, mais seulement fournir x et y et laisser notre fonction d'affichage remplir la largeur et la hauteur de la texture. Nous allons créer une version surchargée de renderTexture qui le fera avec certains paramètres pour gérer l'écrêtage. Ajoutez un rectangle de coupe comme paramètre avec la valeur par défaut nullptr et dans le cas où la coupe a été passée, nous utiliserons la largeur et la hauteur de la coupe au lieu de la largeur et la hauteur de la texture. Ainsi, nous n'allongerons pas le petit sprite à la taille de sa feuille de sprite potentiellement très grande lorsqu'il est dessiné. Cette fonction est une modification de la fonction renderTexture d'origine et ressemble beaucoup.

/**
*  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);
}

Définir des rectangles de découpage


Dans notre cas, il est très facile de calculer des rectangles de découpage en utilisant la méthode très similaire à la méthode de mosaïque de la leçon 3 , mais au lieu de procéder ligne par ligne, nous allons procéder colonne par colonne. Ainsi, la première pièce sera verte, la seconde sera rouge, la troisième sera bleue et la quatrième sera jaune. L'idée de l'informatique est la même que dans la leçon 3, mais nous parcourons les colonnes au lieu des lignes. Ainsi, nos coordonnées y sont calculées en obtenant le reste lors de la division de l'indice de tuile par le nombre de tuiles (2), et la coordonnée x en divisant l'indice par le nombre de tuiles. Ces coordonnées x et y sont des indices x et y, nous les traduisons donc en coordonnées pixel réelles en multipliant par la largeur et la hauteur de la découpe, qui est la même pour toutes les tuiles (100x100). Enfin, sélectionnez la pièce à dessiner, en l'occurrence la première.

Nous aimerions également dessiner nos pièces au centre de l'écran, nous calculons donc ces coordonnées x et y en utilisant la largeur et la hauteur de la tuile au lieu de la largeur et la hauteur de la texture.

//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;

Si, à la place, nous utilisions une feuille de sprite plus complexe avec des sprites tournés de différentes tailles emballés ensemble, nous aurions besoin de stocker des informations sur leur emplacement et leur rotation dans un fichier de métadonnées afin de pouvoir facilement trouver des pièces.

Modifier les images en fonction de l'entrée


Pour vérifier toutes les parties de l'image que nous avons créées, nous ajoutons le traitement d'entrée au clavier à la boucle de traitement des événements et sélectionnons la partie affichée à l'aide des touches 1-4. Pour déterminer si une touche a été enfoncée, vous pouvez vérifier si l'événement est de type SDL_KEYDOWN et si oui, nous pouvons savoir quelle touche a été enfoncée en vérifiant le code de touche à l'intérieur de l'événement à l'aide de e.key.keysym.sym. Une liste complète des types d'événements , des codes de clé et d'autres informations sur SDL_Event est disponible sur le wiki.

Lorsque la touche est enfoncée, nous devons changer la valeur de useClip au numéro de la partie de l'image que nous voulons dessiner. Avec ces modifications, la boucle d'événements ressemble à ceci:

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;
                }
        }
}

Dessinez une image recadrée


La dernière chose à faire est d'obtenir la bonne partie de l'image sur l'écran! Nous le ferons en appelant notre version plus pratique de renderTexture pour dessiner une partie de l'image sans mise à l'échelle supplémentaire et en transférant la partie que nous voulons utiliser (celle utilisée dans useClip).

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

Fin de la leçon 5


Lorsque vous démarrez le programme, vous devriez voir la partie 0 (cercle vert) au centre de l'écran et être en mesure de sélectionner différentes parties de l'image à l'aide des touches numériques. Si vous rencontrez des problèmes, revérifiez votre code et / ou envoyez un e-mail ou un tweet à l'auteur d'origine.

All Articles