我正在开发一个自定义项目来学习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)',屏幕上没有任何反应。我假设问题是我想从子类调用继承的父函数,但我不知道如何解决这个问题。 我希望这对可能的坏语法是可以理解和抱歉的,但正如我在上面提到的那样,我不是母语人士。任何帮助将非常感谢!
提前致谢!
答案 0 :(得分:1)
您有两个类型为sf::Text
的不同对象:
stuff
stuff
的数据成员名为aim
调用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);
}
或者您可以重载setFillColor
和getFillColor
成员函数:
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
班级的字段:
sf::Vector2i mouse;
object& aim;
,字段定位为reference
object
类型,其中object
是您的模板参数因此,您的变量stuff
包含sf::Text
对象将保留的所有数据,因为内容为sf::Text
,sf::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>