Hey,
Well the problem is that I need polymorphism. I have an array of sf::Drawables (sf::Text and sf::Sprite) and I'm trying to implement model/view so when the x of my model/view changes I would like all sf::Drawables to change their positions. The code below illustrates better what I'm trying to say:
#include <list>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
class View{
private:
// The views coordinates
int _x, _y;
// A list of drawable stuff
std::list<const sf::Drawable*> _drawables;
protected:
// Adds a drawable instance to the list
// Pre:
// The instance given must exist at least as long as the
// current instance exists.
// Post:
// The container of drawables now holds a reference to the given
// sf::Drawable instnace. Any changes to it will be reflected
// in the list since it refers to the same object.
void _addDrawable(const sf::Drawable& drawable){
_drawables.push_back(&drawable);
}
// Clears the list of drawables.
// Post:
// The container of references to drawable instances is cleared.
void _clearDrawables(){
_drawables.clear();
}
public:
View(): _x(0), _y(0), _drawables(std::list<const sf::Drawable*>()){
}
View(int x, int y): _x(x), _y(y), _drawables(std::list<const sf::Drawable*>()){
}
View(const View& view): _x(view._x), _y(view._y), _drawables(std::list<const sf::Drawable*>()){
}
virtual ~View(){
}
virtual void update() = 0;
virtual const View& operator =(const View& view) throw(std::bad_cast){
const View& converted = dynamic_cast<const View&>(view);
_x = view._x;
_y = view._y;
return *this;
}
int getX() const {return _x;}
void setX(int x){
/* Here is what I want:
for (auto it = _drawables.begin(), end = _drawables.end(); it != end; it++){
const sf::Vector2f& position = (*it)->getPosition();
(*it)->setPosition(x + position.x - _x, position.y);
}
*/
_x = x;
}
int getY() const {return _y;}
void setY(int y){
/* Same for y
for (auto it = _drawables.begin(), end = _drawables.end(); it != end; it++){
const sf::Vector2f& position = (*it)->getPosition();
(*it)->setPosition(position.x, y + position.y - _y);
}
*/
_y = y;
}
const std::list<const sf::Drawable*>& getDrawables() const {return _drawables;}
};
class MyView : public View{
private:
sf::Font _myFont;
sf::Text* _myDrawable;
void _addDrawables(){
_addDrawable(*_myDrawable);
}
public:
MyView() throw(std::exception): _myFont(sf::Font()), _myDrawable(nullptr){
if (!_myFont.loadFromFile("font.ttf"))
throw std::exception("Could not load font");
_myDrawable = new sf::Text("MyText", _myFont);
_addDrawables();
}
MyView(const MyView& myView): _myFont(myView._myFont), _myDrawable(nullptr){
_myDrawable = new sf::Text(myView._myDrawable->getString(), _myFont);
_addDrawables();
}
virtual ~MyView(){
delete _myDrawable;
}
virtual void update(){
_myDrawable->setString("Updated");
}
virtual const MyView& operator =(const MyView& myView) throw(std::bad_cast){
const MyView& converted = dynamic_cast<const MyView&>(myView);
View::operator =(converted);
*_myDrawable = *converted._myDrawable;
_myDrawable->setFont(_myFont);
return *this;
}
};
int main(){
try{
MyView myView;
sf::RenderWindow window(sf::VideoMode(200, 200), "Drawables");
sf::Event event;
do{
window.clear();
const std::list<const sf::Drawable*>& drawables = myView.getDrawables();
for (auto it = drawables.begin(), end = drawables.end(); it != end; it++)
window.draw(**it);
window.display();
if (window.pollEvent(event))
if (event.type == sf::Event::Closed)
window.close();
else
if (event.type == sf::Event::KeyPressed)
myView.update();
}while(window.isOpen());
return EXIT_SUCCESS;
}
catch(...){
return EXIT_FAILURE;
}
}
sf::Transformable does not inherit sf::Drawable to be able to use it in this case. Can there be at least an intermediate class between sf::Drawable and sf::Text, sf::Sprite, sf::Shape? Let's say:
class Drawable2D : public Drawable, public Transformable{
};
And all classes that inherit Drawable and Transformable to derive from Drawable2D? If not I will need to use 2 containers, one of references to Drawables and one of references to Transformables.