Leçons sur SDL 2: Leçon 4 - Etirement PNG

Bonjour à tous! Il s'agit de la quatrième leçon de SDL 2. J'ai décidé de combiner les deux leçons en une seule, car dans l'original, elles sont petites. Mais ils peuvent être trouvés ici et ici . Eh bien, commençons la leçon.

Premièrement, nous déciderons de ce que nous ferons. Aujourd'hui, nous allons apprendre à télécharger des images d'une autre extension (pas BMP), à savoir: PNG. Refaites l'image dans un format différent pour accélérer le travail et redimensionner l'image. Nous allons travailler avec cette image:

image

L'installation


Donc, nous apprenons d'abord comment télécharger le PNG. Dans le jeu de fonctionnalités SDL 2 standard, il n'y a pas de téléchargement d'une image au format non BMP. Pour télécharger un format différent, vous devez installer l'extension.

Voici les instructions:

Windows
Vous accédez à cette page et téléchargez les archives ZIP ou TAR.GZ à partir de la section Bibliothèques de développement . Décompressez-les et jetez-les dans le dossier avec le compilateur.

Linux
Si votre système utilise Debian, vous devez entrer ces commandes:

apt-cache search libsdl2-image apt-get install libsdl2-image-dev 

Si Yellowdog Updater, Modified est utilisé, vous entrez ces commandes:

 yum search SDL2_image-devel yum  SDL2_image-devel 


Mac OS
Téléchargez le fichier DMG et lisez le fichier Lisez-moi.

Écrire un code


Après avoir défini SDL_image, nous commençons à écrire du code. Tout d'abord, comme toujours, nous allons connecter les bibliothèques, définir les tailles de fenêtre et créer 3 variables globales.

 #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; 

Notez que j'ai connecté SDL_image.h séparément, car il s'agit d'une bibliothèque distincte.

Ensuite, nous écrivons 3 fonctions, connues de nous, dans lesquelles nous allons ajouter et changer quelque chose, comme d'habitude.

Init ()
 bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } 


Ici, nous avons ajouté l'initialisation du module SDL_image. Pour l'initialiser, créez d'abord une variable int , nous avons des drapeaux , et enregistrez-y tous les drapeaux que vous souhaitez utiliser pour l'initialisation.

Liste de tous les drapeaux
SDL_INIT_PNG - initialise le téléchargeur d'images PNG;
SDL_INIT_JPG - initialise le téléchargeur d'images JPG;
SDL_INIT_TIF - initialise le téléchargeur d'images TIF;

Ensuite, nous écrivons cette condition:

 if ( !( IMG_Init( flags ) & flags ) ) 

La fonction IMG_Init () renvoie les indicateurs qu'elle a pu initialiser. Si elle a rendu les drapeaux, mais que celui que nous voulions manquait, nous renvoyons une erreur. Très simple. Notez également que j'utilise IMG_GetError au lieu de SDL_GetError , car nous recherchons une erreur dans la fonction du module SDL_image , pas SDL .

Je veux également noter que j'ai décidé d'utiliser le type bool pour renvoyer un - c'est une manière plus rationnelle.

Continuons à écrire notre programme, écrivons la fonction Load () , dans laquelle nous chargeons une image PNG et la convertissons.

Charge
 bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } 


Ici, nous téléchargeons l'image avec la nouvelle fonction IMG_Load . Sa fonction est la même que celle de SDL_LoadBMP et le résultat est le même - il renvoie une instance de la classe SDL_Surface . Pour trouver des erreurs lors du chargement, nous utilisons également IMG_GetError .

Il est temps de se convertir. Tout d'abord, un peu de théorie. Peu de gens le savent, mais lors du téléchargement d'une image, elle est téléchargée au format 24 bits, et la plupart des écrans modernes sont au format 32 bits. Et chaque fois que nous affichions l'image à l'écran, elle était d'abord refaite au format 32 bits. Pour les programmes simples, cela n'a pas d'importance, mais lors de la création d'une sorte de grand projet, cela affectera considérablement les performances, nous prendrons donc et au stade du chargement des images, nous les recréerons au format d'affichage. La fonction SDL_ConvertSurface vous aidera. Il prend 3 valeurs: la surface que nous voulons formater, le format dans lequel nous voulons formater et les drapeaux. nous voulons formater l'image de la fleur , lui passer le premier paramètre. Le deuxième paramètre est le format de la surface de la fenêtre, nous n'utiliserons pas de drapeaux. Cette fonction renvoie une copie de la surface, que nous affectons immédiatement à flower . Pour rechercher des erreurs, nous prenons la fonction SDL_GetError () , car nous travaillons déjà avec des surfaces, et elles proviennent de SDL , et non de SDL_image .

Ensuite, nous écrivons la fonction Quit, y ajoutons une seule fonction.

Quitter
 void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } 


Nous avons ajouté IMG_Quit pour non initialiser le module SDL_image.

Principal


Maintenant, la chose la plus simple reste - la fonction principale .

 int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } 

Pour commencer, initialisez et créez tout ce dont vous avez besoin et téléchargez les fichiers nécessaires. Nous ne nous arrêterons pas ici.

  SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; 

Après cela, créez un objet de classe SDL_Rect . Nous en aurons besoin pour étirer l'image. Si vous remarquez, l'image de la fleur est 4 fois plus petite que la taille de la fenêtre (2 fois plus mince et 2 fois plus basse), et nous devons l'étirer à la taille de la fenêtre. Donc, dans la largeur du rectangle bg_flower, écrivez la valeur de la largeur de la fenêtre, et en hauteur - la hauteur de la fenêtre. définissez les coordonnées sur 0, de sorte que l'image s'affiche dans le coin supérieur gauche.

Pour afficher des images avec redimensionné, il existe une fonction spéciale. Cela ressemble à ceci:

  SDL_BlitScaled(flower, NULL, scr, &bg_flower); 

Cela prend 4 significations. La première est l'image que nous voulons afficher, la seconde est le rectangle que nous voulons couper de cette image (si nous voulons prendre l'image entière, nous écrivons NULL), la troisième est la surface sur laquelle nous voulons afficher l'image, et la quatrième est le même rectangle, dimensions et les coordonnées dont nous prenons pour étirer ou compresser et afficher l'image.

Ensuite, mettez simplement à jour la surface de l'écran, définissez le délai, quittez et retournez 0.

  SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; }; 

C'est là que notre programme se termine. Afin de compiler ce miracle, vous devez ajouter -lSDL2_image, comme une autre option de compilation.

Et là-dessus, nous terminerons pour aujourd'hui. Voici le code que nous avons obtenu:

 #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; SDL_BlitScaled(flower, NULL, scr, &bg_flower); SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; }; 

Salut tout le monde!

<< Leçon précédente || Prochaine leçon >>

Source: https://habr.com/ru/post/fr456656/


All Articles