c++ 如何使用SDL2显示2D视频游戏的计数器?

vwkv1x7d  于 2023-01-10  发布在  其他
关注(0)|答案(1)|浏览(199)

我正在使用SDL 2库用C++ ver.17制作一个2D RPG类型的视频游戏,这是我自己的乐趣所在(我还不打算出售这款游戏,最多是免费公开)。我已经达到了一个点,我想在游戏的GUI窗口显示一个计数器的关键收集我的2D字符(这是一个精灵表,有4个方向的动画)。另外,我还将添加第二条消息,在游戏过程中始终显示在GUI中。我通过创建一个名为GamePanel的类来构建项目,该类代表整个游戏的管理器。这个类有一个run()方法,包含了游戏的游戏循环,循环调用常用的方法(FPS为60):
Events():用于用户事件
Update():用于更新游戏场景帧
Render():绘制并渲染游戏场景帧。
除其他事项外,在更新中()方法更新角色所收集的键的计数器,并因此更新要在场景中显示的消息。()方法将其全部呈现给我,从而向我显示消息。现在出现的问题是通过SDL2_ttf库使用文本以及随之而来的SDL_Surface的使用,包含使用SDL2_ttf字体的消息,然后转换到SDL_Texture,然后使用SDL_RenderCopy显示它()和SDL_渲染器当前()在场景中。这些段落不能在游戏循环中完成,因为这会导致PC以每秒60帧的速度做的“疲劳”。
因此,是否有一种方法来显示连续更新的消息(以60 FPS的速度)?
你能给予我一些建议,如何进行或更好,如果你已经找到了一些教程,解释给我?
我创建了一个名为TextureManager的类来处理SDL 2中的大多数图形。我将该类设置为单例,以便只有一个示例,并且能够在代码中的任何地方使用它。在该类中,我创建了一些方法:

  • 纹理管理器::加载文本(标准::字符串 * tex):用于加载SDL_Surface,然后将其转换为SDL_Texture。当然,创建的SDL_Surface必须通过SDL_FreeSurface删除。这适用于您要创建的每个纹理。
  • 纹理管理器::绘制文本(标准::字符串 * 文本,整数x,整数y,SDL_纹理 * 图像):用于绘制纹理(其包含例如文本或字符)。

在GamePanel类中,我通过调用TextureManagers来渲染所有内容,然后使用SDL_RenderPresent(m_Renderer);
我创建了一个UI类,其中包含update()和draw()方法,这些方法与要显示的消息(收集的键的计数)以及要在游戏中显示的其他消息相关。
此类是在GamePanel中的游戏循环之外创建的,更准确地说是在GamePanel::Init()方法中创建的,我在该方法中初始化了所有SDL 2库,包括SDL2_ttf(要在GUI环境中显示的字符字体)。
所以我有以下方法:

void GamePanel::update() {

    float dt = Timer::GetInstance()->GetDeltaTime();

    //player->Update(dt);
    player->update();

    // aggiorna l'interfaccia utente
    ui->update();
}

void GamePanel::Render() {

    SDL_SetRenderDrawColor(m_Renderer, 124, 218, 254, 255);
    SDL_RenderClear(m_Renderer);
    
    // Tiles
    tileM->draw();

    // Objects
    for (int i = 0; i < obj.size(); i++)
    {
        if (!obj.at(i).name.empty()) 
        {
            obj.at(i).draw();
        }
    }
    
    // Player
    player->draw(m_Renderer);

    // disegna interfaccia utente: testo indicante numero chiavi disponibili
    ui->draw();

    SDL_RenderPresent(m_Renderer);

}
9rnv2umw

9rnv2umw1#

SDL_ttf的文本渲染API并不是最好的,它可以工作,但也有一些缺点,特别是在性能方面。
文本渲染的速度实际上取决于您使用的质量设置(即您使用的函数)。旧的SDL_ttf文档规定:

实心(即TTF_RenderUTF8_Solid): 快速和脏:* [...]以高质量呈现给定文本[...]。这是所有呈现模式中呈现速度最快的模式。这会导致文本周围没有框,但文本不平滑。[...]此模式用于FPS和其他快速变化更新的文本显示。
阴影(即TTF_RenderUTF8_Shaded):“ 缓慢而漂亮,但使用实心框:* [...]文本已消除锯齿。这将比实心渲染慢,但与混合模式的时间大致相同。”
混合(即TTF_RenderUTF8_Blended):“ 慢速慢速,但在另一个图像上非常好:* [...]当您想要高质量,并且文本变化不太快时使用此选项。”

此外,你还需要将图像复制到VRAM中(这就是你所描述的向SDL_Texture的过渡)。这个操作非常慢。你应该在游戏循环中最大限度地减少使用这个函数(也许只是为了FPS计数器,但外部调试终端肯定会更快)。
对于每一个静态文本(如与NPC的对话)或任何不会改变的文本,您应该在游戏或场景的加载阶段渲染并复制到VRAM。您可能希望此类字符串具有良好的质量。因此,您需要在启动时创建所有SDL_Texture并缓存它们。然后,您只需在GamePanel::render()方法中调用SDL_RenderCopy
现在我不知道你的项目计数器变化有多快。但是如果你在计数器更新时只渲染一次文本(包括纹理的创建),那么它甚至可能在足够高的文本质量级别上变化。然后你像静态字符串一样存储纹理,直到计数器变化。这应该不会引入巨大的延迟。
但是如果有,你可以缓存单个数字。在单独的纹理中渲染从0到9的所有数字一次并存储它们。现在你只需要选择正确的纹理并渲染它们到你想要显示的数字。但是要注意,你不应该对文本这样做,因为你需要应用适当的字距调整。对于数字来说,这是可以忽略的。但是对于文本来说就不是了。如果你用单独的字形来做,文本看起来就不好了。

相关问题