2015-03-12 4 views
1

У меня есть меню, в котором есть много текста визуализируется, что может изменить в размер/цвет/положение, так что я сделал две функции в моем классе меню ...:SDL2 рендеринга текста вопросы

void drawText(string text,int text_size,int x,int y, Uint8 r,Uint8 g,Uint8 b); 
void updateTexts(); 

Функция updateTexts() находится в игровом цикле и содержит множество функций drawText. Когда я запускаю программу, я замечаю, что память программ постепенно увеличивается с 4 мб около 1 гб (она должна оставаться на уровне 4 МБ), после чего она падает. Я предполагаю, что проблема существует, потому что TTF_OpenFont «запускается постоянно, хотя мне нужен способ иметь возможность создавать новые размеры шрифтов« на лету », поскольку мое меню изменяется на основе ввода пользователей.

Есть ли лучший способ сделать это ?

код для двух функций:

void Menu::drawText(string text,int text_size,int x,int y, Uint8 r,Uint8 g,Uint8 b) 
{ 
    TTF_Font* arial = TTF_OpenFont("arial.ttf",text_size); 
    if(arial == NULL) 
    { 
     printf("TTF_OpenFont: %s\n",TTF_GetError()); 
    } 
    SDL_Color textColor = {r,g,b}; 
    SDL_Surface* surfaceMessage = TTF_RenderText_Solid(arial,text.c_str(),textColor); 
    if(surfaceMessage == NULL) 
    { 
     printf("Unable to render text surface: %s\n",TTF_GetError()); 
    } 
    SDL_Texture* message = SDL_CreateTextureFromSurface(renderer,surfaceMessage); 
    SDL_FreeSurface(surfaceMessage); 
    int text_width = surfaceMessage->w; 
    int text_height = surfaceMessage->h; 
    SDL_Rect textRect{x,y,text_width,text_height}; 

    SDL_RenderCopy(renderer,message,NULL,&textRect); 
} 

void Menu::updateTexts() 
{ 
    drawText("Item menu selection",50,330,16,0,0,0); 
    drawText("click a menu item:",15,232,82,0,0,0); 
    drawText("item one",15,59,123,0,0,0); 
    drawText("item two",15,249,123,0,0,0); 
    drawText("item three",15,439,123,0,0,0); 
    drawText("item four",15,629,123,0,0,0); 
} 

ответ

0

Каждый открытый шрифт, созданный поверхность и создается текстура использует память

Если коллекция различных ресурсов, которые вам требуется. ограничено, например. только 3 разных text_size, лучше создать их один раз, а затем повторно использовать. Например, храня их в какой-то кэш:

std::map<int, TTF_Font*> fonts_cache_; 

TTF_Font * Menu::get_font(int text_size) const 
{ 
    if (fonts_cache_.find(text_size) != fonts_cache_.end()) 
    { 
    // Font not yet opened. Open and store it. 
    fonts_cache_[text_size] = TTF_OpenFont("arial.ttf",text_size); 
    // TODO: error checking... 
    } 

    return fonts_cache_[text_size]; 
} 

void Menu::drawText(string text,int text_size,int x,int y, Uint8 r,Uint8 g,Uint8 b) 
{ 
    TTF_Font* arial = get_font(text_size) 
    ... 
} 

Menu::~Menu() 
{ 
    // Release memory used by fonts 
    for (auto pair : fonts_cache_) 
    TTF_CloseFont(pair.second); 
    ... 
} 

Для динамических ресурсов, которые должны быть выделены на каждом вызове метода вы не должны забывать, чтобы освободить их. В настоящее время вы не освобождаете память от TTF_Font* arial, SDL_Texture* message; do:

void Menu::drawText(string text,int text_size,int x,int y, Uint8 r,Uint8 g,Uint8 b) 
{ 
    ... 
    TTF_CloseFont(arial); 
    SDL_DestroyTexture(message); 
} 
+0

Сделал то, что вы сказали, и устранил проблему. большое спасибо. Я даже не знал, что вы можете закрыть шрифт :) :) – doomglhfcn

+0

@doomglhfcn Если мой ответ помог, отметьте его как принятый. – rutsky

+1

Создание и уничтожение поверхностей при каждом изменении текста дает плохую производительность. Таким образом, я создал систему, в которой шрифт загружается один раз, и я делаю одну текстуру, используя карту символов. Затем используйте карту для поиска символов, отображаемых при отображении строки. Подобно тому, как вы будете делать растровый шрифт – Zammalad