问题描述
我正在使用SFML在屏幕上显示精灵。我首先使用纹理并调用loadFromFile()加载图像。这很好,不会发生任何错误。图像路径似乎正确并且已加载图像,但似乎未将数据存储在Sprite中。精灵显示无误,但显示空白图像。
我的代码:
Main.cpp
#include <SFML/Graphics.hpp>
#include "Menu.h"
using namespace sf;
int main()
{
VideoMode vm = VideoMode::getDesktopMode();
int width = vm.width,height = vm.height;
RenderWindow window(VideoMode(width,height),"score Arena v1.0",Style::Fullscreen);
window.setPosition(Vector2i(0,0));
Menu menu(width,height);
while (window.isopen())
{
Event event;
while (window.pollEvent(event))
{
switch (event.type) {
case Event::Closed:
window.close();
break;
//when a key is pressed
case Event::Keypressed:
if (Keyboard::isKeypressed(Keyboard::Escape))
window.close();
break;
}
}
window.clear();
menu.draw(window);
window.display();
}
return 0;
}
Menu.h
#pragma once
#include <string>
#include <SFML/Graphics.hpp>
using namespace std;
using namespace sf;
class Menu {
int page = 0;
string title = "score Arena";
string labels[4]{
"Single Player","Multi Player","Options","Exit"
};
Sprite background;
int width,height;
public:
Menu(int,int);
void draw(RenderWindow &window);
};
Menu.cpp
#include "Menu.h"
#include <SFML/Graphics.hpp>
#include <iostream>
Menu::Menu(int width,int height) {
this->width = width;
this->height = height;
Texture bg;
if (!bg.loadFromFile("menuBg.jpg"))
std::cout << "Error loading image!" << std::endl;
background.setTexture(bg);
}
void Menu::draw(RenderWindow &window) {
window.draw(background,RenderStates::Default);
}
解决方法
当您调用sf::Sprite
成员函数时,sf::Texture
对象不会在内部复制传递的setTexture()
对象。 sf::Sprite
只是指sf::Texture
;前者不拥有后者。呈现sf::Texture
时,关联的sf::Sprite
必须存在。
sf::Sprite
的文档中对此进行了说明:
请注意,
sf::Sprite
实例不会复制 它使用的纹理,仅保留对其的引用。因此,sf::Texture
使用sf::Sprite
时不得销毁它 (即,永远不要编写使用本地sf::Texture
实例的函数 用于创建精灵)。
问题出在您的Menu
的构造函数中:
Menu::Menu(int width,int height) {
this->width = width;
this->height = height;
Texture bg; // <-- it is local variable !!!
if (!bg.loadFromFile("menuBg.jpg"))
std::cout << "Error loading image!" << std::endl;
background.setTexture(bg); // <-- associating sprite to a local object!!!
// bg goes out of existence!!!
}
程序控制流离开构造函数后,sf::Texture
对象bg
就不复存在了,因为bg
是构造函数内部的局部变量。结果,sf::Sprite
对象background
– Menu
数据成员 –超过了其关联的sf::Texture
对象bg
–本地对象。
然后,在Menu::draw()
中使用此sf::Sprite
对象background
,该对象内部指的是不再存在的sf::Texture
对象:
void Menu::draw(RenderWindow &window) {
window.draw(background,RenderStates::Default);
}
可能的解决方案
在sf::Texture
的构造函数中,Menu
对象不是 local对象,您可以使其成为{{的 data成员 1}}:
Menu
通过这种方式,class Menu {
// ...
Texture bg;
Sprite background;
// ...
};
拥有Menu
(与以前一样,bg
的构造函数拥有Menu
)因此bg
控制Menu
的生命周期:bg
对象生存期间,bg
被保持活动状态。这次,当您调用Menu
时,Menu::draw()
对象确实引用了一个活跃的sf::Sprite
对象。