SFML从模板派生类调用父函数

时间:2017-07-25 00:06:31

标签: c++ sfml

我正在开发一个自定义项目来学习SFML,但我遇到了问题。我想做一个'可点击'的课程,我可以添加一些花哨的功能,我的第一个目标是写一个'onMouseOver'功能,这个功能可能与Javascript几乎相同。这是班级:

template <class object>
class clickable: public object{
private:
    sf::Vector2i mouse;
    object& aim;
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
public:
    clickable(sf::Vector2i mouse,object& aim):mouse(mouse),aim(aim){}
    bool onMouseOver(sf::Vector2i mouse) {  
        float width = aim.getLocalBounds().width;
        float height = aim.getLocalBounds().height;
        if ((mouse.x >= aim.getPosition().x) && (mouse.x <= aim.getPosition().x + width) && (mouse.y >= aim.getPosition().y) && (mouse.y <= aim.getPosition().y + height))
            return true;
        else return false;
    }
};

这是我的主要内容:

    int main()
{
    sf::Font font;
    if (!font.loadFromFile("arial.ttf")) {
        std::cout << "Error!";
    }
    sf::RenderWindow window(sf::VideoMode(800, 600), "Title", sf::Style::Default);
    sf::Vector2i mouse = sf::Mouse::getPosition(window);
    vector<sf::Text> objects;
    objects.push_back(sf::Text("Test text.", font, 14));
    objects[0].setPosition(20, 20);
    clickable<sf::Text> stuff(mouse,objects[0]);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
            if (event.type == sf::Event::MouseMoved) {
                eger = sf::Mouse::getPosition(window);
            }
        }
        window.clear();
        window.draw(stuff);
        if (stuff.onMouseOver(mouse)) objects[0].setFillColor(sf::Color::Red);
        else objects[0].setFillColor(sf::Color::White);
        window.display();
    }
    return 0;}

我测试了这段代码(使用不同的变量名,因为我来自匈牙利)并且它有效。我的问题是,如果我想将'objects [0] .setFillColor(sf :: Color :: Red)'更改为'stuff.setFillColor(sf :: Color :: Red)',屏幕上没有任何反应。我假设问题是我想从子类调用继承的父函数,但我不知道如何解决这个问题。 我希望这对可能的坏语法是可以理解和抱歉的,但正如我在上面提到的那样,我不是母语人士。任何帮助将非常感谢!

提前致谢!

3 个答案:

答案 0 :(得分:1)

您有两个类型为sf::Text的不同对象:

  1. stuff
  2. stuff的数据成员名为aim
  3. 调用setFillColor的{​​{1}}方法会设置stuff的填充色,而不是stuff。但是aim的{​​{1}}方法完全依赖于draw的绘制方法:

    stuff

    aim不知道virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); } 的填充色,因此aim将完全像以前一样。

    解决方案是重新设计stuff课程,这取决于您的意图。为什么要继承模板类并拥有该类类型的数据成员?

    现在最简单的做法可能是重新实现window.draw(stuff) clickable方法作为setFillColor的新方法:

    sf::Text

答案 1 :(得分:1)

我可以快速,轻松地快速解决您的问题。只需在您的可点击类的draw成员函数中添加此行代码,然后再调用target.draw(aim, states);

aim.setFillColor(this->getFillColor());
像这样:

virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
    aim.setFillColor(this->getFillColor());
    target.draw(aim, states);
}

或者您可以重载setFillColorgetFillColor成员函数:

void setFillColor(const sf::Color& c) {
    aim.setFillColor(c);
}

const sf::Color& getFillColor() {
    return aim.getFillColor();
}

解释:

您声明了一个变量stuff,如下所示:clickable<sf::Text> stuff(mouse, objects[0]);

根据您的模板类定义,这意味着东西是从clickable继承的sf::Text,因此它是clickable sf::Text,它也是sf::Text }。

查看clickable班级的字段:

  • a sf::Vector2i mouse;
  • 一个object& aim;,字段定位为reference object类型,其中object是您的模板参数

因此,您的变量stuff包含sf::Text对象将保留的所有数据,因为内容为sf::Textsf::Vector2i和对{的引用{1}}对象,这不是他自己。所以在这里,你的stuff对象可以访问2个不同的sf::Text对象。他自己和目标所引用的那个。

sf::Text成员函数代码显示它绘制了字段draw,因此引用了aim,而不是自己持有的数据

当您在代码中执行

sf::Text

您在stuff对象的objects[0].setFillColor( sf::Color::Red ); 字段引用的对象上调用setFillColor方法,而那样:

aim

更改stuff.setFillColor(sf::Color::Red); 对象本身。你的绘图函数将通过stuff对象绘制对象引用,但不知道应用于stuff对象的所有修改

所以解决方案很简单:应用于stuff对象的所有修改都需要应用于引用的对象

当您想要绘制对象时(在绘制方法中)或要求应用修改时(例如,当您调用setFillColor方法时),可以这样做。

顺便说一句,亚历克斯是对的,因为你的班级设计不是很好。你也不能保持对sf :: Text对象的引用并为(* this)调用sf :: Text draw方法(或者只是不要重载可点击对象中的draw方法并对sf :: Text进行适当的复制)在你的对象中)

答案 2 :(得分:0)

谢谢你们两位,现在我明白了!两种解释都很好。我重新设计了这个课程,因为以下被困的程序员在这里是我的解决方案:

template <class object>
class clickable: public object{
public:
    clickable(const string& s, const sf::Font& f, unsigned int size) : object::Text(s, f, size) {}

    void cmd_out() {
        cout << (string) (*this).getString();
    }
    void graph_out(float x = 0, float y = 0) {
    }
    bool onMouseOver(const sf::Vector2i& eger) {    
        float width = (*this).getLocalBounds().width;
        float height = (*this).getLocalBounds().height;
        if ((eger.x >= (*this).getPosition().x) && (eger.x <= (*this).getPosition().x + width) && (eger.y >= (*this).getPosition().y) && (eger.y <= (*this).getPosition().y + height))
            return true;
        else return false;
    }
};

现在它正在工作,但是我只能使用这个sf :: Text可点击对象,但是如果我需要任何其他对象,那么根据需要添加另一个构造函数会很容易。< / p>