From 1aae9e6cb601834e442db35f20503a18a4335523 Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Wed, 21 Jun 2023 16:05:11 +0200 Subject: [PATCH] Basic multiplayer view scaffolding --- CMakeLists.txt | 2 +- TODO.md | 4 ++ src/config.h | 5 +- src/game/camera/multiplayer_view.cpp | 78 +++++++++++++++++++++++ src/game/camera/multiplayer_view.hpp | 30 +++++++++ src/game/camera/tracking_view.cpp | 29 --------- src/game/camera/tracking_view.h | 4 -- src/game/camera/tracking_view_options.hpp | 5 -- src/game/game.cpp | 5 -- src/game/game.h | 3 - src/game/level/level_loader.cpp | 3 +- src/game/player/player_collection.cpp | 14 ++++ src/game/player/player_collection.hpp | 2 + 13 files changed, 134 insertions(+), 50 deletions(-) create mode 100644 src/game/camera/multiplayer_view.cpp create mode 100644 src/game/camera/multiplayer_view.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c9a883..d5e9b16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ set(SOURCES src/levels.hpp src/sprites/tiling/tilemap.cpp src/sprites/tiling/tilemap.hpp - src/sprites/tiling/tilemap_config.hpp src/sprites/tiling/tileset_config.hpp src/sprites/tiling/tileset.cpp src/sprites/tiling/tileset.hpp src/game/frame_counter.cpp src/game/frame_counter.hpp src/game/level/level_renderer.cpp src/game/level/level_renderer.hpp src/sprites/skymap/skymap.cpp src/sprites/skymap/skymap.hpp) + src/sprites/tiling/tilemap_config.hpp src/sprites/tiling/tileset_config.hpp src/sprites/tiling/tileset.cpp src/sprites/tiling/tileset.hpp src/game/frame_counter.cpp src/game/frame_counter.hpp src/game/level/level_renderer.cpp src/game/level/level_renderer.hpp src/sprites/skymap/skymap.cpp src/sprites/skymap/skymap.hpp src/game/camera/multiplayer_view.cpp src/game/camera/multiplayer_view.hpp) set(PHYSICS_00_SOURCES src/prototypes/physics_00.cpp) diff --git a/TODO.md b/TODO.md index 30e5138..1eb2159 100644 --- a/TODO.md +++ b/TODO.md @@ -4,6 +4,10 @@ - [ ] Split screen +## Bugs + +- [ ] Player spawns initially at (0,0) and almost fails to jump to target spawn + ## High priority - [ ] Procedural level generation diff --git a/src/config.h b/src/config.h index 85f0e82..8751436 100644 --- a/src/config.h +++ b/src/config.h @@ -24,7 +24,7 @@ #define KEY_REPEAT_ENABLED false // Graphic settings -#define ISOMETRIC_SKEW (15.f/32.f) +#define ISOMETRIC_SKEW (16.f/32.f) #define MOVEMENT_SKEW sf::Vector2f(1.f, 1/ISOMETRIC_SKEW/2.f) #define WORLD_TO_ISO_SCALE 50.0f // 50.f, don't change. Rather adjust the zoom of the camera @@ -35,7 +35,8 @@ #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 +#define MP_VIEW_ADD_NEW_PLAYERS true +#define MP_VIEW_REMOVE_DISCONNECTED_PLAYERS true // Simulations #define MAPSIM_WALL_THICKNESS 3.f diff --git a/src/game/camera/multiplayer_view.cpp b/src/game/camera/multiplayer_view.cpp new file mode 100644 index 0000000..ea91f6e --- /dev/null +++ b/src/game/camera/multiplayer_view.cpp @@ -0,0 +1,78 @@ +#include "multiplayer_view.hpp" +#include "../player/player_collection.hpp" +#include "ITrackable.h" + +std::shared_ptr MultiplayerView::getInstance() +{ + if (singletonInstance == nullptr) + { + singletonInstance = std::make_shared(); + } + + return singletonInstance; +} + +void MultiplayerView::update() +{ + // Update based on PlayerCollection + // Add new + if (MP_VIEW_ADD_NEW_PLAYERS) + { + for (const auto &player: PlayerCollection::getInstance()->getNewPlayers()) + { + if (player->getTrackableState() == TrackableState::TRACKING) + { + addPlayer(player); + } + } + } + + // Remove old + if (MP_VIEW_REMOVE_DISCONNECTED_PLAYERS) + { + for (const auto &player: PlayerCollection::getInstance()->getRemovedPlayers()) + { + removePlayer(player); + } + } + + GameObject::update(); +} + +void MultiplayerView::addPlayer(const std::shared_ptr &player) +{ + // Player already added? + if (viewsForPlayers.find(player->getPlayerId()) != viewsForPlayers.end()) + { + LOG(WARNING) << "Player " << player->getPlayerId() << " already added to MultiplayerView."; + return; + } + + // Create new view + auto view = std::make_shared(); + view->addTrackable(player); + + // TODO: Set viewport + + viewsForPlayers[player->getPlayerId()] = view; + addChild(view); +} + +void MultiplayerView::removePlayer(const std::shared_ptr &player) +{ + // Player already removed? + if (viewsForPlayers.find(player->getPlayerId()) == viewsForPlayers.end()) + { + LOG(WARNING) << "Player " << player->getPlayerId() << " already removed from MultiplayerView."; + return; + } + + // Make view show all remaining players + auto view = viewsForPlayers[player->getPlayerId()]; + view->removeTrackable(player); + + for (const auto &remainingPlayers: PlayerCollection::getInstance()->getPlayers()) + { + view->addTrackable(remainingPlayers); + } +} diff --git a/src/game/camera/multiplayer_view.hpp b/src/game/camera/multiplayer_view.hpp new file mode 100644 index 0000000..85ac8f7 --- /dev/null +++ b/src/game/camera/multiplayer_view.hpp @@ -0,0 +1,30 @@ +#ifndef HOLESOME_MULTIPLAYER_VIEW_HPP +#define HOLESOME_MULTIPLAYER_VIEW_HPP + + +#include +#include "../game_object.h" +#include "tracking_view.h" +#include "../player/player.hpp" + +class MultiplayerView : public GameObject +{ +public: + static std::shared_ptr getInstance(); + + MultiplayerView() = default; + + void update() override; + + void addPlayer(const std::shared_ptr& player); + + void removePlayer(const std::shared_ptr& player); + +private: + static inline std::shared_ptr singletonInstance = nullptr; + + std::map> viewsForPlayers; // Player ID => View +}; + + +#endif //HOLESOME_MULTIPLAYER_VIEW_HPP diff --git a/src/game/camera/tracking_view.cpp b/src/game/camera/tracking_view.cpp index 4c27e39..f457c09 100644 --- a/src/game/camera/tracking_view.cpp +++ b/src/game/camera/tracking_view.cpp @@ -7,9 +7,7 @@ TrackingView::TrackingView(TrackingViewOptions options) : options(options), hasViewChanged(false), trackables({}) { - ; marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow); - Game::getInstance()->registerView(this); } TrackingView::~TrackingView() @@ -275,33 +273,6 @@ float TrackingView::getRadius(float threshold) const 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( diff --git a/src/game/camera/tracking_view.h b/src/game/camera/tracking_view.h index 3bc9823..581ff8e 100644 --- a/src/game/camera/tracking_view.h +++ b/src/game/camera/tracking_view.h @@ -17,8 +17,6 @@ public: ~TrackingView(); - void update() override; - void draw(sf::RenderWindow *window) override; void lateUpdate() override; @@ -60,8 +58,6 @@ 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 9f2bd11..955ae82 100644 --- a/src/game/camera/tracking_view_options.hpp +++ b/src/game/camera/tracking_view_options.hpp @@ -37,11 +37,6 @@ struct TrackingViewOptions * Value between 0 and 1 to setWorld relative padding. */ sf::Vector2f viewSizePadding = DEF_TV_VIEW_SIZE_PADDING; - - /** - * If setWorld 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/game.cpp b/src/game/game.cpp index dc7333d..581cd51 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -123,11 +123,6 @@ std::shared_ptr Game::constructInstance(const std::shared_ptr& gameObject); - void registerView(TrackingView *view); - std::shared_ptr window; - std::vector views = {}; private: static inline std::shared_ptr singletonInstance = nullptr; std::vector> gameObjects = {}; diff --git a/src/game/level/level_loader.cpp b/src/game/level/level_loader.cpp index 56dd31d..dba07a2 100644 --- a/src/game/level/level_loader.cpp +++ b/src/game/level/level_loader.cpp @@ -9,6 +9,7 @@ #include "../physics/hole/hole_depth_simulation.hpp" #include "level_renderer.hpp" #include "../../sprites/skymap/skymap.hpp" +#include "../camera/multiplayer_view.hpp" void LevelLoader::loadLevel(const LevelConfig &levelConfig) { @@ -54,7 +55,7 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig) game->addGameObject(MapSimulation::getInstance()); // Add views - game->addGameObject(std::make_shared()); + game->addGameObject(std::make_shared()); LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; } diff --git a/src/game/player/player_collection.cpp b/src/game/player/player_collection.cpp index 23118af..26aadda 100644 --- a/src/game/player/player_collection.cpp +++ b/src/game/player/player_collection.cpp @@ -104,3 +104,17 @@ void PlayerCollection::spawnPlayer(const std::shared_ptr &inputId auto player = std::make_shared(inputIdentity, PLAYER_SKIN, spawn); PlayerCollection::getInstance()->addPlayer(player); } + +std::vector> PlayerCollection::getPlayers() const +{ + std::vector> players = {}; + for (auto &child: getChildren()) + { + auto player = std::dynamic_pointer_cast(child); + if (player != nullptr) + { + players.push_back(player); + } + } + return players; +} diff --git a/src/game/player/player_collection.hpp b/src/game/player/player_collection.hpp index 8fcdcda..2d7ef8f 100644 --- a/src/game/player/player_collection.hpp +++ b/src/game/player/player_collection.hpp @@ -18,6 +18,8 @@ public: void removePlayer(const std::shared_ptr& player); + std::vector> getPlayers() const; + std::vector> getNewPlayers() const; std::vector> getRemovedPlayers() const;