1

所以我正在尝试使用 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对象,将转换后的对象传递FontEntityCreateText(FontEntity)方法,然后尝试绘制sf::Text返回的对象。

但是,当out.setString(font.GetText());被调用时,我得到了异常:

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

另一方面,如果我删除该out.setFont(font.GetFont())行,则不会发生此错误。

我想知道是否有人确切地知道这里发生了什么?我似乎找不到关于这个特定问题的任何建议,我已经尝试(但失败了)遵循SFML Text and fonts tutorial

我的第一个想法是我遇到了某种狡猾的指针问题,但据我了解本教程,我正在尝试做的事情应该没问题。

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

.h 文件(如果有帮助)如下:

#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;
};

和 .cpp 文件:

#include "stdafx.h"
#include "FontEntity.h"


FontEntity::FontEntity(float x, float y, sf::Font font) : Entity(x, y)
{
    this->text = "";
    this->font = font;
}

FontEntity::FontEntity(float x, float y, sf::Font font, std::string text) : Entity(x, y)
{
    this->text = text;
    this->font = font;
}

FontEntity::~FontEntity(void)
{
}

std::string FontEntity::GetText(void)
{
    return this->text;
}

void FontEntity::SetText(std::string text)
{
    this->text = text;
}

sf::Font FontEntity::GetFont(void)
{
    return this->font;
}

void FontEntity::SetFont(sf::Font font)
{
    this->font = font;
}

int FontEntity::GetSize(void)
{
    return this->size;
}

void FontEntity::SetSize(int size)
{
    this->size = size;
}

谢谢阅读!非常感谢所有输入。

4

1 回答 1

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++ 中传递对象的经验法则

现在你的 FontEntity

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

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

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

于 2013-10-29T08:40:56.557 回答