SFML 2.1“setFont”未处理的异常

时间:2013-10-24 02:12:31

标签: c++ sfml

所以我正在尝试使用SFML中的.setFont(sf::Font)方法,它似乎以某种方式打破了sf::Text对象的其余部分。我正在使用以下函数执行此操作:

sf::Text Renderer::CreateText(FontEntity font)
{
    sf::Text out;

    out.setFont(font.GetFont());
    out.setString(font.GetText());
    out.setCharacterSize(24);
    out.setColor(sf::Color::White);
    out.setStyle(sf::Text::Bold);

    return out;
}

上面用于我已经实现的绘制调用,并且我认为问题可能在哪里(虽然我不确定在哪里):

void Renderer::Draw(DrawData* drawData)
{
    this->window->clear();

    for (Entity* entity: drawData->GetEntities())
    {
        auto fontEntity = static_cast<FontEntity*>(entity);

        // If font entity
        if (fontEntity)
        {
            sf::Text text = CreateText(*fontEntity);
            this->window->draw(text);
        }
    }

    this->window->display();
}

循环遍历Entity个对象列表,将它们转换为FontEntity个对象,将转换后的FontEntity传递给CreateText(FontEntity)方法,然后尝试绘制{ {1}}返回。

然而,当调用sf::Text时,我得到例外:

  

0x6177BA8C(sfml-graphics-d-2.dll)中的未处理异常   GameEngine.exe:0xC0000005:访问冲突读取位置   0x0000000D。

另一方面,如果删除out.setString(font.GetText());行,则不会发生此错误。

我想知道是否有人确切知道这里发生了什么?我似乎无法就这个具体问题找到任何建议,我已经尝试(并且失败)关注SFML Text and fonts tutorial

我的第一个想法是,我有一些狡猾的指针问题正在进行,但据我理解教程,我正在尝试做的应该没问题。

out.setFont(font.GetFont())类是一个自定义类,我用它来管理有效的可绘制字符串,但可以很好地存储在我的FontEntity对象列表中。

.h文件,如果有帮助,如下:

Entity

.cpp文件:

#include "Entity.h"
#include <string>
#include "SFML\Graphics.hpp"

class FontEntity : public Entity
{
public:
    FontEntity(float x, float y, sf::Font font);
    FontEntity(float x, float y, sf::Font font, std::string text);
    ~FontEntity(void);

    std::string GetText(void);
    void SetText(std::string);

    sf::Font GetFont(void);
    void SetFont(sf::Font);

    int GetSize(void);
    void SetSize(int);

protected:
    std::string text;
    sf::Font font;
    int size;
};

感谢阅读!所有输入都完全受到赞赏。

1 个答案:

答案 0 :(得分:1)

按值传递并通过引用/指针传递

sf::Font是重物,永远不会按值传递它们,总是像参考一样:

class FontEntity : public Entity
{
public:
    FontEntity(float x, float y, sf::Font* font);
    FontEntity(float x, float y, sf::Font* font, std::string text);
    ~FontEntity(void);

    // every member function that do not modify the object
    // should be const.
    std::string GetText(void) const;

    // most of the time, it's more efficient to pass-by-reference
    // except for base type (int, char, etc.)
    // std::string are not that big, so it's not really inefficient to
    // pass them by value
    void SetText(const std::string&);

    // you don't want the rest of the code messing with the font
    // parameter since it will affect every object that is using it.
    const sf::Font *GetFont(void) const;
    void SetFont(sf::Font*);

    int GetSize(void) const;
    void SetSize(int);

protected:
    std::string text;
    sf::Font* font; // keep a pointer to the sf::font
    int size;
};

另一方面,sf::Text是非常轻量级的对象,旨在被复制并传递到任何地方。

正如@ Pawnguy7评论的那样,错误来自于您通过值传递sf::Font。这与您使用C ++的方式有关,而与SFML的工作方式无关。有关在C ++中传递对象的信息,请参阅Rules of thumb

现在你的FontEntity

另一件事是,我真的不明白为什么你有FontEntity。你应该只保留sf :: Text的向量或列表(你喜欢的任何容器),然后只需通过那个向量并调用this->window->draw(yourTextContainer.at(i));或类似的东西。

如果sf :: Font是汽车杂志和sf :: Text汽车轮胎,那么你的FontEntity就像是试图将轮胎放在轮胎上的轮胎上。

另外,为什么要将FontEntity对象保存在Entity容器中?铸造是一项昂贵的操作,如果可能的话,应该不惜一切代价避免设计。另一个昂贵的操作是为每个框架创建每个FontEntity的文本,你应该做的是创建它们一次并在渲染后存储它们。