From 414f3b79fc2ef8363f080d84980abcdef3997fa0 Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Tue, 13 Jun 2023 21:59:50 +0200 Subject: [PATCH] Improved map wallout, fixed spawned player in wall glitch and now actually rendering collectables. Player handling has also been reworked --- CMakeLists.txt | 4 +- src/config.h | 2 + src/coordinates/translated_coordinates.cpp | 5 + src/coordinates/translated_coordinates.h | 9 +- src/game/camera/tracking_view.cpp | 45 +++++++- src/game/camera/tracking_view.h | 5 + src/game/camera/tracking_view_options.hpp | 5 + src/game/collectables/collectable.cpp | 5 - src/game/collectables/collectable.hpp | 2 - .../collection/collectables_collection.cpp | 13 ++- .../collection/collectables_collection.hpp | 2 + src/game/game.cpp | 16 ++- src/game/game_object.cpp | 22 ++++ src/game/game_object.h | 4 + src/game/level/level_loader.cpp | 25 ++++- .../physics/hole/hole_depth_simulation.cpp | 2 +- .../physics/hole/hole_depth_simulation.hpp | 6 +- src/game/physics/map/map_simulation.cpp | 45 ++++++-- src/game/physics/map/map_simulation.hpp | 7 +- src/game/player/player.cpp | 13 ++- src/game/player/player.hpp | 5 +- src/game/player/player_collection.cpp | 106 ++++++++++++++++++ src/game/player/player_collection.hpp | 42 +++++++ src/game/player/player_spawner.cpp | 39 ------- src/game/player/player_spawner.hpp | 23 ---- src/logging/easylogging++.h | 2 +- src/texture_config.h | 2 +- 27 files changed, 345 insertions(+), 111 deletions(-) create mode 100644 src/game/player/player_collection.cpp create mode 100644 src/game/player/player_collection.hpp delete mode 100644 src/game/player/player_spawner.cpp delete mode 100644 src/game/player/player_spawner.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 45c0676..a708826 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,8 +52,6 @@ set(SOURCES src/game/camera/ITrackable.h src/game/input/input_identity.h src/utilities/magic_enum.hpp - src/game/player/player_spawner.cpp - src/game/player/player_spawner.hpp src/game/camera/tracking_area.h src/game/camera/tracking_view_options.hpp src/game/collectables/collectable.cpp @@ -96,7 +94,7 @@ set(SOURCES src/game/collectables/collection/collectables_collection.cpp src/game/collectables/collection/collectables_collection.hpp src/game/collectables/collection/collectables_depth_collection.cpp - src/game/collectables/collection/collectables_depth_collection.hpp src/game/collectables/collectable_in_level.hpp src/game/collectables/collectable_factory.cpp src/game/collectables/collectable_factory.hpp) + src/game/collectables/collection/collectables_depth_collection.hpp src/game/collectables/collectable_in_level.hpp src/game/collectables/collectable_factory.cpp src/game/collectables/collectable_factory.hpp src/game/player/player_collection.cpp src/game/player/player_collection.hpp) set(PHYSICS_00_SOURCES src/prototypes/physics_00.cpp) diff --git a/src/config.h b/src/config.h index 83ab1b0..adb33a4 100644 --- a/src/config.h +++ b/src/config.h @@ -34,8 +34,10 @@ #define DEF_TV_MIN_VIEW_SIZE sf::Vector2f(6, 6) * WORLD_TO_ISO_SCALE #define DEF_TV_MAX_VIEW_SIZE sf::Vector2f(0, 0) #define DEF_TV_VIEW_SIZE_PADDING sf::Vector2f(0.5f, 0.5f) +#define DEF_TV_ADD_PLAYERS_DYNAMICALLY true // Simulations +#define MAPSIM_WALL_THICKNESS 3.f #define MAPSIM_VELOCITY_ITERATIONS 6 #define MAPSIM_POSITION_ITERATIONS 2 #define HOLESIM_VELOCITY_ITERATIONS 8 diff --git a/src/coordinates/translated_coordinates.cpp b/src/coordinates/translated_coordinates.cpp index 56a8425..f2cc6be 100644 --- a/src/coordinates/translated_coordinates.cpp +++ b/src/coordinates/translated_coordinates.cpp @@ -68,3 +68,8 @@ void TranslatedCoordinates::setScreenOffset(IsometricCoordinates offset) { setWorldOffset(CoordinateTransformer::isometricToWorld(offset)); } + +TranslatedCoordinates::TranslatedCoordinates(GridCoordinates gridCoordinates) +{ + set(gridCoordinates); +} diff --git a/src/coordinates/translated_coordinates.h b/src/coordinates/translated_coordinates.h index 01769f5..7a7bd10 100644 --- a/src/coordinates/translated_coordinates.h +++ b/src/coordinates/translated_coordinates.h @@ -9,12 +9,13 @@ class TranslatedCoordinates { public: explicit TranslatedCoordinates(WorldCoordinates worldCoordinates); + explicit TranslatedCoordinates(GridCoordinates gridCoordinates); - WorldCoordinates world() const; + [[nodiscard]] WorldCoordinates world() const; - IsometricCoordinates isometric() const; + [[nodiscard]] IsometricCoordinates isometric() const; - GridCoordinates grid() const; + [[nodiscard]] GridCoordinates grid() const; void set(WorldCoordinates newWorldCoordinates); @@ -35,7 +36,7 @@ public: void setScreenOffset(IsometricCoordinates offset); private: - WorldCoordinates worldCoordinates; + WorldCoordinates worldCoordinates{}; std::shared_ptr parent = nullptr; }; diff --git a/src/game/camera/tracking_view.cpp b/src/game/camera/tracking_view.cpp index 5c0ef1e..57bf798 100644 --- a/src/game/camera/tracking_view.cpp +++ b/src/game/camera/tracking_view.cpp @@ -1,11 +1,13 @@ #include "tracking_view.h" #include "../../utilities/vector_utils.hpp" +#include "../player/player_collection.hpp" TrackingView::TrackingView(TrackingViewOptions options) : options(options), view(nullptr), hasViewChanged(false), trackables({}) -{; +{ + ; marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow); Game::getInstance()->registerView(this); } @@ -65,7 +67,8 @@ void TrackingView::setSize(sf::Vector2f newSize) didAspectRationChange = true; } - if (options.softResizeSpeed != 0 && !didAspectRationChange) { + if (options.softResizeSpeed != 0 && !didAspectRationChange) + { // Smooth out transition to new size newSize = size + (newSize - size) * options.softResizeSpeed * FRAME_TIME.asSeconds(); } @@ -142,7 +145,7 @@ void TrackingView::draw(sf::RenderWindow *window) marker->draw(window); } -void TrackingView::addTrackable(const std::shared_ptr& trackable) +void TrackingView::addTrackable(const std::shared_ptr &trackable) { trackables.push_back(trackable); } @@ -271,3 +274,39 @@ float TrackingView::getRadius(float threshold) const // Only half of the side, since we are calculating radius return smallestSide / 2.f * threshold; } + +void TrackingView::update() +{ + if (options.addPlayersDynamically) + { + addPlayersDynamically(); + } +} + +void TrackingView::addPlayersDynamically() +{ + // Update based on PlayerCollection + // Add new + for (const auto &player: PlayerCollection::getInstance()->getNewPlayers()) + { + if (player->getTrackableState() == TrackableState::TRACKING) + { + addTrackable(player); + } + } + + // Remove old + for (const auto &player: PlayerCollection::getInstance()->getRemovedPlayers()) + { + removeTrackable(player); + } +} + +void TrackingView::removeTrackable(const std::shared_ptr &trackable) +{ + trackables.erase( + std::remove_if(trackables.begin(), trackables.end(), [&trackable](const std::shared_ptr &t) + { + return t == trackable; + }), trackables.end()); +} diff --git a/src/game/camera/tracking_view.h b/src/game/camera/tracking_view.h index b64529a..3bc9823 100644 --- a/src/game/camera/tracking_view.h +++ b/src/game/camera/tracking_view.h @@ -17,6 +17,7 @@ public: ~TrackingView(); + void update() override; void draw(sf::RenderWindow *window) override; @@ -24,6 +25,8 @@ public: void addTrackable(const std::shared_ptr& trackable); + void removeTrackable(const std::shared_ptr &trackable); + sf::Vector2f getSize() const; sf::Vector2f getCenter() const; @@ -57,6 +60,8 @@ private: float getRadius(float threshold) const; sf::Vector2f getWindowSize() const; + + void addPlayersDynamically(); }; diff --git a/src/game/camera/tracking_view_options.hpp b/src/game/camera/tracking_view_options.hpp index 49d2bce..fee18de 100644 --- a/src/game/camera/tracking_view_options.hpp +++ b/src/game/camera/tracking_view_options.hpp @@ -37,6 +37,11 @@ struct TrackingViewOptions * Value between 0 and 1 to set relative padding. */ sf::Vector2f viewSizePadding = DEF_TV_VIEW_SIZE_PADDING; + + /** + * If set to true, view will add all new players automatically and remove them accordingly, based on PlayerCollection. + */ + bool addPlayersDynamically = DEF_TV_ADD_PLAYERS_DYNAMICALLY; }; #endif //HOLESOME_TRACKING_VIEW_OPTIONS_HPP diff --git a/src/game/collectables/collectable.cpp b/src/game/collectables/collectable.cpp index c695510..94cdbb6 100644 --- a/src/game/collectables/collectable.cpp +++ b/src/game/collectables/collectable.cpp @@ -8,11 +8,6 @@ Collectable::Collectable() collectableCount++; } -void Collectable::draw(sf::RenderWindow *window) -{ - -} - void Collectable::setRotation(float angle) { diff --git a/src/game/collectables/collectable.hpp b/src/game/collectables/collectable.hpp index edd317d..dbb816d 100644 --- a/src/game/collectables/collectable.hpp +++ b/src/game/collectables/collectable.hpp @@ -9,8 +9,6 @@ class Collectable : public GameObject public: Collectable(); - void draw(sf::RenderWindow *window) override; - void setSprite(const std::string &spriteName); void setRotation(float angle); diff --git a/src/game/collectables/collection/collectables_collection.cpp b/src/game/collectables/collection/collectables_collection.cpp index c05b7e2..dabee5c 100644 --- a/src/game/collectables/collection/collectables_collection.cpp +++ b/src/game/collectables/collection/collectables_collection.cpp @@ -66,7 +66,7 @@ void CollectablesCollection::update() void CollectablesCollection::draw(sf::RenderWindow *window) { // Render collectables in reverse order of depth - int maxDepth = depthCollections.size(); + int maxDepth = (int) depthCollections.size(); for (int depth = maxDepth - 1; depth >= 0; depth--) { auto depthCollection = depthCollections.at(depth); @@ -87,3 +87,14 @@ void CollectablesCollection::updateCollectables() } } } + +std::shared_ptr CollectablesCollection::getDepthCollection(int depth) +{ + if (depthCollections.find(depth) == depthCollections.end()) + { + LOG(ERROR) << "Depth collection for depth " << depth << " does not exist! Returning empty collection ..."; + return std::make_shared(depth); + } + + return depthCollections[depth]; +} diff --git a/src/game/collectables/collection/collectables_collection.hpp b/src/game/collectables/collection/collectables_collection.hpp index a776421..0aad6f4 100644 --- a/src/game/collectables/collection/collectables_collection.hpp +++ b/src/game/collectables/collection/collectables_collection.hpp @@ -23,6 +23,8 @@ public: void add(const std::shared_ptr& collectable); void remove(const std::shared_ptr& collectable); + std::shared_ptr getDepthCollection(int depth); + private: static inline std::shared_ptr singletonInstance = nullptr; diff --git a/src/game/game.cpp b/src/game/game.cpp index 4069532..2ef7233 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -5,6 +5,7 @@ #include "game.h" #include "level/level_loader.hpp" #include "physics/map/map_simulation.hpp" +#include "../logging/easylogging++.h" Game::Game(std::shared_ptr window) : window(std::move(window)) { @@ -15,6 +16,7 @@ void Game::run() sf::Clock clock; sf::Time TimeSinceLastUpdate = sf::seconds(0); + LOG(INFO) << "Game loop started ..."; while (window->isOpen()) { @@ -29,6 +31,8 @@ void Game::run() } drawFrame(); } + + LOG(INFO) << "Game closing ..."; } void Game::exit() @@ -83,12 +87,16 @@ void Game::update() } } - InputMapper::getInstance()->updateIdentities(); - - if (isLevelLoaded()) + // Physics updates + for (const auto &gameObject: gameObjects) { - MapSimulation::getInstance()->updateSimulation(); + if (gameObject->getActive()) + { + gameObject->physicsUpdate(); + } } + + InputMapper::getInstance()->updateIdentities(); } std::shared_ptr Game::getInstance() diff --git a/src/game/game_object.cpp b/src/game/game_object.cpp index a8332af..c75ca70 100644 --- a/src/game/game_object.cpp +++ b/src/game/game_object.cpp @@ -57,3 +57,25 @@ void GameObject::addChild(const std::shared_ptr &child) { addChildWorldOffset(child, {0, 0}); } + +void GameObject::removeChild(const std::shared_ptr &child) +{ + auto it = std::find(children.begin(), children.end(), child); + if (it != children.end()) + { + children.erase(it); + } +} + +void GameObject::clearChildren() +{ + children.clear(); +} + +void GameObject::physicsUpdate() +{ + for (auto &child: children) + { + child->physicsUpdate(); + } +} diff --git a/src/game/game_object.h b/src/game/game_object.h index 9d69baf..a87fede 100644 --- a/src/game/game_object.h +++ b/src/game/game_object.h @@ -18,12 +18,16 @@ public: virtual void lateUpdate(); + virtual void physicsUpdate(); + void setActive(bool active); bool getActive() const { return isActive; } void addChildScreenOffset(const std::shared_ptr &child, IsometricCoordinates offset = {0, 0}); void addChildWorldOffset(const std::shared_ptr &child, WorldCoordinates offset); void addChild(const std::shared_ptr &child); + void removeChild(const std::shared_ptr &child); + void clearChildren(); [[nodiscard]] std::vector> getChildren() const { return children; } std::shared_ptr coordinates; diff --git a/src/game/level/level_loader.cpp b/src/game/level/level_loader.cpp index 4dc71ed..a899265 100644 --- a/src/game/level/level_loader.cpp +++ b/src/game/level/level_loader.cpp @@ -2,12 +2,13 @@ #include "../game.h" #include "../physics/map/map_simulation.hpp" #include "../../debug/grid_debug_layer.h" -#include "../player/player_spawner.hpp" #include "../../levels.hpp" #include "../collectables/collection/collectables_collection.hpp" #include "../collectables/collectable_factory.hpp" +#include "../player/player_collection.hpp" +#include "../physics/hole/hole_depth_simulation.hpp" -void LevelLoader::loadLevel(const LevelConfig& levelConfig) +void LevelLoader::loadLevel(const LevelConfig &levelConfig) { auto game = Game::getInstance(); game->clearGameObjects(); @@ -16,6 +17,7 @@ void LevelLoader::loadLevel(const LevelConfig& levelConfig) game->setLevel(levelConfig); MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize); + PlayerCollection::getInstance()->clear(); // Add basic game objects if (DEVELOPER_MODE) @@ -24,12 +26,14 @@ void LevelLoader::loadLevel(const LevelConfig& levelConfig) } game->addGameObject(std::make_shared()); - game->addGameObject(std::make_shared(levelConfig.playerSpawnPoints)); + game->addGameObject(PlayerCollection::getInstance()); + PlayerCollection::getInstance()->setSpawnPoints(levelConfig.playerSpawnPoints); // Prepare collectables framework - auto maxDepth = levelConfig.worldMapSize.x * 2; - CollectablesCollection::getInstance()->createEmpty(maxDepth); - game->addGameObject(CollectablesCollection::getInstance()); + auto maxDepth = (int) levelConfig.worldMapSize.x * 2; + auto collectablesCollection = CollectablesCollection::getInstance(); + collectablesCollection->createEmpty(maxDepth); + game->addGameObject(collectablesCollection); // Spawn collectibles for (auto const &collectableInfo: levelConfig.collectables) @@ -37,6 +41,15 @@ void LevelLoader::loadLevel(const LevelConfig& levelConfig) spawnCollectable(collectableInfo); } + // Add physics simulations + game->addGameObject(MapSimulation::getInstance()); + // For every depth, add a hole depth simulation + for (int depth = 0; depth < maxDepth; depth++) + { + auto depthCollection = collectablesCollection->getDepthCollection(depth); + game->addGameObject(std::make_shared(depthCollection)); + } + LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; } diff --git a/src/game/physics/hole/hole_depth_simulation.cpp b/src/game/physics/hole/hole_depth_simulation.cpp index 387724f..3d1c995 100644 --- a/src/game/physics/hole/hole_depth_simulation.cpp +++ b/src/game/physics/hole/hole_depth_simulation.cpp @@ -7,7 +7,7 @@ HoleDepthSimulation::HoleDepthSimulation(std::shared_ptr(WORLD_GRAVITY); } -void HoleDepthSimulation::updateSimulation() +void HoleDepthSimulation::physicsUpdate() { updateBodiesFromCollectionHistory(); diff --git a/src/game/physics/hole/hole_depth_simulation.hpp b/src/game/physics/hole/hole_depth_simulation.hpp index d364e24..5b62409 100644 --- a/src/game/physics/hole/hole_depth_simulation.hpp +++ b/src/game/physics/hole/hole_depth_simulation.hpp @@ -10,12 +10,12 @@ /** * @brief Simulates the hole(s) for the specific depth */ -class HoleDepthSimulation +class HoleDepthSimulation : public GameObject { public: - HoleDepthSimulation(std::shared_ptr collectables); + explicit HoleDepthSimulation(std::shared_ptr collectables); - void updateSimulation(); + void physicsUpdate() override; private: std::shared_ptr collectables; diff --git a/src/game/physics/map/map_simulation.cpp b/src/game/physics/map/map_simulation.cpp index 881e24f..4cd6047 100644 --- a/src/game/physics/map/map_simulation.cpp +++ b/src/game/physics/map/map_simulation.cpp @@ -1,5 +1,6 @@ #include "map_simulation.hpp" #include "../../../config.h" +#include "../../player/player_collection.hpp" MapSimulation::MapSimulation() { @@ -15,7 +16,7 @@ std::shared_ptr MapSimulation::getInstance() return singletonInstance; } -void MapSimulation::updateSimulation() +void MapSimulation::physicsUpdate() { // Update simulation positions for (auto &mapPlayer: mapPlayersById) @@ -34,15 +35,20 @@ void MapSimulation::updateSimulation() void MapSimulation::resetMap(sf::Vector2f worldMapSize) { + // Clear all players + for (auto &mapPlayer: mapPlayersById) + { + removePlayer(mapPlayer.second->player); + } + // No gravity, since this a top-down view of the map world = std::make_shared(b2Vec2(0.0f, 0.0f)); - mapPlayersById.clear(); // Create map borders - constructSquareObstacle(-1, 0, 0, worldMapSize.y); - constructSquareObstacle(0, -1, worldMapSize.x, 0); - constructSquareObstacle(worldMapSize.x, 0, worldMapSize.x + 1, worldMapSize.y); - constructSquareObstacle(0, worldMapSize.y, worldMapSize.x, worldMapSize.y + 1); + constructSquareObstacle(-MAPSIM_WALL_THICKNESS, -MAPSIM_WALL_THICKNESS, 0, worldMapSize.y + MAPSIM_WALL_THICKNESS); // Bottom left + constructSquareObstacle(0, -MAPSIM_WALL_THICKNESS, worldMapSize.x, 0); // Bottom right + constructSquareObstacle(worldMapSize.x, -MAPSIM_WALL_THICKNESS, worldMapSize.x + MAPSIM_WALL_THICKNESS, worldMapSize.y + MAPSIM_WALL_THICKNESS); // Top right + constructSquareObstacle(0, worldMapSize.y, worldMapSize.x, worldMapSize.y + MAPSIM_WALL_THICKNESS); // Top left } void MapSimulation::constructSquareObstacle(float minX, float minY, float maxX, float maxY) @@ -62,11 +68,34 @@ void MapSimulation::constructSquareObstacle(float minX, float minY, float maxX, body->CreateFixture(&fixtureDef); } -void MapSimulation::addPlayer(const std::shared_ptr& player) +void MapSimulation::addPlayer(const std::shared_ptr &player) { b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; - bodyDef.position.Set(player->coordinates->world().x, player->coordinates->world().y); + bodyDef.position.Set(player->spawnPosition.world().x, player->spawnPosition.world().y); b2Body *body = world->CreateBody(&bodyDef); mapPlayersById[player->getPlayerId()] = std::make_shared(player, body); } + +void MapSimulation::update() +{ + // Update players from player collection + // New player + for (auto &player: PlayerCollection::getInstance()->getNewPlayers()) + { + addPlayer(player); + } + // Removed players + for (auto &player: PlayerCollection::getInstance()->getRemovedPlayers()) + { + removePlayer(player); + } +} + +void MapSimulation::removePlayer(std::shared_ptr &player) +{ + // Remove body from simulation + int playerId = player->getPlayerId(); + world->DestroyBody(mapPlayersById[playerId]->body); + mapPlayersById.erase(playerId); +} diff --git a/src/game/physics/map/map_simulation.hpp b/src/game/physics/map/map_simulation.hpp index 24e4f54..b6288fb 100644 --- a/src/game/physics/map/map_simulation.hpp +++ b/src/game/physics/map/map_simulation.hpp @@ -7,12 +7,14 @@ #include "../../player/player.hpp" #include "map_player.hpp" -class MapSimulation +class MapSimulation : public GameObject { public: MapSimulation(); - void updateSimulation(); + void update() override; + + void physicsUpdate() override; void resetMap(sf::Vector2f worldMapSize); @@ -29,6 +31,7 @@ private: void constructSquareObstacle(float minX, float minY, float maxX, float maxY); + void removePlayer(std::shared_ptr &player); }; diff --git a/src/game/player/player.cpp b/src/game/player/player.cpp index 7dfb218..2099b32 100644 --- a/src/game/player/player.cpp +++ b/src/game/player/player.cpp @@ -1,19 +1,21 @@ #include "player.hpp" -#include "../../config.h" +#include "../../logging/easylogging++.h" #include Player::Player(std::shared_ptr assignedInput, const std::string &skinRessourceName, GridCoordinates initCoordinates) + : spawnPosition(initCoordinates) { playerId = playerCreationCounter++; - this->spawnPosition = initCoordinates; - coordinates->set(initCoordinates); + coordinates->set(spawnPosition); input = std::move(assignedInput); skinSprite = std::make_shared(skinRessourceName, getIsoSize()); addChildScreenOffset(skinSprite, IsometricCoordinates(-getIsoSize() / 2.f)); + + LOG(INFO) << "Player " << playerId << " created."; } sf::Vector2f Player::getTrackablePosition() const @@ -92,3 +94,8 @@ void Player::setWorldRadius(float newWorldRadius) skinSprite->setSize(newSize); skinSprite->coordinates->setScreenOffset(IsometricCoordinates(-newSize / 2.f)); } + +Player::~Player() +{ + LOG(INFO) << "Player " << playerId << " destroyed."; +} diff --git a/src/game/player/player.hpp b/src/game/player/player.hpp index 33964a1..9a92707 100644 --- a/src/game/player/player.hpp +++ b/src/game/player/player.hpp @@ -13,6 +13,8 @@ public: Player(std::shared_ptr assignedInput, const std::string &skinRessourceName, GridCoordinates initCoordinates); + ~Player(); + void update() override; [[nodiscard]] sf::Vector2f getTrackablePosition() const override; @@ -29,13 +31,12 @@ public: [[nodiscard]] float getWorldRadius() const; + TranslatedCoordinates spawnPosition; private: std::shared_ptr input; float radiusInWorld = DEFAULT_PLAYER_RADIUS; std::shared_ptr skinSprite; - GridCoordinates spawnPosition; - int playerId; static inline int playerCreationCounter = 0; diff --git a/src/game/player/player_collection.cpp b/src/game/player/player_collection.cpp new file mode 100644 index 0000000..23118af --- /dev/null +++ b/src/game/player/player_collection.cpp @@ -0,0 +1,106 @@ +#include "player_collection.hpp" + +#include +#include "../input/input_mapper.h" +#include "../../texture_config.h" + +PlayerCollection::PlayerCollection() +{ + // Set default spawn point + setSpawnPoints({{0, 0}}); + + // Create player for existing input identities + for (auto &inputIdentity: InputMapper::getInstance()->getInputIdentities()) + { + spawnPlayer(inputIdentity); + } +} + +std::shared_ptr PlayerCollection::getInstance() +{ + if (singletonInstance == nullptr) + { + singletonInstance = std::make_shared(); + } + return singletonInstance; +} + +void PlayerCollection::addPlayer(const std::shared_ptr &player) +{ + newPlayerBuffer.push_back(player); + addChild(player); +} + +void PlayerCollection::clear() +{ + newPlayerBuffer.clear(); + removedPlayerBuffer.clear(); + + // Fill in removed players + for (auto &child: getChildren()) + { + auto player = std::dynamic_pointer_cast(child); + if (player != nullptr) + { + removedPlayerBuffer.push_back(player); + } + } + + clearChildren(); +} + +void PlayerCollection::lateUpdate() +{ + GameObject::lateUpdate(); + + newPlayerBuffer.clear(); + removedPlayerBuffer.clear(); + + // Create player for new input identities + for (auto &inputIdentity: InputMapper::getInstance()->newInputIdentities) + { + spawnPlayer(inputIdentity); + } + + // Remove players, that are not active anymore + for (auto &child: getChildren()) + { + if (child != nullptr && !child->getActive()) + { + removedPlayerBuffer.push_back(std::dynamic_pointer_cast(child)); + removeChild(child); + } + } +} + +void PlayerCollection::removePlayer(const std::shared_ptr &player) +{ + removedPlayerBuffer.push_back(player); + removeChild(player); +} + +std::vector> PlayerCollection::getNewPlayers() const +{ + return newPlayerBuffer; +} + +std::vector> PlayerCollection::getRemovedPlayers() const +{ + return removedPlayerBuffer; +} + +void PlayerCollection::setSpawnPoints(std::vector newSpawnPoints) +{ + this->spawnPoints = std::move(newSpawnPoints); + nextSpawnPointIndex = 0; +} + +void PlayerCollection::spawnPlayer(const std::shared_ptr &inputIdentity) +{ + // Get proper Spawn point, if available + auto spawn = spawnPoints[nextSpawnPointIndex]; + nextSpawnPointIndex = static_cast((nextSpawnPointIndex + 1) % spawnPoints.size()); + + auto player = std::make_shared(inputIdentity, PLAYER_SKIN, spawn); + PlayerCollection::getInstance()->addPlayer(player); +} diff --git a/src/game/player/player_collection.hpp b/src/game/player/player_collection.hpp new file mode 100644 index 0000000..8fcdcda --- /dev/null +++ b/src/game/player/player_collection.hpp @@ -0,0 +1,42 @@ +#ifndef HOLESOME_PLAYER_COLLECTION_HPP +#define HOLESOME_PLAYER_COLLECTION_HPP + + +#include "../game_object.h" +#include "player.hpp" + +class PlayerCollection : public GameObject +{ +public: + PlayerCollection(); + + static std::shared_ptr getInstance(); + + void setSpawnPoints(std::vector newSpawnPoints); + + void addPlayer(const std::shared_ptr& player); + + void removePlayer(const std::shared_ptr& player); + + std::vector> getNewPlayers() const; + + std::vector> getRemovedPlayers() const; + + void lateUpdate() override; + + void clear(); + +private: + static inline std::shared_ptr singletonInstance = nullptr; + + std::vector> newPlayerBuffer = {}; + std::vector> removedPlayerBuffer = {}; + + std::vector spawnPoints; + int nextSpawnPointIndex = 0; + + void spawnPlayer(const std::shared_ptr &inputIdentity); +}; + + +#endif //HOLESOME_PLAYER_COLLECTION_HPP diff --git a/src/game/player/player_spawner.cpp b/src/game/player/player_spawner.cpp deleted file mode 100644 index b25e6a7..0000000 --- a/src/game/player/player_spawner.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "player_spawner.hpp" -#include "player.hpp" -#include "../../texture_config.h" -#include "../physics/map/map_simulation.hpp" - -PlayerSpawner::PlayerSpawner(std::vector spawnPoints) -{ - this->spawnPoints = spawnPoints; - - // Create player for existing input identities - for (auto &inputIdentity: InputMapper::getInstance()->getInputIdentities()) - { - spawnPlayer(inputIdentity); - } -} - -void PlayerSpawner::update() -{ - // Create player for new input identities - for (auto &inputIdentity: InputMapper::getInstance()->newInputIdentities) - { - spawnPlayer(inputIdentity); - } -} - -void PlayerSpawner::spawnPlayer(const std::shared_ptr &inputIdentity) -{ - // Get proper Spawn point, if available - auto spawn = spawnPoints[nextSpawnPointIndex]; - nextSpawnPointIndex = static_cast((nextSpawnPointIndex + 1) % spawnPoints.size()); - - auto player = std::make_shared(inputIdentity, PLAYER_SKIN, spawn); - - MapSimulation::getInstance()->addPlayer(player); - Game::getInstance()->addGameObject(player); - - // TODO: Better view handling - Game::getInstance()->views[0]->addTrackable(player); -} diff --git a/src/game/player/player_spawner.hpp b/src/game/player/player_spawner.hpp deleted file mode 100644 index fd26fce..0000000 --- a/src/game/player/player_spawner.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef HOLESOME_PLAYER_SPAWNER_HPP -#define HOLESOME_PLAYER_SPAWNER_HPP - - -#include "../game_object.h" -#include "../game.h" - -class PlayerSpawner : public GameObject -{ -public: - PlayerSpawner(std::vector spawnPoints); - - void update() override; - - void spawnPlayer(const std::shared_ptr &inputIdentity); - -private: - std::vector spawnPoints; - int nextSpawnPointIndex = 0; -}; - - -#endif //HOLESOME_PLAYER_SPAWNER_HPP diff --git a/src/logging/easylogging++.h b/src/logging/easylogging++.h index 3361e23..e23c332 100644 --- a/src/logging/easylogging++.h +++ b/src/logging/easylogging++.h @@ -3870,7 +3870,7 @@ class Loggers : base::StaticClass { private: LoggingFlag m_flag; }; - /// @brief Removes flag and add it when scope goes out + /// @brief Removes flag and addPlayer it when scope goes out class ScopedRemoveFlag { public: ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { diff --git a/src/texture_config.h b/src/texture_config.h index 9bf25e1..739614b 100644 --- a/src/texture_config.h +++ b/src/texture_config.h @@ -7,7 +7,7 @@ #include "sprites/configs/sheet_config.hpp" #include "sprites/configs/sprite_config.hpp" -#define PLAYER_SKIN "hole" +#define PLAYER_SKIN "ring" /** * All textures used in the game.