You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SDL2_TTF库在SDL窗口中显示动态流逝时间?

问题解答

1. 仅用SDL2_TTF成员函数能否显示动态文本?

可以,但你遇到的报错是参数类型不匹配导致的:TTF_RenderText_Solid要求文本参数为const char*,而std::to_string(float)返回的是std::string,直接传递会触发类型不兼容错误。

解决这个问题只需调用std::string的c_str()方法,将其转换为C风格字符串即可:

float elapsedTime = 45.67f;
std::string timeStr = std::to_string(elapsedTime);
// 转成const char*传入
SDL_Surface* textSurface = TTF_RenderText_Solid(yourFont, timeStr.c_str(), yourTextColor);

需要注意:每次动态内容(比如分数、生命值)变化时,都需要重新调用TTF渲染函数生成新的Surface,再转换为Texture交给SDL渲染器更新显示。

2. 封装基于SDL渲染的动态文本类

如果需要频繁更新文本(如帧率、实时分数),封装一个复用的动态文本类能大幅提升代码可维护性,还能减少不必要的重复渲染开销。以下是一个实用的实现示例:

核心设计思路

  • 保存SDL渲染器、字体、文本颜色的引用,避免重复传递参数
  • 内部维护当前文本内容和对应的Texture,仅在文本/颜色变化时重新渲染,节省性能
  • 提供统一的文本更新、颜色设置、渲染方法,支持直接传入数字类型(int/float)

示例代码

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <string>
#include <cstdio>

class DynamicText {
private:
    SDL_Renderer* m_renderer;
    TTF_Font* m_font;
    SDL_Color m_textColor;
    std::string m_currentText;
    SDL_Texture* m_textTexture = nullptr;
    int m_textWidth = 0;
    int m_textHeight = 0;

    // 内部方法:重新渲染文本并更新Texture
    void refreshTexture() {
        // 销毁旧Texture避免内存泄漏
        if (m_textTexture != nullptr) {
            SDL_DestroyTexture(m_textTexture);
            m_textTexture = nullptr;
        }

        // 生成Surface并转成Texture
        SDL_Surface* textSurface = TTF_RenderText_Solid(m_font, m_currentText.c_str(), m_textColor);
        if (!textSurface) return;

        m_textTexture = SDL_CreateTextureFromSurface(m_renderer, textSurface);
        m_textWidth = textSurface->w;
        m_textHeight = textSurface->h;
        SDL_FreeSurface(textSurface);
    }

public:
    // 构造函数:初始化依赖资源
    DynamicText(SDL_Renderer* renderer, TTF_Font* font, SDL_Color color)
        : m_renderer(renderer), m_font(font), m_textColor(color) {}

    // 析构函数:清理资源
    ~DynamicText() {
        if (m_textTexture) SDL_DestroyTexture(m_textTexture);
    }

    // 更新文本内容(仅当内容变化时重新渲染)
    void setText(const std::string& newText) {
        if (newText != m_currentText) {
            m_currentText = newText;
            refreshTexture();
        }
    }

    // 重载:支持直接传入int类型
    void setText(int number) {
        setText(std::to_string(number));
    }

    // 重载:支持float类型,可自定义小数位数
    void setText(float number) {
        char buffer[32];
        snprintf(buffer, sizeof(buffer), "%.2f", number); // 保留两位小数
        setText(std::string(buffer));
    }

    // 修改文本颜色
    void setColor(SDL_Color newColor) {
        if (newColor.r != m_textColor.r || newColor.g != m_textColor.g || 
            newColor.b != m_textColor.b || newColor.a != m_textColor.a) {
            m_textColor = newColor;
            refreshTexture();
        }
    }

    // 将文本渲染到指定坐标
    void render(int x, int y) {
        if (!m_textTexture) return;
        SDL_Rect destRect = {x, y, m_textWidth, m_textHeight};
        SDL_RenderCopy(m_renderer, m_textTexture, nullptr, &destRect);
    }

    // 获取当前文本的尺寸
    void getSize(int& outWidth, int& outHeight) {
        outWidth = m_textWidth;
        outHeight = m_textHeight;
    }
};

使用示例

// 假设已完成SDL、TTF初始化,且创建了renderer和font对象
SDL_Color white = {255, 255, 255, 255};
DynamicText scoreText(renderer, gameFont, white);
DynamicText timeText(renderer, gameFont, white);

float gameElapsedTime = 0.0f;
int playerScore = 0;

// 游戏主循环
while (isRunning) {
    // 处理事件、更新游戏逻辑...
    gameElapsedTime += deltaTime;
    playerScore += 10;

    // 更新动态文本
    scoreText.setText(playerScore);
    timeText.setText(gameElapsedTime);

    // 渲染流程
    SDL_RenderClear(renderer);
    // 渲染游戏场景...
    scoreText.render(30, 30); // 渲染分数到(30,30)
    timeText.render(30, 60);  // 渲染时长到(30,60)
    SDL_RenderPresent(renderer);
}

额外提示

  • 如果需要更美观的文本效果(如抗锯齿、阴影),只需将TTF_RenderText_Solid替换为TTF_RenderText_Blended或TTF_RenderText_Shaded即可
  • 确保字体对象TTF_Font*的生命周期长于DynamicText实例,避免出现悬空指针问题

内容的提问来源于stack exchange,提问作者Ömer Can Öztürk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:38:35