SFML-спрайт представляет собой белый квадрат при создании нескольких текстур

Я создаю фреймворк SFML, и когда я использую функцию loadImage один раз, изображение загружается правильно со всеми цветами, но если я использую его два раза для другой текстуры, визуализируется только один спрайт, и он весь белый. Я читал, что вы не хотите удалять текстуру или спрайт, иначе он будет белым. Но в этом коде я храню все текстуры в векторе. Кто-нибудь знает, что не так в этой функции?

FM::Image FM::graphics::loadImage(const char* fileName) {

        texturesindex++;
        sf::Texture texture;
        texture.loadFromFile(fileName);
        textures.push_back(texture);
        sf::Sprite sprite(textures[texturesindex]);
        Image image;
        image.sprite = sprite;
        return image;
}

Вот весь код:

SFFM.cpp:

    #include "SFFM.h"
    #include <SFML/Graphics.hpp>
    #include <vector>
    #include <string>

    int backgroundcolor[3] = { 0,0,0};
    sf::RenderWindow Window(sf::VideoMode(800, 600), "MyGame");
    std::vector<sf::Texture> textures;
    int texturesindex = -1;

    void FM::window::setWindowOptions(unsigned int Width, unsigned int Height, const char* Title, int FrameLimit) {

        Window.setSize(sf::Vector2u(Width, Height));
        Window.setFramerateLimit(FrameLimit);
        Window.setTitle(Title);
    }

    void FM::window::setBackgroundColor(int r, int g, int b) {

        backgroundcolor[0] = r;
        backgroundcolor[1] = g;
        backgroundcolor[2] = b;
    }

    FM::Image FM::graphics::loadImage(const char* fileName) {

        texturesindex++;
        sf::Texture texture;
        texture.loadFromFile(fileName);
        textures.push_back(texture);
        sf::Sprite sprite(textures[texturesindex]);
        Image image;
        image.sprite = sprite;
        return image;
    }

    void FM::graphics::drawImage(Image image, int x, int y, int scalex, int scaley, int rotation) {

        image.sprite.setPosition(x, -y);
        image.sprite.setRotation(rotation);
        image.sprite.setScale(sf::Vector2f(scalex, scaley));
        Window.draw(image.sprite);
    }

    void FM::graphics::drawImage(Image image, int x, int y, int scalex, int scaley) {

        image.sprite.setPosition(x, -y);
        image.sprite.setScale(sf::Vector2f(scalex, scaley));
        Window.draw(image.sprite);
    }

    void FM::graphics::drawImage(Image image, int x, int y) {

        image.sprite.setPosition(x, -y);
        Window.draw(image.sprite);
    }

    int main()
    {   
        FM::Start();

        while (Window.isOpen())
        {
            sf::Event event;

            while (Window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    Window.close();
                else if (event.type == sf::Event::Resized)
                {
                    Window.setView(sf::View(sf::FloatRect(0, 0, event.size.width, event.size.height)));
                }
            }

            Window.clear(sf::Color(backgroundcolor[0], backgroundcolor[1], backgroundcolor[2]));
            FM::Update();
            Window.display();
        }

        return 0;
    }

SFFM.h:

#pragma once
#include <SFML/Graphics.hpp>

namespace FM
{

void Update();

void Start();



class window {

public:

    static void setWindowOptions(unsigned int Width, unsigned int Height, const char * Title, int FrameLimit);

    static void setBackgroundColor(int r, int g, int b);
};

class Image {

public:
    sf::Sprite sprite;
};

class graphics {

public:

    static Image loadImage(const char* fileName);
    static void drawImage(Image image, int x, int y, int scalex, int scaley, int rotation);
    static void drawImage(Image image, int x, int y, int scalex, int scaley);
    static void drawImage(Image image, int x, int y);
};

class Input {

public:

};
};

main.cpp:

#include "SFFM.h"
#include <SFML\Graphics.hpp>
FM::Image Gangster;
FM::Image Block;
int x = 0;
int y = 0;

void FM::Start() {

window::setWindowOptions(1280, 720, "Platformer", 120);
window::setBackgroundColor(0, 127, 255); 
Gangster = graphics::loadImage("assets/Gangster.png");
}

void FM::Update() {

graphics::drawImage(Gangster, x, y, 5, 5);
graphics::drawImage(Block, 100, 100, 5, 5);

if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {

    y += 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {

    y -= 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {

    x += 1;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {

    x -= 1;
}

}

Вот скриншот:

SFML-спрайт представляет собой белый квадрат при создании нескольких текстур

Почему main нет в main.cpp?

Benjamin James Drury 17.03.2018 16:45

Поскольку я хотел упростить ситуацию, я сделал две функции start и update, которые вызываются в основной функции в SFFM.cpp, так что мне не нужно видеть весь беспорядок в основной функции.

BlockySteve 17.03.2018 20:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
2
547
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

TL; DR Solutions, либо:

  • Используйте контейнер, отличный от std::vector<sf::Texture> - std::list<sf::Texture> или std::forward_list<sf::Texture>.
  • Хранить указатели на текстуры - std::vector<std::unique_ptr<sf::Texture>>.

Объяснение

Вы храните объекты текстуры вместе со ссылками на них. Это правильно, потому что злоба просто сохраняет ссылку (указатель) на свою текстуру. Это также означает, что адрес текстуры должен оставаться неизменным в течение всего времени жизни спрайта.

Похоже, вы не учли, как работает std :: vector push_back (). Вектор изначально выделяет некоторую память, и когда нет места для вставки нового элемента, вектор выделяет больше памяти и копирует туда все вставленные элементы и новый. Таким образом, все адреса пунктов меняются.

В вашем случае элемент является текстурой, его адрес изменяется при использовании другой текстуры, поэтому некоторый спрайт «теряет» свою текстуру. Обычно это приводит к рисованию белых квадратов.

Благодарю за ответ. Но тогда как мне добавить указатель на вектор. С отталкиванием?

BlockySteve 22.03.2018 18:32

@BlockySteve textures.emplace_back (new sf :: Texture (texture)), если вы используете C++ 11, textures.push_back (std :: make_unique <sf :: Texture> (texture)), если вы используете C++ 14 . Или лучше использовать первую альтернативу, в вашем случае достаточно заменить «вектор» на «список».

Dmitry T. 28.03.2018 12:06

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