Sinon, je ne comprends pas pourquoi on devrait éviter d'utiliser des pointeurs sur void*, car, je trouve ceci beaucoup plus pratique que d'utiliser un any.get<Type>() :
#ifndef APPLICATION
#define APPLICATION
#include "stateManager.h"
#include "resourceManager.h"
namespace sfgl {
class Application {
public :
Application(sf::RenderWindow &window) : window(window) {
app = this;
}
template <typename R> void addResourceManager (ResourceManager<R>& rmi, std::string name);
template <typename R> ResourceManager<R>& resourceManager(std::string name);
virtual void load () = 0;
virtual void render () = 0;
sf::RenderWindow& getWindow() {
return window;
}
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::make_pair(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;
}
StateManager& getStateManager() {
return stm;
}
static Application *app;
private :
StateManager stm;
sf::RenderWindow &window;
std::map<std::string, sf::Clock> clocks;
std::map<std::string, ResourceManager<void*>&> resourceManagers;
};
template <typename R>
void Application::addResourceManager(ResourceManager<R>& rmi, std::string name) {
std::map<std::string, ResourceManager<void*>&>::iterator it = resourceManagers.find(name);
if (it != resourceManagers.end())
throw Erreur (11, "Resource manager already added!", 0);
resourceManagers.insert(std::make_pair(name, rmi));
}
template <typename R>
ResourceManager<R>& Application::resourceManager(std::string name) {
typename std::map<std::string, ResourceManager<void*>&>::iterator it = resourceManagers.find(name);
if (it == resourceManagers.end())
throw Erreur (12, "Resource manager not found!", 0);
return reinterpret_cast<ResourceManager<R>&>(it->second);
}
Application* Application::app = nullptr;
}
#endif // APPLICATION
Ce qui me donne au final comme code :
#ifndef MY_APPLI
#define MY_APPLI
#include "SFGL/Core/application.h"
#include <SFML/Graphics.hpp>
#include "SFGL/Graphics/2D/tile.h"
using namespace sfgl;
using namespace sf;
class MyAppli : public Application {
public :
MyAppli(sf::RenderWindow &window) : Application (window) {
TextureManager tm;
addResourceManager<Texture>(tm, "TextureManager");
}
void load() {
TextureManager &tm = resourceManager<Texture>("TextureManager");
tm.load("tilesets/herbe.png", "HERBE");
}
void render() {
TextureManager &tm = resourceManager<Texture>("TextureManager");
Tile *t = new Tile(tm.getResourceByAlias("HERBE"), Vec2f(0, 0), Vec2f(100, 50),IntRect(0, 0, 100, 50), 0);
while (getWindow().isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (getWindow().pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
getWindow().close();
}
// clear the window with black color
getWindow().clear(sf::Color::Black);
// draw everything here...
getWindow().draw(*t);
// end the current frame
getWindow().display();
}
delete t;
tm.deleteResourceByAlias("HERBE");
}
~MyAppli() {
}
};
#endif // MY_APPLI
#include <vector>
#include <iostream>
#include <SFML/Graphics.hpp>
#include "myApplication.h"
using namespace sf;
int main () {
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
MyAppli app(window);
app.load();
app.render();
}
C'est déjà plus court comme main.
Bref, je suis presque arrivé à terme il ne me reste plus que les classes Cursor, Player, Icon et sfgl::renderWindow à implémenter.
Et ensuite je commencer les tutoriels.
Pour les tutoriels je pense que je vais faire un système de génération de monde aléatoire se sera le plus simple.
Le développeur pourra rendre différents states (les states décriront les états du jeux à un moment donné (menus, monde, ressources à charger, options du jeux, etc...)), on pourra basculer d'un state à l'autre via le statemanager de la classe application.
Ceci permettra de revenir à un menu du jeux par exemple sans devoir tout recharger à la main.
Il faudra hériter et redéfinir certains méthode dans les classes states et application car celles-ci sont abstraites :
States :
reload : rechargement des textures du state. (des menus par exemple)
init : recréation des guis des menus par exemple.
draw : affichage du monde en fonction des options de rendu, des menus correspondant à l'état du jeux, etc...
update : mise à jour de l'état des states en fonction du temps.
Application :
load : chargement des ressources de départ.
init : création du monde.
render : rendu du monde.
update : c'est là dedans que le développeur mettra à jour les states et autres objets du framework en fonction des évènements d'entrée.
Voilà je pense que ça ira comme ça au niveau architecture.