SFML 2.1 "setFont"未处理的异常

SFML 2.1 "setFont" unhandled exception

本文关键字:异常 未处理 setFont SFML      更新时间:2023-10-16

所以我正在尝试使用 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) 方法中,然后尝试绘制返回的sf::Text

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

0x6177BA8C (sfml-graphics-d-2.dll) 中的未处理异常 游戏引擎.exe:0xC0000005:访问违规读取位置 0x0000000D。

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

我想知道是否有人确切知道这里发生了什么?我似乎找不到有关此特定问题的任何建议,并且我已经尝试(但失败了)遵循SFML文本和字体教程。

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

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

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

#include "Entity.h"
#include <string>
#include "SFMLGraphics.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;
}

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

按值传递和按引用/指针传递

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.你应该只保留 sf::Text 的向量或列表(任何你喜欢的容器),然后浏览该向量并调用this->window->draw(yourTextContainer.at(i));或类似的东西。

如果 sf::Font 是汽车磁力和 sf::Text 汽车轮胎,你的 FontEntity 就像试图把轮胎放在车轮上的轮胎上。

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