web-dev-qa-db-fra.com

Comment rendre du texte en SDL2?

Je me demandais comment rendre du texte avec SDL2. J'ai trouvé une API appelée SDL_TTF et quelques tutoriels, mais ils ne fonctionnent pas avec ma situation.

J'utilise un SDL_Window et SDL_Renderer, alors que les didacticiels sont spécifiques à SDL_Surface.

Est-il possible d'utiliser SDL_TTF avec SDL_Render/SDL_Window? Si c'est le cas, comment?

33
Ethan Webster

Oui, c'est possible, étant donné que vous avez un moteur de rendu et une fenêtre et que vous n'avez pas vraiment de réflexions sur les surfaces, alors vous voudrez peut-être penser à créer une texture, voici un exemple de code

TTF_Font* Sans = TTF_OpenFont("Sans.ttf", 24); //this opens a font style and sets a size

SDL_Color White = {255, 255, 255};  // this is the color in rgb format, maxing out all would give you the color white, and it will be your text's color

SDL_Surface* surfaceMessage = TTF_RenderText_Solid(Sans, "put your text here", White); // as TTF_RenderText_Solid could only be used on SDL_Surface then you have to create the surface first

SDL_Texture* Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage); //now you can convert it into a texture

SDL_Rect Message_rect; //create a rect
Message_rect.x = 0;  //controls the rect's x coordinate 
Message_rect.y = 0; // controls the rect's y coordinte
Message_rect.w = 100; // controls the width of the rect
Message_rect.h = 100; // controls the height of the rect

//Mind you that (0,0) is on the top left of the window/screen, think a rect as the text's box, that way it would be very simple to understance

//Now since it's a texture, you have to put RenderCopy in your game loop area, the area where the whole code executes

SDL_RenderCopy(renderer, Message, NULL, &Message_rect); //you put the renderer's name first, the Message, the crop size(you can ignore this if you don't want to dabble with cropping), and the rect which is the size and coordinate of your texture

//Don't forget too free your surface and texture

J'ai essayé d'expliquer le code ligne par ligne, vous ne voyez aucune fenêtre ici car je supposais déjà que vous saviez comment initialiser un moteur de rendu qui me donnerait une idée que vous savez aussi comment initialiser une fenêtre, alors tout ce que vous besoin est l'idée sur la façon d'initialiser une texture.

Questions mineures ici, votre fenêtre s'est-elle ouverte? était-il coloré en noir? si c'est le cas, alors mes pensées étaient bonnes, sinon, vous pouvez simplement me demander et je pourrais changer ce code pour implémenter la section entière qui se compose d'un moteur de rendu et d'une fenêtre.

45
kdyz

Exemple exécutable minimal de SDL_ttf

enter image description here

Pas super efficace, mais facile à intégrer. Pour l'efficacité, voir: Comment rendre efficacement les polices et le texte avec SDL2?

Conservé dans un référentiel distinct de la source SDL principale, mais hébergé sur le même serveur officiel, cela devrait donc convenir: http://hg.libsdl.org/SDL_ttf/

Les sauts de ligne ne fonctionneront pas. Vous devez travailler avec des hauteurs de ligne.

Compiler et exécuter:

Sudo apt-get install -y libsdl2-dev
gcc -lSDL2 -lSDL2_ttf -o ttf ttf.c
./ttf /usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf

Vous devez transmettre le chemin d'accès d'un fichier de police TTF au programme.

ttf.c

#include <stdlib.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

#define WINDOW_WIDTH 300
#define WINDOW_HEIGHT (WINDOW_WIDTH)

/*
- x, y: upper left corner.
- texture, rect: outputs.
*/
void get_text_and_rect(SDL_Renderer *renderer, int x, int y, char *text,
        TTF_Font *font, SDL_Texture **texture, SDL_Rect *rect) {
    int text_width;
    int text_height;
    SDL_Surface *surface;
    SDL_Color textColor = {255, 255, 255, 0};

    surface = TTF_RenderText_Solid(font, text, textColor);
    *texture = SDL_CreateTextureFromSurface(renderer, surface);
    text_width = surface->w;
    text_height = surface->h;
    SDL_FreeSurface(surface);
    rect->x = x;
    rect->y = y;
    rect->w = text_width;
    rect->h = text_height;
}

int main(int argc, char **argv) {
    SDL_Event event;
    SDL_Rect rect1, rect2;
    SDL_Renderer *renderer;
    SDL_Texture *texture1, *texture2;
    SDL_Window *window;
    char *font_path;
    int quit;

    if (argc == 1) {
        font_path = "FreeSans.ttf";
    } else if (argc == 2) {
        font_path = argv[1];
    } else {
        fprintf(stderr, "error: too many arguments\n");
        exit(EXIT_FAILURE);
    }

    /* Inint TTF. */
    SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
    SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_WIDTH, 0, &window, &renderer);
    TTF_Init();
    TTF_Font *font = TTF_OpenFont(font_path, 24);
    if (font == NULL) {
        fprintf(stderr, "error: font not found\n");
        exit(EXIT_FAILURE);
    }
    get_text_and_rect(renderer, 0, 0, "hello", font, &texture1, &rect1);
    get_text_and_rect(renderer, 0, rect1.y + rect1.h, "world", font, &texture2, &rect2);

    quit = 0;
    while (!quit) {
        while (SDL_PollEvent(&event) == 1) {
            if (event.type == SDL_QUIT) {
                quit = 1;
            }
        }
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
        SDL_RenderClear(renderer);

        /* Use TTF textures. */
        SDL_RenderCopy(renderer, texture1, NULL, &rect1);
        SDL_RenderCopy(renderer, texture2, NULL, &rect2);

        SDL_RenderPresent(renderer);
    }

    /* Deinit TTF. */
    SDL_DestroyTexture(texture1);
    SDL_DestroyTexture(texture2);
    TTF_Quit();

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

GitHub en amont .

Testé dans Ubuntu 16.04, SDL 2.0.4.

Oui, ça l'est. Vous créez une surface avec le texte souhaité, puis vous la convertissez en une texture que vous pouvez rendre.

Quelques exemples de code d'un de mes projets:

std::string score_text = "score: " + std::to_string(score);        
SDL_Color textColor = { 255, 255, 255, 0 };
SDL_Surface* textSurface = TTF_RenderText_Solid(font, score_text.c_str(), textColor);
SDL_Texture* text = SDL_CreateTextureFromSurface(renderer, textSurface);
int text_width = textSurface->w;
int text_height = textSurface->h;
SDL_FreeSurface(textSurface);
SDL_Rect renderQuad = { 20, win_height - 30, text_width, text_height };
SDL_RenderCopy(renderer, text, NULL, &renderQuad);
SDL_DestroyTexture(text);

Cela suppose que vous avez correctement initialisé SDL_ttf et chargé une police. Dans l'exemple scoreest un int. L'écran est effacé et rendu ailleurs (je n'ai pas inclus cette partie).

Pour un exemple de travail complet, consultez le tutoriel pour SDL_ttf dans SDL2 chez Lazy Foo .

11
jpw