SFML开发国际象棋游戏:非窗口绘制函数无法加载纹理的问题
问题根源
SFML 的 Sprite 并不存储纹理的像素数据,它仅持有一个指向 Texture 对象的引用。你在 load_textures() 函数中声明的 Texture texture 是局部变量,函数执行完毕后这个局部变量会被销毁,导致 boardSprite 引用的纹理变成无效状态——这就是渲染时显示白色矩形的原因。
而将纹理加载代码放在 draw_board() 内时,局部 Texture 变量的生命周期覆盖了整个渲染循环,纹理始终有效,因此能正常显示。
解决方案
把 Texture 改为 GameRender 类的成员变量,让它的生命周期与类实例保持一致,避免提前销毁。
1. 修改类声明,添加纹理成员
class GameRender { private: sf::Texture boardTexture; // 作为类成员保存纹理,延长生命周期 sf::Sprite boardSprite; // 你的其他成员变量(如window等) };
2. 更新 load_textures() 函数
void GameRender::load_textures(){ if (!boardTexture.loadFromFile("../graphics/textures/board.png")){ throw std::runtime_error("Failed to load board texture"); } boardSprite.setTexture(boardTexture); }
3. 优化纹理加载时机(可选)
建议在 GameRender 的构造函数中调用一次 load_textures(),而不是在 draw_board() 开头反复加载:
GameRender::GameRender() { // 初始化window等操作... load_textures(); } void GameRender::draw_board(){ // 移除这里的load_textures()调用 Event event; Vector2u prevWinSize = window.getSize(); const float desiredAspectRatio = 1.0f / 1.0f; const float basicScaleX = static_cast<float>(prevWinSize.x) / boardSprite.getGlobalBounds().width; const float basicScaleY = static_cast<float>(prevWinSize.y) / boardSprite.getGlobalBounds().height; boardSprite.setScale(basicScaleX, basicScaleY); while (window.isOpen()){ // 原循环代码保持不变 } }
这样修改后,纹理会在类初始化时加载一次,生命周期与类实例绑定,boardSprite 引用的纹理始终有效,就能正常渲染棋盘了。
内容的提问来源于stack exchange,提问作者Arondy
相关产品推荐
相关产品推荐

