2014-04-05 83 views
29

我想知道如何使用SDL2呈現文本。我找到了一個名爲SDL_TTF的API和一些教程,但它們不適用於我的情況。如何在SDL2中呈現文本?

我使用的是SDL_WindowSDL_Renderer,而教程僅針對SDL_Surface

是否可以使用SDL_TTFSDL_Render/SDL_Window?如果是這樣,怎麼樣?

回答

34

是的,這是可能的,因爲你有一個渲染器和一個窗口,再加上你真的沒有與表面涉足任何想法,那麼你可能要介意創造的質感,這裏是一個示例代碼

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 

我試着逐行解釋代碼,因爲我已經假定你已經知道如何初始化渲染器,這會給我一個想法,即你也知道如何初始化一個窗口,那麼你所需要的就是關於如何初始化紋理的想法。

這裏有個小問題,你的窗戶打開了嗎?它是黑色的嗎?如果是這樣,那麼我的想法是正確的,如果沒有,那麼你可以問我,我可以改變這段代碼來實現由渲染器和窗口組成的整個部分。

+43

你可以請釋放你的表面嗎? – Leonardo

+0

@Leonardo釘住了它。 – saadtaame

+0

Message_rect.w = 100; //程序員是否應該知道他的文本最終會變得多寬? – engineerX

8

是的。你用你想要的文本創建一個曲面,然後將其轉換爲可以渲染的紋理。

從我的項目之一,一些示例代碼:

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

這是假設你已經正確初始化SDL_ttf和加載的字體。在這個例子中,score是一個int。屏幕被清除並呈現到其他地方(我沒有包含該部分)。

如需完整的工作示例,請查看tutorial for SDL_ttf in SDL2 at Lazy Foo

+0

這會因某種原因未處理的內存異常? –

+0

@EthanWebster哦,代碼僅僅是作爲一個(非工作)的例子,因爲它缺少重要的東西來運行,比如init代碼,錯誤檢查等等。 – jpw

+0

@EthanWebster我用一些工作示例代碼添加了一個指向教程的鏈接。 – jpw

10

SDL_ttf最小的可運行的例子

enter image description here

不是超級效率,但容易整合。爲了提高效率,請參閱:Rendering fonts and text with SDL2 efficiently

不停地在比主SDL源分開回購,但同樣的官方服務器上託管的,所以應該是罰款:http://hg.libsdl.org/SDL_ttf/

換行符將無法正常工作。你必須使用線條高度。

您必須在TTF字庫文件的路徑傳遞給程序爲:

./ttf /usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf 

編譯:

sudo apt-get install -y libsdl2-dev 
gcc -lSDL2 -lSDL2_ttf -o ttf ttf.c 

測試在Ubuntu 16.04,SDL 2.0.4。

在GitHub的倉庫代碼:https://github.com/cirosantilli/cpp-cheat/blob/e52ed4b838e2697d8f44ab5bef3e7a170705d48e/sdl/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; 
}