diff --git a/include/Game.h b/include/Game.h index 1edbada..c1b1aa3 100644 --- a/include/Game.h +++ b/include/Game.h @@ -1,76 +1,18 @@ #pragma once -#include -#include -#include -#include -#include +class GameInternal; -#include "Manager.h" -#include "Vector2D.h" -#include "Entity.h" - -typedef std::function gamefunction; - -class AssetManager; -class CollisionHandler; -class TextureManager; -class SoundManager; -class Map; - -namespace engine { - extern gamefunction init; - extern gamefunction update; - - extern Game* game; // this is a temporary fix to remove artifacts of chicken_game from the engine while the API is not yet finalized -} - -class Game -{ +// TODO: add managers here +class Game { public: - Game(); - ~Game(); + virtual ~Game() {} - void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen); - void selectCharacters(const char* &playerSprite, const char* &enemySprite); + virtual void init() = 0; + virtual void update() = 0; - void handleEvents(); - void update(); - void render(); - void clean(); - bool running() const; - - /* static */ SDL_Renderer* renderer = nullptr; - /* static */ SDL_Event event; - /* static */ CollisionHandler* collisionHandler; - /* static */ AssetManager* assets; - /* static */ TextureManager* textureManager; - /* static */ SoundManager* soundManager; - - // moved globals - Manager manager; - Map* map; // game specific, might not be needed for all types of games - - Entity& player1; - Entity& player2; - - Entity& wall; - - std::vector& tiles; - std::vector& players; - std::vector& projectiles; - std::vector& hearts; - std::vector& powerups; - // end moved globals - - void refreshPlayers(); - Entity::TeamLabel getWinner() const; - void setWinner(Entity::TeamLabel winningTeam); - -private: - - int counter = 0; - bool isRunning = false; - SDL_Window* window; - Entity::TeamLabel winner; + GameInternal* gameInternal; //!< \deprecated }; + + +// game factory include to simplify imports in implementation +#include "GameFactory.h" \ No newline at end of file diff --git a/include/GameFactory.h b/include/GameFactory.h new file mode 100644 index 0000000..443a2d6 --- /dev/null +++ b/include/GameFactory.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "Game.h" + +class GameInternal; + +class GameFactory { +public: + using CreateFunc = std::function; + + static GameFactory& instance() { + static GameFactory factory; + return factory; + } + + /*Game* get() { + assert(this->gameInstance != nullptr); + return this->gameInstance; + }*/ + + /*Game* create(GameInternal* gameInternal) { + Game* game = this->gameInstance == nullptr ? this->creator() : this->gameInstance; // TODO: error handling + game->gameInternal = gameInternal; + this->gameInstance = game; + return game; + }*/ + + void registerClass(const std::string& className, CreateFunc createFunc) { + this->creators[className] = createFunc; + } + + Game* create(const std::string& className, GameInternal* gameInternal) { + auto it = this->creators.find(className); + if (it != creators.end()) { + Game* game = it->second(); + game->gameInternal = gameInternal; + return game; + } + return nullptr; + } + +private: + CreateFunc creator; + std::map creators; +}; + +/* +#define REGISTER_GAME(className) \ + static bool registered_##className = []() { \ + GameFactory::instance().registerClass(#className, []() -> Game* { return new className; }); \ + return true; \ + }(); +*/ diff --git a/include/GameInternal.h b/include/GameInternal.h new file mode 100644 index 0000000..8cd806c --- /dev/null +++ b/include/GameInternal.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "Manager.h" +#include "Vector2D.h" +#include "Entity.h" + +typedef std::function gamefunction; + +class AssetManager; +class CollisionHandler; +class TextureManager; +class SoundManager; +class Map; +class Game; + +class GameInternal +{ +public: + GameInternal(); + ~GameInternal(); + + void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen); + void selectCharacters(const char* &playerSprite, const char* &enemySprite); + + void handleEvents(); + void update(); + void render(); + void clean(); + bool running() const; + + /* static */ SDL_Renderer* renderer = nullptr; + /* static */ SDL_Event event; + /* static */ CollisionHandler* collisionHandler; + /* static */ AssetManager* assets; + /* static */ TextureManager* textureManager; + /* static */ SoundManager* soundManager; + + // moved globals + Manager manager; + Map* map; // game specific, might not be needed for all types of games + + Entity& player1; + Entity& player2; + + Entity& wall; + + std::vector& tiles; + std::vector& players; + std::vector& projectiles; + std::vector& hearts; + std::vector& powerups; + // end moved globals + + void refreshPlayers(); + Entity::TeamLabel getWinner() const; + void setWinner(Entity::TeamLabel winningTeam); + +private: + + Game* gameInstance; + + int counter = 0; + bool isRunning = false; + SDL_Window* window; + Entity::TeamLabel winner; +}; diff --git a/include/GameRegistryHelper.h b/include/GameRegistryHelper.h new file mode 100644 index 0000000..b980d70 --- /dev/null +++ b/include/GameRegistryHelper.h @@ -0,0 +1,17 @@ +#pragma once + +#include "GameFactory.h" + +namespace vego { + template + class GameRegistryHelper { + public: + GameRegistryHelper(const std::string& className) { + static_assert(std::is_base_of::value, "Your class must inherit from Game"); + GameFactory::instance().registerClass( + className, + []() -> Game* { return new T; } + ); + }; + }; +} \ No newline at end of file diff --git a/include/Manager.h b/include/Manager.h index 2497667..ea549db 100644 --- a/include/Manager.h +++ b/include/Manager.h @@ -9,11 +9,11 @@ #include "Constants.h" #include "Entity.h" -class Game; +class GameInternal; class Manager { public: - Manager(Game* game) : game(game) {}; + Manager(GameInternal* game) : game(game) {}; void update(); void draw(); @@ -29,10 +29,10 @@ public: Entity& addEntity(); - Game* getGame() { return this->game; }; + GameInternal* getGame() { return this->game; }; private: - Game* game; + GameInternal* game; std::vector> entities; std::array, MAX_GROUPS> entitiesByGroup; std::array, MAX_TEAMS> entitiesByTeam; diff --git a/include/Map.h b/include/Map.h index 09f46b6..4c1bc3b 100644 --- a/include/Map.h +++ b/include/Map.h @@ -3,7 +3,7 @@ #include #include -class Game; +class GameInternal; class Map { public: @@ -21,6 +21,6 @@ public: * \return Boolean for success * */ - static void loadMap(const char* path, int sizeX, int sizeY, Game* game, const std::map>* textureDict /* backreference */); - static void addTile(unsigned long id, int x, int y, Game* game, const std::map>* textureDict); + static void loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map>* textureDict /* backreference */); + static void addTile(unsigned long id, int x, int y, GameInternal* game, const std::map>* textureDict); }; diff --git a/include/PopupWindow.h b/include/PopupWindow.h index ccd01f6..464ab28 100644 --- a/include/PopupWindow.h +++ b/include/PopupWindow.h @@ -5,7 +5,7 @@ #include "Entity.h" -class Game; +class GameInternal; class PopupWindow { diff --git a/include/SoundManager.h b/include/SoundManager.h index 6fa2d73..bcfc0ac 100644 --- a/include/SoundManager.h +++ b/include/SoundManager.h @@ -13,7 +13,7 @@ enum SoundTypes THROW_EGG, }; -class Game; +class GameInternal; class SoundManager { public: @@ -30,6 +30,6 @@ class SoundManager std::map sound_cache; Mix_Chunk* loadSound(const char* fileName); - static void playSound(Game* game, SoundTypes sound); + static void playSound(GameInternal* game, SoundTypes sound); private: }; \ No newline at end of file diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 8a70be9..d737a5d 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -3,7 +3,7 @@ #include "TextureManager.h" #include "SoundManager.h" #include "ProjectileComponent.h" -#include "Game.h" +#include "GameInternal.h" #include "TransformComponent.h" @@ -11,7 +11,6 @@ #include "ColliderComponent.h" #include "Constants.h" #include "Entity.h" -#include "Game.h" #include "Vector2D.h" #include "PowerupComponent.h" #include diff --git a/src/ColliderComponent.cpp b/src/ColliderComponent.cpp index 08475d0..aeca234 100644 --- a/src/ColliderComponent.cpp +++ b/src/ColliderComponent.cpp @@ -2,7 +2,7 @@ #include "CollisionHandler.h" #include "Entity.h" -#include "Game.h" +#include "GameInternal.h" #include "TransformComponent.h" #include diff --git a/src/Game.cpp b/src/GameInternal.cpp similarity index 86% rename from src/Game.cpp rename to src/GameInternal.cpp index c38cc9c..148a32e 100644 --- a/src/Game.cpp +++ b/src/GameInternal.cpp @@ -1,4 +1,4 @@ -#include "Game.h" +#include "GameInternal.h" #include @@ -14,10 +14,10 @@ #include "TextureManager.h" #include "StatEffectsComponent.h" #include "Constants.h" +#include "Game.h" +#include "GameFactory.h" -Game* engine::game = nullptr; // will be initialized in constructor - -Game::Game() : +GameInternal::GameInternal() : manager(this), tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)), players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS)), @@ -27,18 +27,16 @@ Game::Game() : player1(manager.addEntity()), player2(manager.addEntity()), wall(manager.addEntity()) -{ - engine::game = this; -}; +{}; -Game::~Game() = default; +GameInternal::~GameInternal() = default; -void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) +void GameInternal::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) { - Game::assets = new AssetManager(&manager); - Game::textureManager = new TextureManager(&manager); - Game::soundManager = new SoundManager(); - Game::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer? + GameInternal::assets = new AssetManager(&manager); + GameInternal::textureManager = new TextureManager(&manager); + GameInternal::soundManager = new SoundManager(); + GameInternal::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer? int flags = 0; if (fullscreen) @@ -84,7 +82,7 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo } SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - SDL_Texture* backgroundTexture = Game::textureManager->loadTexture("assets/startscreen.png"); + SDL_Texture* backgroundTexture = GameInternal::textureManager->loadTexture("assets/startscreen.png"); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL); @@ -181,10 +179,11 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo player2.addComponent(); player2.addGroup((size_t) Entity::GroupLabel::PLAYERS); - engine::init(); + this->gameInstance = GameFactory::instance().create("Chickengame", this); //!< \todo Should be specified via a config file + this->gameInstance->init(); } -void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite) +void GameInternal::selectCharacters(const char* &playerSprite, const char* &enemySprite) { // TODO: move this whereever it makes sense (maybe game as a member) std::map> characterSprites; @@ -252,7 +251,7 @@ void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite) } } - SDL_Texture* backgroundTexture = Game::textureManager->loadTexture("assets/characterSelection.png"); + SDL_Texture* backgroundTexture = GameInternal::textureManager->loadTexture("assets/characterSelection.png"); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL); @@ -280,7 +279,7 @@ void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite) this->isRunning = true; } -void Game::handleEvents() +void GameInternal::handleEvents() { SDL_PollEvent(&event); @@ -294,15 +293,15 @@ void Game::handleEvents() } } -void Game::update() +void GameInternal::update() { manager.refresh(); manager.update(); - engine::update(); // TODO: this might have to be split up into two update functions, before and after manager... + this->gameInstance->update(); // TODO: this might have to be split up into two update functions, before and after manager... } -void Game::render() +void GameInternal::render() { SDL_RenderClear(renderer); for (auto& t : tiles) @@ -323,7 +322,7 @@ void Game::render() SDL_RenderPresent(renderer); } -void Game::clean() +void GameInternal::clean() { delete(textureManager); SDL_DestroyRenderer(renderer); @@ -332,18 +331,18 @@ void Game::clean() std::cout << "Game Cleaned!" << std::endl; } -bool Game::running() const +bool GameInternal::running() const { return isRunning; } -void Game::setWinner(Entity::TeamLabel winningTeam) +void GameInternal::setWinner(Entity::TeamLabel winningTeam) { this->winner = winningTeam; this->isRunning = false; } -Entity::TeamLabel Game::getWinner() const +Entity::TeamLabel GameInternal::getWinner() const { return this->winner; } diff --git a/src/GameObject.cpp b/src/GameObject.cpp index b94c03a..2b065c2 100644 --- a/src/GameObject.cpp +++ b/src/GameObject.cpp @@ -2,7 +2,7 @@ #include "SDL_error.h" #include "TextureManager.h" -#include "Game.h" +#include "GameInternal.h" GameObject::GameObject(const char* texturesheet, int x, int y) { diff --git a/src/HealthComponent.cpp b/src/HealthComponent.cpp index 25dd3ff..ead3412 100644 --- a/src/HealthComponent.cpp +++ b/src/HealthComponent.cpp @@ -2,7 +2,7 @@ #include "Direction.h" #include "Entity.h" -#include "Game.h" +#include "GameInternal.h" #include void HealthComponent::init() diff --git a/src/Map.cpp b/src/Map.cpp index 125f029..5689d9e 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -6,11 +6,11 @@ #include #include "Constants.h" -#include "Game.h" +#include "GameInternal.h" #include "SDL_error.h" #include "TileComponent.h" -void Map::loadMap(const char* path, int sizeX, int sizeY, Game* game, const std::map>* textureDict /* backreference */) +void Map::loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map>* textureDict /* backreference */) { std::string tileIDstr; char singleChar = 0; @@ -56,7 +56,7 @@ void Map::loadMap(const char* path, int sizeX, int sizeY, Game* game, const std: mapFile.close(); } -void Map::addTile(unsigned long id, int x, int y, Game* game, const std::map>* textureDict) // tile entity +void Map::addTile(unsigned long id, int x, int y, GameInternal* game, const std::map>* textureDict) // tile entity { auto& tile(game->manager.addEntity()); tile.addComponent(x, y, TILE_SIZE, TILE_SIZE, id, textureDict); diff --git a/src/PopupWindow.cpp b/src/PopupWindow.cpp index 5912eaf..39362a9 100644 --- a/src/PopupWindow.cpp +++ b/src/PopupWindow.cpp @@ -4,7 +4,7 @@ #include "Entity.h" #include "PopupWindow.h" #include "TextureManager.h" -#include "Game.h" +#include "GameInternal.h" PopupWindow::PopupWindow(const char* title, const std::string &message) : continueGame(false), interacted(false) { diff --git a/src/PowerupComponent.cpp b/src/PowerupComponent.cpp index 48de1be..7d4ce0a 100644 --- a/src/PowerupComponent.cpp +++ b/src/PowerupComponent.cpp @@ -1,5 +1,5 @@ #include "PowerupComponent.h" -#include "Game.h" +#include "GameInternal.h" #include "CollisionHandler.h" #include "Entity.h" #include "HealthComponent.h" diff --git a/src/ProjectileComponent.cpp b/src/ProjectileComponent.cpp index deb588d..75c711b 100644 --- a/src/ProjectileComponent.cpp +++ b/src/ProjectileComponent.cpp @@ -4,7 +4,7 @@ #include "SoundManager.h" #include "TransformComponent.h" #include "Entity.h" -#include "Game.h" +#include "GameInternal.h" #include "HealthComponent.h" #include "Vector2D.h" #include diff --git a/src/SoundManager.cpp b/src/SoundManager.cpp index 2a890d7..b8575c8 100644 --- a/src/SoundManager.cpp +++ b/src/SoundManager.cpp @@ -4,7 +4,7 @@ #include #include -#include "Game.h" +#include "GameInternal.h" #include "AssetManager.h" Mix_Chunk* SoundManager::loadSound(const char* fileName) @@ -27,7 +27,7 @@ Mix_Chunk* SoundManager::loadSound(const char* fileName) return sound; } -void SoundManager::playSound(Game* game, SoundTypes sound) +void SoundManager::playSound(GameInternal* game, SoundTypes sound) { switch (sound) { diff --git a/src/SpriteComponent.cpp b/src/SpriteComponent.cpp index ab40f25..9dea93e 100644 --- a/src/SpriteComponent.cpp +++ b/src/SpriteComponent.cpp @@ -9,7 +9,7 @@ #include "TextureManager.h" #include "Entity.h" #include "TransformComponent.h" -#include "Game.h" +#include "GameInternal.h" #include "Manager.h" SpriteComponent::SpriteComponent(const char* path) diff --git a/src/TextureManager.cpp b/src/TextureManager.cpp index 6d56c35..3e46d46 100644 --- a/src/TextureManager.cpp +++ b/src/TextureManager.cpp @@ -4,7 +4,7 @@ #include #include -#include "Game.h" +#include "GameInternal.h" SDL_Texture* TextureManager::loadTexture(const char* fileName) { diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index 3175968..71b1302 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -4,7 +4,7 @@ #include "ColliderComponent.h" #include "Constants.h" #include "Entity.h" -#include "Game.h" +#include "GameInternal.h" #include "Vector2D.h" #include #include diff --git a/src/main.cpp b/src/main.cpp index ce47941..092afb4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,11 +2,11 @@ #include #include "Entity.h" -#include "Game.h" +#include "GameInternal.h" #include "Constants.h" #include "PopupWindow.h" -Game* game = nullptr; +GameInternal* game = nullptr; int main(int argc, char* argv[]) { @@ -18,7 +18,7 @@ int main(int argc, char* argv[]) Uint32 frameStart; int frameTime; - game = new Game(); + game = new GameInternal(); game->init("No_Name_Chicken_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false); while (game->running()) {