There are multiple ways to achieve such a thing and it largely depends on the structure you chose for your 'engine'.
One way would be to assume that every class than can get displayed are derived from sf::Drawable. Thus the class that is responsible to 'manage' those drawables could simply hold a std::vector of std::unique_ptr to all your drawables.
Here's some quickly cooked code which defines just two drawable classes and one application class. Everything should of course get extended and properly declared & defined in header and source files, etc...
Be warned the code uses some C++11 features which aren't supported by all compilers, specially not MSVC.
#include <SFML/Graphics.hpp> // sf::Drawable, sf::RenderTarget, sf::RenderStates, sf::Sprite, sf::CircleShape, sf::RenderWindow, sf::Event
#include <vector> // std::vector
#include <memory> // std::unique_ptr
class Player : public sf::Drawable
{
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
target.draw(m_sprite, states);
}
private:
sf::Sprite m_sprite;
};
class Ball : public sf::Drawable
{
private:
void draw(sf::RenderTarget& target, RenderStates states) const
{
target.draw(m_circle, states);
}
private:
sf::CircleShape m_circle;
};
class App
{
public:
App()
{
m_drawables.push_back(std::make_unique(Ball));
m_drawables.push_back(std::make_unique(Player));
}
void run()
{
sf::Event event;
while(m_window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
m_window.close;
}
m_window.clear();
for(auto it = m_drawables.begin(); it != m_drawables.end(); it++)
m_window.draw(*(*it));
m_window.draw();
}
private:
sf::RenderWindow m_window;
std::vector<std::unique_ptr<sf::Drawable>> m_drawables;
};
int main()
{
App app;
app.run();
}
Obviously it's all untested, but it should demonstrate
one possible principle.
There are many other ways and all have their ups and downs...