我最近通过一本书开始学习 SFML,并提出了一个问题,当您加载图像时,您会得到一个大的白色方块。
我有类
TextureHolder
用于管理游戏资源,例如纹理,精灵等(尚未完成)。我试图给它一个 RAII 方法,所以现在它不起作用(我通过书本学习)
纹理.hpp
#pragma once
#include <map>
#include <memory>
#include <SFML/Graphics.hpp>
namespace Textures {
enum class ID { Landscape, Airplane, Missile };
}
class TextureHolder final {
public:
void load(Textures::ID id, const std::string& filename);
sf::Texture& get(Textures::ID id);
const sf::Texture& get(Textures::ID id) const;
private:
std::map<Textures::ID, std::unique_ptr<sf::Texture>> m_TextureMap;
};
纹理.cpp
#include <iostream>
#include "Textures.hpp"
void TextureHolder::load(Textures::ID id, const std::string &filename) {
std::unique_ptr<sf::Texture> texture(new sf::Texture());
if (!texture->loadFromFile(filename)) {
std::cerr << "Failed to load texture from file: " << filename << std::endl;
return;
}
m_TextureMap.insert(std::make_pair(id, std::move(texture)));
}
sf::Texture &TextureHolder::get(const Textures::ID id) {
const auto found = m_TextureMap.find(id);
return *found->second;
}
const sf::Texture& TextureHolder::get(const Textures::ID id) const {
const auto found = m_TextureMap.find(id);
return *found->second;
}
游戏.hpp
#pragma once
#include <bitset>
#include <SFML/Graphics.hpp>
enum Movement {
Up,
Down,
Left,
Right,
MovementCount
};
class Game final {
public:
explicit Game();
void run();
~Game() = default;
private:
void processEvents();
void update(sf::Time deltaTime);
void render();
void handlePlayerInput(sf::Keyboard::Key , bool );
sf::RenderWindow m_window;
sf::Texture m_texturePlane;
sf::Sprite m_spritePlane;
std::bitset<MovementCount> m_isMoving;
};
游戏.cpp
#include "Game.hpp"
#include <iostream>
#include "Textures.hpp"
namespace {
constexpr short WIDTH = 640;
constexpr short HEIGHT = 480;
const std::string TITLE = "SFML Application";
constexpr float PLAYER_SPEED = 500.0f;
}
Game::Game() : m_window(sf::VideoMode(WIDTH, HEIGHT), TITLE) {
m_window.setVerticalSyncEnabled(true);
TextureHolder texture_holder;
texture_holder.load(Textures::ID::Airplane, "/home/davit/CLionProjects/untitled/plane-animated-top-down-game-art.png");
m_spritePlane.setTexture(texture_holder.get(Textures::ID::Airplane));
}
void Game::run() {
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
const auto TimePerFrame = sf::seconds(1.f / 60.f);
while (m_window.isOpen()) {
const sf::Time elapsedTime = clock.restart();
timeSinceLastUpdate += elapsedTime;
while (timeSinceLastUpdate > TimePerFrame) {
timeSinceLastUpdate -= TimePerFrame;
processEvents();
update(TimePerFrame);
}
render();
}
}
void Game::processEvents() {
sf::Event event;
while (m_window.pollEvent(event)) {
switch (event.type) {
case sf::Event::KeyPressed:
handlePlayerInput(event.key.code, true);
break;
case sf::Event::KeyReleased:
handlePlayerInput(event.key.code, false);
break;
case (sf::Event::Closed):
m_window.close();
break;
}
}
}
void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed) {
if (key == sf::Keyboard::W)
m_isMoving[Up] = isPressed;
else if (key == sf::Keyboard::S)
m_isMoving[Down] = isPressed;
else if (key == sf::Keyboard::A)
m_isMoving[Left] = isPressed;
else if (key == sf::Keyboard::D)
m_isMoving[Right] = isPressed;
}
void Game::update(const sf::Time deltaTime) {
sf::Vector2f movement(0.f, 0.f);
if (m_isMoving[Up])
movement.y -= PLAYER_SPEED;
if (m_isMoving[Down])
movement.y += PLAYER_SPEED;
if (m_isMoving[Left])
movement.x -= PLAYER_SPEED;
if (m_isMoving[Right])
movement.x += PLAYER_SPEED;
m_spritePlane.move(movement * deltaTime.asSeconds());
}
void Game::render() {
m_window.clear();
m_window.draw(m_spritePlane);
m_window.display();
}
这里的问题与您上次发布此代码时的问题相同。
来自 sf::Sprite::setTexture 的 SFML 文档。
纹理参数指的是只要存在就必须存在的纹理 精灵使用它。
这对于您的代码来说并非如此,这就是为什么您会得到一个白色矩形。
Game::Game() : m_window(sf::VideoMode(WIDTH, HEIGHT), TITLE) {
m_window.setVerticalSyncEnabled(true);
TextureHolder texture_holder;
texture_holder.load(Textures::ID::Airplane, "/home/davit/CLionProjects/untitled/plane-animated-top-down-game-art.png");
m_spritePlane.setTexture(texture_holder.get(Textures::ID::Airplane));
}
texture_holder
变量被销毁,Game
构造函数的末尾和其中的所有纹理也同时被销毁。您必须将纹理保留移出游戏构造函数。例如将其放在 Game 类中