diff --git a/src/game/camera/multiplayer_view.cpp b/src/game/camera/multiplayer_view.cpp index ea91f6e..3ea46d4 100644 --- a/src/game/camera/multiplayer_view.cpp +++ b/src/game/camera/multiplayer_view.cpp @@ -51,11 +51,10 @@ void MultiplayerView::addPlayer(const std::shared_ptr &player) // Create new view auto view = std::make_shared(); view->addTrackable(player); - - // TODO: Set viewport - viewsForPlayers[player->getPlayerId()] = view; addChild(view); + + updateLayout(); } void MultiplayerView::removePlayer(const std::shared_ptr &player) @@ -76,3 +75,60 @@ void MultiplayerView::removePlayer(const std::shared_ptr &player) view->addTrackable(remainingPlayers); } } + +void MultiplayerView::updateLayout() const +{ + if (viewsForPlayers.empty()) + { + return; + } + + int viewCount = viewsForPlayers.size(); + + // Handle simple cases + if (viewCount == 1) + { + viewsForPlayers.begin()->second->setViewport({0, 0}, {1, 1}); + return; + } + if (viewCount == 2) + { + auto it = viewsForPlayers.begin(); + it->second->setViewport({0, 0}, {0.5, 1}); + it++; + it->second->setViewport({0.5, 0}, {0.5, 1}); + return; + } + + // Calculate layout + int firstRowViewCount = ceil(viewCount / 2.f); + int secondRowViewCount = viewCount - firstRowViewCount; + int index = 0; + for (auto &view: getViews()) + { + bool secondRow = index >= viewCount / 2.f; + int rowViewCount = secondRow ? secondRowViewCount : firstRowViewCount; + int rowIndexOfView = index - (secondRow ? firstRowViewCount : 0); + + view->setViewport( + { + rowIndexOfView / (float) rowViewCount, + secondRow ? 0.5f : 0 + }, { + 1.f / rowViewCount, + 0.5f + } + ); + index++; + } +} + +std::vector> MultiplayerView::getViews() const +{ + std::vector> views; + for (const auto &[_, view]: viewsForPlayers) + { + views.push_back(view); + } + return views; +} diff --git a/src/game/camera/multiplayer_view.hpp b/src/game/camera/multiplayer_view.hpp index 85ac8f7..7fcb6e7 100644 --- a/src/game/camera/multiplayer_view.hpp +++ b/src/game/camera/multiplayer_view.hpp @@ -20,10 +20,13 @@ public: void removePlayer(const std::shared_ptr& player); + std::vector> getViews() const; + private: static inline std::shared_ptr singletonInstance = nullptr; std::map> viewsForPlayers; // Player ID => View + void updateLayout() const; }; diff --git a/src/game/camera/tracking_view.cpp b/src/game/camera/tracking_view.cpp index f457c09..6f72ceb 100644 --- a/src/game/camera/tracking_view.cpp +++ b/src/game/camera/tracking_view.cpp @@ -7,6 +7,7 @@ TrackingView::TrackingView(TrackingViewOptions options) : options(options), hasViewChanged(false), trackables({}) { + initializeView(); marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow); } @@ -18,12 +19,6 @@ TrackingView::~TrackingView() void TrackingView::lateUpdate() { - // Initialize if necessary - if (view == nullptr) - { - initializeView(); - } - processTrackableStates(); if (!trackables.empty()) @@ -35,7 +30,7 @@ void TrackingView::lateUpdate() // Update window if necessary if (hasViewChanged) { - Game::getInstance()->window->setView(*this->view); + this->setViewForWindow(); hasViewChanged = false; } } @@ -281,3 +276,14 @@ void TrackingView::removeTrackable(const std::shared_ptr &trackable) return t == trackable; }), trackables.end()); } + +void TrackingView::setViewport(sf::Vector2f center, sf::Vector2f size) +{ + // TODO: Resize content for viewport + view->setViewport(sf::FloatRect(center.x, center.y, size.x, size.y)); +} + +void TrackingView::setViewForWindow() +{ + Game::getInstance()->window->setView(*this->view); +} diff --git a/src/game/camera/tracking_view.h b/src/game/camera/tracking_view.h index 581ff8e..0764df8 100644 --- a/src/game/camera/tracking_view.h +++ b/src/game/camera/tracking_view.h @@ -25,6 +25,10 @@ public: void removeTrackable(const std::shared_ptr &trackable); + void setViewport(sf::Vector2f center, sf::Vector2f size); + + void setViewForWindow(); + sf::Vector2f getSize() const; sf::Vector2f getCenter() const; diff --git a/src/game/level/level_loader.cpp b/src/game/level/level_loader.cpp index dba07a2..c4a3bfc 100644 --- a/src/game/level/level_loader.cpp +++ b/src/game/level/level_loader.cpp @@ -22,6 +22,9 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig) MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize); PlayerCollection::getInstance()->clear(); + // Add views + game->addGameObject(MultiplayerView::getInstance()); + // Add rendered level objects std::shared_ptr levelRenderer = std::make_shared(); game->addGameObject(levelRenderer); @@ -54,9 +57,6 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig) // Add physics simulations game->addGameObject(MapSimulation::getInstance()); - // Add views - game->addGameObject(std::make_shared()); - LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; } diff --git a/src/game/level/level_renderer.cpp b/src/game/level/level_renderer.cpp index 7c22f14..df84f1f 100644 --- a/src/game/level/level_renderer.cpp +++ b/src/game/level/level_renderer.cpp @@ -1 +1,12 @@ #include "level_renderer.hpp" +#include "../camera/multiplayer_view.hpp" +#include "../../logging/easylogging++.h" + +void LevelRenderer::draw(sf::RenderWindow *window) +{ + for(auto &view : MultiplayerView::getInstance()->getViews()) + { + view->setViewForWindow(); + GameObject::draw(window); + } +} diff --git a/src/game/level/level_renderer.hpp b/src/game/level/level_renderer.hpp index 96e4c7a..906c2e4 100644 --- a/src/game/level/level_renderer.hpp +++ b/src/game/level/level_renderer.hpp @@ -6,6 +6,8 @@ class LevelRenderer : public GameObject { +public: + void draw(sf::RenderWindow *window) override; };