【问题标题】:SDL2 rendering text issuesSDL2 呈现文本问题
【发布时间】:2015-03-12 14:48:43
【问题描述】:

我有一个菜单,其中有很多可以改变大小/颜色/位置的文本,所以我在菜单类中创建了两个函数...:

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

updateTexts() 函数位于游戏循环中并包含许多 drawText 函数,当我启动程序时,我注意到程序内存逐渐从 4mb 增加到 1gb(应该保持在 4mb)然后它崩溃了。我认为问题存在是因为 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);
}

【问题讨论】:

    标签: c++ sdl-2


    【解决方案1】:

    每个打开的字体、创建的表面和创建的纹理都会占用内存。

    如果您需要的不同资源的收集有限,例如只有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* arialSDL_Texture* message的内存;做:

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

    【讨论】:

    • 照你说的做,解决了问题。多谢。我什至不知道你可以关闭字体:) :)
    • 每次需要更改文本时创建和销毁表面会导致性能不佳。因此,我制作了一个系统,其中一次加载字体,然后使用字符映射制作单个纹理。然后在显示字符串时使用地图“查找”要呈现的字符。类似于你如何做一个位图字体
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 2022-12-15
    • 2020-05-17
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多