SFML - 从纹理加载后 Sprite 为空白
SFML - Sprite is blank after loading from texture
我正在使用 SFML 在屏幕上显示精灵。我首先使用纹理并调用 loadFromFile() 来加载图像。这很有效,没有发生错误。似乎图像路径是正确的并且它加载了图像,但它似乎没有将数据存储在精灵中。精灵显示没有错误,但显示空白图像。
我的以下代码片段中的代码是否有问题?它们应该相当容易阅读:)。
我的代码:
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);
}
当您调用 setTexture()
成员函数时,sf::Sprite
对象不会在内部复制传递的 sf::Texture
对象。一个 sf::Sprite
只是指一个 sf::Texture
;前者不拥有后者。呈现 sf::Sprite
.
时,关联的 sf::Texture
必须存在
在 sf::Sprite
的文档中说明:
It is important to note that the sf::Sprite
instance doesn't copy the
texture that it uses, it only keeps a reference to it. Thus, a
sf::Texture
must not be destroyed while it is used by a sf::Sprite
(i.e. never write a function that uses a local sf::Texture
instance
for creating a sprite).
问题出在您的 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);
}
可能的解决方案
在 Menu
的构造函数中,sf::Texture
对象不是 本地对象 ,您可以使它成为 数据成员 / Menu
:
class Menu {
// ...
Texture bg;
Sprite background;
// ...
};
这样,Menu
拥有 bg
(与之前 Menu
的构造函数拥有 bg
相反),因此 Menu
控制 bg
的生命周期:bg
在 Menu
对象存在时保持活动状态。这一次,当您调用 Menu::draw()
时,sf::Sprite
对象确实引用了一个活跃的 sf::Texture
对象。
我正在使用 SFML 在屏幕上显示精灵。我首先使用纹理并调用 loadFromFile() 来加载图像。这很有效,没有发生错误。似乎图像路径是正确的并且它加载了图像,但它似乎没有将数据存储在精灵中。精灵显示没有错误,但显示空白图像。
我的以下代码片段中的代码是否有问题?它们应该相当容易阅读:)。
我的代码:
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);
}
当您调用 setTexture()
成员函数时,sf::Sprite
对象不会在内部复制传递的 sf::Texture
对象。一个 sf::Sprite
只是指一个 sf::Texture
;前者不拥有后者。呈现 sf::Sprite
.
sf::Texture
必须存在
在 sf::Sprite
的文档中说明:
It is important to note that the
sf::Sprite
instance doesn't copy the texture that it uses, it only keeps a reference to it. Thus, asf::Texture
must not be destroyed while it is used by asf::Sprite
(i.e. never write a function that uses a localsf::Texture
instance for creating a sprite).
问题出在您的 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);
}
可能的解决方案
在 Menu
的构造函数中,sf::Texture
对象不是 本地对象 ,您可以使它成为 数据成员 / Menu
:
class Menu {
// ...
Texture bg;
Sprite background;
// ...
};
这样,Menu
拥有 bg
(与之前 Menu
的构造函数拥有 bg
相反),因此 Menu
控制 bg
的生命周期:bg
在 Menu
对象存在时保持活动状态。这一次,当您调用 Menu::draw()
时,sf::Sprite
对象确实引用了一个活跃的 sf::Texture
对象。