Белый квадрат вместо реального изображения

Недавно я начал изучать 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;
}

Game.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;
};

Game.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();
}

См. документацию SFML по адресу Проблема белого квадрата — там довольно хорошо объяснено, в чем проблема и как ее исправить.

Jesper Juhl 06.07.2024 02:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема здесь та же, что и в прошлый раз, когда вы публиковали этот код.

Из документации SFML для sf::Sprite::setTexture.

Аргумент текстуры относится к текстуре, которая должна существовать до тех пор, пока спрайт использует его.

Это неверно для вашего кода, поэтому вы получаете белый прямоугольник.

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));
} // *** all textures are destroyed here ***

Переменная texture_holder уничтожается в конце конструктора Game, и все текстуры в ней уничтожаются одновременно. Вам необходимо переместить держатель текстуры из конструктора Game. Поместите это, например, в класс Game.

Так

class Game {
    ...
    TextureHolder     m_texture_holder; // <==== HERE
    sf::RenderWindow  m_window;
    sf::Texture       m_texturePlane;
    sf::Sprite        m_spritePlane;

Поместив держатель текстуры в класс Game, вы гарантируете, что все текстуры будут существовать до тех пор, пока существует объект Game.

Другие вопросы по теме

Похожие вопросы

Есть ли способ упростить дробь, включая десятичные?
Может ли кто-нибудь сказать мне, как я могу создать несколько объектов, используя вектор, не указывая длину вектора?
Valgrind жалуется после изменения возвращаемой переменной ссылки из вектора в С++
Хорошо ли определено приведение к идентичному макету с константными членами?
Обработчик sigaction ожидает блокировки неопределенное время
Функция constexpr шаблона базового класса в производном классе и получила ошибку
Обход Морриса приводит к исключению в LeetCode: очиститель адресов, переполнение стека
Достаточно ли времени жизни локальной лямбды в качестве обработчика завершения для co_spawn, т.е. функции с functor&&?
Как преобразовать лямбда-функцию в другую, используя кортеж параметров
Если по умолчанию объявлен только виртуальный деструктор, создается ли неявно конструктор копирования?