diff --git a/CMakeLists.txt b/CMakeLists.txt index e2bb869..90cb5fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,7 +136,9 @@ set(SOURCES src/game/layer/global_layer.cpp src/game/layer/global_layer.hpp src/typography/font_manager.cpp - src/typography/font_manager.hpp) + src/typography/font_manager.hpp + src/screens/winner_screen.cpp + src/screens/winner_screen.hpp src/screens/screen.cpp src/screens/screen.hpp) set(PHYSICS_00_SOURCES src/prototypes/physics_00.cpp) diff --git a/src/config.h b/src/config.h index f717123..912d384 100644 --- a/src/config.h +++ b/src/config.h @@ -26,6 +26,7 @@ // Window settings #define ANTIALIASINGLEVEL 8 #define KEY_REPEAT_ENABLED false +#define REFERENCE_SIZE sf::Vector2f(1920, 1080) // Graphic settings #define ISOMETRIC_SKEW (16.f/32.f) diff --git a/src/game/game.cpp b/src/game/game.cpp index b588bb8..87e4b5c 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -7,6 +7,8 @@ #include "physics/map/map_simulation.hpp" #include "../logging/easylogging++.h" #include "layer/global_layer.hpp" +#include "player/player_collection.hpp" +#include "../screens/winner_screen.hpp" Game::Game(std::shared_ptr window) : window(std::move(window)) { @@ -65,6 +67,8 @@ void Game::addGameObject(const std::shared_ptr &gameObject) void Game::update() { + handleWinning(); + // Add new game objects for (const auto &gameObject: gameObjectsBuffer) { @@ -152,3 +156,54 @@ void Game::startCountdown(int durationInSeconds) countdown = std::make_shared(durationInSeconds); GlobalLayer::getInstance()->add(countdown); } + +std::shared_ptr Game::checkForWinner() +{ + std::vector> players = PlayerCollection::getInstance()->getPlayers(); + + // Has timer run out or is only one player left? + if (!countdown->isFinished() && players.size() > 1) + { + return nullptr; + } + + // Return player with highest score as winner + std::shared_ptr winner = nullptr; + for (const auto &player: players) + { + if (winner == nullptr || player->getPoints() > winner->getPoints()) + { + winner = player; + } + } + + return winner; +} + +void Game::handleWinning() +{ + if (!isLevelLoaded()) + { + return; + } + + // Any players in game? + if (PlayerCollection::getInstance()->getPlayers().empty()) + { + return; + } + + std::shared_ptr winner = checkForWinner(); + if (winner == nullptr) + { + return; + } + + LOG(INFO) << "Player " << winner->getPlayerId() << " won the game with " << winner->getPoints() << " points."; + + // Stop game and show winner + LevelLoader::cleanUp(); + auto winnerScreen = std::make_shared(winner); + GlobalLayer::getInstance()->add(winnerScreen); + addGameObject(GlobalLayer::getInstance()); +} diff --git a/src/game/game.h b/src/game/game.h index 6cb17d6..7e7cd1b 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -51,6 +51,10 @@ private: void drawFrame(); void update(); + + std::shared_ptr checkForWinner(); + + void handleWinning(); }; diff --git a/src/game/layer/global_layer.cpp b/src/game/layer/global_layer.cpp index a4cf365..c3f9f96 100644 --- a/src/game/layer/global_layer.cpp +++ b/src/game/layer/global_layer.cpp @@ -25,8 +25,8 @@ GlobalLayer::GlobalLayer() { // Reference screen size of 1920x1080 TrackingViewOptions options = { - .minViewSize = sf::Vector2f{10, 1080}, - .initialCenter = sf::Vector2f{1920, 1080} / 2.0f, + .minViewSize = sf::Vector2f{10, REFERENCE_SIZE.y}, + .initialCenter = REFERENCE_SIZE / 2.0f, }; view = std::make_shared(options); diff --git a/src/game/level/level_loader.cpp b/src/game/level/level_loader.cpp index e93a725..c50bc95 100644 --- a/src/game/level/level_loader.cpp +++ b/src/game/level/level_loader.cpp @@ -90,3 +90,16 @@ void LevelLoader::spawnCollectable(const CollectableInLevel &collectableInfo) CollectablesCollection::getInstance()->add(collectable); HolesSimulation::getInstance()->addCollectable(collectable); } + +void LevelLoader::cleanUp() +{ + auto game = Game::getInstance(); + game->clearGameObjects(); + game->setLevel(LevelConfig()); + HolesSimulation::getInstance()->clear(); + PlayerCollection::getInstance()->clear(); + GlobalLayer::getInstance()->clear(); + HoleLayout::getInstance()->clear(); + + LOG(INFO) << "Cleaned up level."; +} diff --git a/src/game/level/level_loader.hpp b/src/game/level/level_loader.hpp index 0dce671..e30ee47 100644 --- a/src/game/level/level_loader.hpp +++ b/src/game/level/level_loader.hpp @@ -12,6 +12,8 @@ public: static void loadLevel(const std::string &levelName); + static void cleanUp(); + static void spawnCollectable(const CollectableInLevel &collectableInfo); }; diff --git a/src/screens/screen.cpp b/src/screens/screen.cpp new file mode 100644 index 0000000..d54a56a --- /dev/null +++ b/src/screens/screen.cpp @@ -0,0 +1,21 @@ +#include "screen.hpp" + +void Screen::draw(sf::RenderWindow *window) +{ + GameObject::draw(window); + + for(auto &drawable : drawables) + { + window->draw(*drawable); + } +} + +void Screen::add(const std::shared_ptr& drawable) +{ + drawables.push_back(drawable); +} + +void Screen::add(const std::shared_ptr& gameObject) +{ + addDetachedChild(gameObject); +} diff --git a/src/screens/screen.hpp b/src/screens/screen.hpp new file mode 100644 index 0000000..509eacf --- /dev/null +++ b/src/screens/screen.hpp @@ -0,0 +1,20 @@ +#ifndef HOLESOME_SCREEN_HPP +#define HOLESOME_SCREEN_HPP + + +#include "../game/game_object.h" + +class Screen : public GameObject +{ +public: + void draw(sf::RenderWindow *window) override; + +protected: + std::vector> drawables; + + void add(const std::shared_ptr& drawable); + void add(const std::shared_ptr& gameObject); +}; + + +#endif //HOLESOME_SCREEN_HPP diff --git a/src/screens/winner_screen.cpp b/src/screens/winner_screen.cpp new file mode 100644 index 0000000..52528c3 --- /dev/null +++ b/src/screens/winner_screen.cpp @@ -0,0 +1,34 @@ +#include "winner_screen.hpp" + +#include "../typography/font_manager.hpp" +#include "../texture_config.h" + +WinnerScreen::WinnerScreen(const std::shared_ptr &winner) + : winner(winner) +{ + // Winner title + auto winnerTitle = std::make_shared(); + winnerTitle->setFont(*FontManager::getInstance()->getDefaultFont()); + winnerTitle->setString("Winner"); + winnerTitle->setCharacterSize(50); + winnerTitle->setFillColor(sf::Color::Yellow); + winnerTitle->setStyle(sf::Text::Bold); + winnerTitle->setPosition(REFERENCE_SIZE.x / 2 - winnerTitle->getGlobalBounds().width / 2, 100); + add(winnerTitle); + + // Add graphic of the winner + auto winnerGraphic = std::make_shared(PLAYER_SKIN); + auto center = REFERENCE_SIZE / 2.f; + auto winnerPosition = center - winnerGraphic->getSize() / 2.f; + winnerGraphic->coordinates->setIsometric(IsometricCoordinates(winnerPosition)); + add(winnerGraphic); + + // Show points below + auto points = std::make_shared(); + points->setFont(*FontManager::getInstance()->getDefaultFont()); + points->setString("Points: " + std::to_string(winner->getPoints())); + points->setCharacterSize(20); + points->setFillColor(sf::Color::White); + points->setPosition(REFERENCE_SIZE.x / 2 - points->getGlobalBounds().width / 2, REFERENCE_SIZE.y - 300); + add(points); +} diff --git a/src/screens/winner_screen.hpp b/src/screens/winner_screen.hpp new file mode 100644 index 0000000..234c90f --- /dev/null +++ b/src/screens/winner_screen.hpp @@ -0,0 +1,19 @@ +#ifndef HOLESOME_WINNER_SCREEN_HPP +#define HOLESOME_WINNER_SCREEN_HPP + + +#include +#include "../game/player/player.hpp" +#include "screen.hpp" + +class WinnerScreen : public Screen +{ +public: + WinnerScreen(const std::shared_ptr &winner); + +private: + std::shared_ptr winner; +}; + + +#endif //HOLESOME_WINNER_SCREEN_HPP