Leçon 3 : Texte
Vous aurez sûrement besoin d'utiliser du texte dans vos programmes avec SDL : pour ce faire, le mieux est d'utiliser la bibliothèque SDL_TTF, qui vous permet d'appliquer du texte sur vos surfaces à partir de polices True Type. Bien utile, vous pourrez au passage employer des polices plus fantaisiste que le sans-serif par défaut, et même l'utiliser avec OpenGL...
Pré-requis
Afin de pouvoir utiliser correctement SDL_ttf, il vous faudra télécharger deux bibliothèques. La première, disponnibles sur le site officiel de SDL, comporte toutes les méthodes que nous utiliserons, tandis que la seconde, FreeType, apporte de nouvelles fonctionnalités à SDL_ttf. Vous pourrez en télécharger les dernières versions aux adresses suivantes :
Initialisation
Avant toute chose, voyons ce dont nous avons besoin pour utiliser SDL_TTF. Tout d'abord, il nous faut un objet TTF_Font qui sera utilisé pour charger et utiliser les polices True Type. Nous le déclarerons ainsi : TTF_Font *font;. Ceci fait, il nous faudra aussi une surface text qui recevra le texte et que l'on blittera par la suite sur l'écran (dans ce tutorial nous utiliserons SDL en mode double buffering). Nous déclarerons la surface texte ainsi : SDL_Surface *text;. Nous aurons aussi besoin d'une surface "Screen" (l'écran) et d'un SDL_Rect "Rectangle_Destination".
Maintenant que nous avons tous les ingrédients nécessaires, il ne reste qu'à utiliser la fonction TTF_Init() pour initialiser la bibliothèque. N'oubliez pas, si vous ne le faites pas dans votre fonction texte comme ici, d'appeler TTF_CloseFont(font); dans votre fonction de sortie pour quitter proprement SDL_TTF.
Utilisation
Enfin du concret : nous allons créer une fonction pour appliquer le texte sur une surface (ici l'écran). De quoi aurons-nous besoin ? Du texte bien sûr, de son apparance, sa taille, sa couleur, sa position sur l'écran en X et en Y (vu que l'on blittera sur l'écran : la méthode est la même pour blitter sur une surface) et, même si ce n'est pas nécessaire, l'utilisation ou non d'un fondu de couleurs... On peut donc établir un prototype dans ce genre :
void vTexte(char* message, short x, short y, char* font_face, short font_size, Uint32 iColor, bool shaded, Uint32 iColorShaded);
Pour cet exemple, on dira que le dossier du binaire contient un fichier de police True Type "police.ttf". Vu que la fonction vTexte() demande pas mal d'arguments, on va définir des valeurs par défaut pour qu'elle soit plus simple à utiliser par la suite :
void vTexte(char* message, short x, short y, char* font_face = "./police.ttf", short font_size = 16, Uint32 iColor = 0, bool shaded = true, Uint32 iColorShaded = 0);
Il ne reste plus qu'à poser l'implémentation de la fonction, après quoi vous aurez droits à des explications en bonne et dûe forme :
void vTexte(char* message, short x, short y, char *font_face, short font_size, Uint32 iColor, bool shaded, Uint32 iColorShaded) { // Les objets SDL_Color utilisés pour la couleur du texte SDL_Color color, colorShaded; // On récupère les valeurs RGB de iColor color.r = (iColor & SDL_MapRGB(Screen->format,255,0,0)) >> 16; color.g = (iColor & SDL_MapRGB(Screen->format,0,255,0)) >> 8; color.b = (iColor & SDL_MapRGB(Screen->format,0,0,255)); if (shaded) { // Idem pour la couleur du fondu colorShaded.r = (iColorShaded & SDL_MapRGB(Screen->format,255,0,0)) >> 16; colorShaded.g = (iColorShaded & SDL_MapRGB(Screen->format,0,255,0)) >> 8; colorShaded.b = (iColorShaded & SDL_MapRGB(Screen->format,0,0,255)); } font = TTF_OpenFont(font_face, font_size); // Chargement de la police if (!font) fprintf(stderr, "Impossible de charger la taille %dpt depuis %s: %s\n", font_size, font_face, SDL_GetError()); // Rendu du texte normal avec la couleur iColor if (!shaded) text = TTF_RenderText_Solid(font, message, color); // Rendu du texte avec fondu vers la couleur iColorShaded else if (shaded) text = TTF_RenderText_Shaded(font, message, color, colorShaded); // Maintenant la surface 'text' contient le texte. if (text == NULL) fprintf(stderr, "Impossible de rendre le texte : %s\n", SDL_GetError()); else if (text!=NULL) { Rectangle_Destination.x = x; Rectangle_Destination.y = y; Rectangle_Destination.w = text->w; Rectangle_Destination.h = text->h; // On blitte la surface aux coordonnées définies par le rectangle if (SDL_BlitSurface(text, NULL, Screen, &Rectangle_Destination) < 0) fprintf(stderr, "Impossible de blitter le texte : %s\n", SDL_GetError()); // Après quoi on libère la surface. SDL_FreeSurface(text); } // Fermeture de la police. TTF_CloseFont(font); }
Explications. Tout d'abord, on récupère la couleur du texte. Quand on utilisera la fonction vTexte(), on passera la couleur avec la fonction SDL_MapRGB() : elle renvoie un Uint32 (comme iColor) et est plus simple (les puristes utiliseront directement le code octal). La fonction SDL_MapRGB se définit ainsi : SDL_MapRGB(SDL_PixelFormat* format de pixels, Uint8 rouge, Uint8 vert, Uint8 bleu). Le format de pixels à passer sera Screen->format (celui de l'écran). Les différentes couche de la couleur (rouge, vert et bleu : RVB) seront définies par trois nombres entre 0 et 255. Ainsi, pour obtenir du rouge, on fera SDL_MapRGB(Screen->format,255, 0,0). Pour du magenta, on fera SDL_MapRGB(Screen->format,255,0,255), pour du bleu sombre SDL_MapRGB(Screen->format,0,0,50)etc. Au début de la fonction, on créé les objets de couleur SDL_Color auquels on affecte les valeurs de iColor et iColorShaded (opération binaire).

Le résultat du code ci-dessus.
Une fois que nous avons la couleur, on charge la police dans l'objet TTF_Font (avec la taille donnée) gràce à la fonction TTF_OpenFont() : elle attend comme argument l'adresse du fichier ttf et la taille de police à utiliser. Ceci fait, on écrit le texte dans la surface "text" : si la variable shaded est sur false, on rend le texte normalement avec la fonction TTF_RendText_Solid(), qui attend comme arguments l'objet TTF_Font, le texte a écrire et la Couleur (en objet SDL_Color). Si elle est positive, on rend le texte avec fondu gràce à la fonction TTF_RenderText_Shaded(), qui attend les mêmes arguments que TTF_RenderText_Solid() + la couleur de fondu. Ceci fait, il ne reste plus qu'à blitter la surface "text" à l'écran. On vérifie d'abord qu'elle n'est pas vide et, ceci fait, on définit la position du Rectangle en X et en Y, après quoi on blitte la surface et on la libère. Ceci fait, il ne reste plus qu'à libérer 'font' avec la fonction TTF_CloseFont(font).
Conclusion
Cette fonction a pour but de vous montrer comment utiliser SDL_TTF, mais vous pouvez, par exemple, charger une police en début de programme pour l'utiliser sans la recharger. Dans ce cas, n'oubliez pas de la libérer à la sortie. Voilà à peu près tout ce qu'il y a à savoir sur SDL_TTF. Vous pourrez également l'utiliser avec OpenGL : pour ce faire, il suffit de transformer la surface "text" en texture OpenHL (ce qui se fait sans difficulté). Voilà tout. Bon code.