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



我正在用C++版本17制作一款2D RPG类型的视频游戏,使用SDL2库是为了自己的快乐(我还不打算出售游戏,最多是免费公开)。我已经到了想要在游戏的GUI窗口中显示由我的2D角色收集的键的计数器的地步(这是一个具有4个方向的动画的精灵表)。此外,我还将添加第二条消息,在游戏期间始终显示在GUI中。我通过创建一个名为GamePanel的类来构建这个项目,该类代表整个游戏的管理者。这个类有一个名为run()的方法,它包含游戏的游戏循环。在它中,通常的方法被称为循环(FPS为60):

事件():用于用户事件
更新():更新游戏场景帧
渲染():绘制和渲染游戏场景帧。

除其他外,在Update()方法中,我会更新角色收集的关键帧计数器,从而更新要在场景中显示的消息。然后,Render()方法将其全部呈现给我,从而向我显示消息。现在出现的问题是通过SDL2_ttf库使用文本,然后使用SDL_Surface,使用SDL2_ttf字体包含消息,然后转换到SDL_Texture,然后在场景中使用SDL_RenderCopy()和SDL_RenderPresent()显示消息。这些段落不能在游戏循环中完成,因为这将导致";疲劳;PC以每秒60帧的速度进行操作。

因此,有没有办法显示持续更新的消息(以60 FPS的速度)?

如果你找到了一些向我解释的教程,你能给我一些关于如何继续的建议吗?

我创建了一个名为TextureManager的类来处理SDL2的大部分图形。我创建这个类singleton是为了只有一个实例,并且能够在代码中的任何地方使用它。在这个类中,我创建了一些方法:

  • TextureManager::LoadText(std::string*tex):用于加载SDL_Surface,然后将其转换为SDL_Text。当然,创建的SDL_Surface必须通过SDL_FreeSurface删除。这适用于要创建的每个纹理。

  • TextureManager::DrawText(std::string*text,int x,int y,SDL_Texture*image):用于绘制纹理(例如包含文本或字符)。

在GamePanel类中,我通过调用TextureManagers,然后使用SDL_RenderPresent(m_Renderer)来渲染所有内容;

我创建了一个UI类,其中包含与要显示的消息(收集的密钥的计数)以及要在游戏中显示的其他消息相关的update()和draw()方法。

这个类是在GamePanel的游戏循环之外创建的,更确切地说是在GamePanel::Init()方法中创建的,在该方法中我初始化了所有SDL2库,包括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);
}

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的所有数字并存储它们。现在,您只需要拾取正确的纹理并将其渲染到要显示的数字即可。但要注意,你不应该对文本这样做,因为那样你需要应用适当的紧排。对于数字来说,这是可以忽略的,但对于文本来说则不然。如果使用单独的字形,文本看起来就不好看了。

最新更新