Yeah I know but it'll take time because I have computers which support functionnalities than other doesn't support. (By example my oldest computer don't support FBO and shaders)
So I need to have very specific classes for each supported functionnalities. (It's not always the case with actual frameworks or libraries) :
-JOGL doesn't work on my PC if I use swing and some javaclass which lead to concurrent thread exceptions. (Same for each framework using JOGL)
-QtSockets doesn't work on my plateform.
-Unity, Irrlicht and other c++ framework doesn't use SFML, so, I'm forced to use their entity system and I don't really need them for simple 2D games. (I prefer don't use GLSL if my Pc doesn't support shaders and fbo and use ASM shaders by example, but I'll not make that here because I very suck in ASM, but in case of someone want to do it...)
So I've a class called "World" which use different EntityManagers type depending on which functionnalities are supported. (So I can use shaders or not, if the PC support shaders, the effects'll just be more beautifull.)
Here is an example (I use the crtp pattern)
#ifndef WORLD_H
#define WORLD_H
#include <SFML/Graphics.hpp>
#include "../Graphics/3D/view.h"
#include "../Graphics/2D/entityManager.h"
#include "../Graphics/3D/entityManager.h"
namespace odfaeg {
class EntitiesUpdater;
class AnimUpdater;
class World {
public :
static void createEntityManager (sf::View &view, std::string name, int cellWidth, int cellHeight, int cellDepth);
static void createEntityManager (g3d::View &view, std::string name, int cellWidth, int cellHeight, int cellDepth = 1);
static void removeEntityManager(std::string mapName);
static void setCurrentEntityManager(std::string name);
static void update();
static void checkVisibleEntities();
template <typename E>
static std::vector<E*> getVisibleEntities (std::string expression);
template <typename E>
static bool containsMovableVisibleEntity(E *ae) {
if (!ae->isMovable())
return false;
if (currentEntityManager->isG2DEntity())
static_cast<g2d::EntityManager*>(currentEntityManager)->containsMovableVisibleEntity(ae);
else
static_cast<g3d::EntityManager*>(currentEntityManager)->containsMovableVisibleEntity(ae);
}
template <typename E>
static void removeVisibleEntity(E* entity);
template <typename E>
static void insertVisibleEntity(E* entity);
virtual ~World();
private :
static std::vector<EntitiesUpdater*> eus;
static std::vector<AnimUpdater*> aus;
static std::vector<EntityManagerHolder*> ems;
static EntityManagerHolder* currentEntityManager;
};
}
#endif
g3d::EntityManager use a shader but g2d::EntityManager doesn't use a shader.
I'll put some items into the class Application (the command system, the view, etc...) and the developper'll just have to inherits from this class, redefining some methods to render, build and update the world.
#ifndef APPLICATION
#define APPLICATION
#include <SFML/Graphics.hpp>
#include "resourceCache.h"
#include "../Graphics/3D/renderWindow.h"
#include "../Graphics/3D/renderStates.h"
#include "system.h"
#include "../Graphics/3D/tileMap.h"
namespace odfaeg {
class Application {
public :
Application(sf::VideoMode vm, std::string title, bool g2dAppli, sf::Uint32 style = sf::Style::Default, sf::ContextSettings settings = sf::ContextSettings()) {
if (g2dAppli) {
if (sf::Shader::isAvailable()) {
ODFAEGWindow = new g3d::RenderWindow(vm, title, style, settings);
g3d::View& view = ODFAEGWindow->getView();
view.setUpVector(Vec3f(0, -1, 0));
view.scale(-1, 1, 1);
view.move(-ODFAEGWindow->getSize().x * 0.5f, -ODFAEGWindow->getSize().y * 0.5f, 0);
} else {
SFMLWindow = new sf::RenderWindow(vm, title, style, settings);
}
} else {
if (sf::Shader::isAvailable()) {
ODFAEGWindow = new g3d::RenderWindow(vm, title, style, settings);
} else {
ODFAEGWindow = new g3d::RenderWindow(vm, title, style, settings, true);
}
}
clearColor = sf::Color(0, 0, 0);
app = this;
running = false;
}
void move(float x, float y, float z = 0) {
if (ODFAEGWindow != nullptr)
ODFAEGWindow->getView().move(x, y, z);
else
SFMLWindow->getView().move(x, y);
}
int exec() {
load();
running = true;
while (running) {
render();
update();
}
return EXIT_SUCCESS;
}
void stop() {
running = false;
if(SFMLWindow != nullptr)
SFMLWindow->close();
else
ODFAEGWindow->close();
}
void load() {
if (SFMLWindow != nullptr)
g3d::TileMap::genBuffers(SFMLWindow->getSize().x, SFMLWindow->getSize().y);
else
g3d::TileMap::genBuffers(ODFAEGWindow->getSize().x, ODFAEGWindow->getSize().y);
onLoad();
onInit();
running = true;
}
virtual void onInit() {}
void render() {
g3d::TileMap::clearBufferBits(sf::Color(0, 0, 0));
g3d::TileMap::clearDepthBits();
if (SFMLWindow != nullptr) {
SFMLWindow->clear(clearColor);
} else {
ODFAEGWindow->clear(clearColor);
}
onRender();
if (SFMLWindow != nullptr) {
SFMLWindow->display();
} else {
ODFAEGWindow->display();
}
}
void update() {
sf::Event event;
if (SFMLWindow != nullptr) {
if (SFMLWindow->pollEvent(event)) {
onUpdate(event);
}
} else {
if (ODFAEGWindow->pollEvent(event)) {
onUpdate(event);
}
}
listener.pushEvent(event);
}
void draw(sf::Drawable& drawable, sf::RenderStates states = sf::RenderStates::Default) {
if (SFMLWindow != nullptr)
SFMLWindow->draw(drawable, states);
}
void draw(g3d::Drawable& drawable, g3d::RenderStates states = g3d::RenderStates::Default) {
if (ODFAEGWindow != nullptr) {
ODFAEGWindow->draw(drawable, states);
}
}
virtual void onLoad (){}
virtual void onRender (){}
virtual void onUpdate (sf::Event &event) {}
void addClock(sf::Clock clock, std::string name) {
//std::map<std::string, sf::Clock>::iterator it = clocks.find(name);
/*if (it != clocks.end())
throw Erreur (13, "This clock already exist!", 0);*/
clocks.insert(std::pair<std::string, sf::Clock>(name, clock));
}
sf::Clock getClock(std::string name) {
std::map<std::string, sf::Clock>::iterator it = clocks.find(name);
if (it == clocks.end())
throw Erreur (14, "Clock not found!", 0);
return it->second;
}
ResourceCache& getCache() {
return cache;
}
void setClearColor(sf::Color clearColor) {
this->clearColor = clearColor;
}
static bool isG2dAppli() {
return g2dAppli;
}
static Application* app;
private :
sf::RenderWindow *SFMLWindow;
g3d::RenderWindow *ODFAEGWindow;
std::map<std::string, sf::Clock> clocks;
Listener listener;
ResourceCache cache;
static bool g2dAppli;
bool running;
sf::Color clearColor;
};
}
#endif // APPLICATION
The sf::Event'll be passed at the derived application, the developper'll be able so to retrieve event's informations and the application'll pass each sf::Event to the listener which'll execute each actions.