Multiplayer viewports rendering now

This commit is contained in:
Maximilian Giller 2023-06-21 20:42:42 +02:00
parent 1aae9e6cb6
commit 26561f5d13
7 changed files with 95 additions and 13 deletions

View file

@ -51,11 +51,10 @@ void MultiplayerView::addPlayer(const std::shared_ptr<Player> &player)
// Create new view // Create new view
auto view = std::make_shared<TrackingView>(); auto view = std::make_shared<TrackingView>();
view->addTrackable(player); view->addTrackable(player);
// TODO: Set viewport
viewsForPlayers[player->getPlayerId()] = view; viewsForPlayers[player->getPlayerId()] = view;
addChild(view); addChild(view);
updateLayout();
} }
void MultiplayerView::removePlayer(const std::shared_ptr<Player> &player) void MultiplayerView::removePlayer(const std::shared_ptr<Player> &player)
@ -76,3 +75,60 @@ void MultiplayerView::removePlayer(const std::shared_ptr<Player> &player)
view->addTrackable(remainingPlayers); 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<std::shared_ptr<TrackingView>> MultiplayerView::getViews() const
{
std::vector<std::shared_ptr<TrackingView>> views;
for (const auto &[_, view]: viewsForPlayers)
{
views.push_back(view);
}
return views;
}

View file

@ -20,10 +20,13 @@ public:
void removePlayer(const std::shared_ptr<Player>& player); void removePlayer(const std::shared_ptr<Player>& player);
std::vector<std::shared_ptr<TrackingView>> getViews() const;
private: private:
static inline std::shared_ptr<MultiplayerView> singletonInstance = nullptr; static inline std::shared_ptr<MultiplayerView> singletonInstance = nullptr;
std::map<int, std::shared_ptr<TrackingView>> viewsForPlayers; // Player ID => View std::map<int, std::shared_ptr<TrackingView>> viewsForPlayers; // Player ID => View
void updateLayout() const;
}; };

View file

@ -7,6 +7,7 @@ TrackingView::TrackingView(TrackingViewOptions options) : options(options),
hasViewChanged(false), hasViewChanged(false),
trackables({}) trackables({})
{ {
initializeView();
marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow); marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow);
} }
@ -18,12 +19,6 @@ TrackingView::~TrackingView()
void TrackingView::lateUpdate() void TrackingView::lateUpdate()
{ {
// Initialize if necessary
if (view == nullptr)
{
initializeView();
}
processTrackableStates(); processTrackableStates();
if (!trackables.empty()) if (!trackables.empty())
@ -35,7 +30,7 @@ void TrackingView::lateUpdate()
// Update window if necessary // Update window if necessary
if (hasViewChanged) if (hasViewChanged)
{ {
Game::getInstance()->window->setView(*this->view); this->setViewForWindow();
hasViewChanged = false; hasViewChanged = false;
} }
} }
@ -281,3 +276,14 @@ void TrackingView::removeTrackable(const std::shared_ptr<ITrackable> &trackable)
return t == trackable; return t == trackable;
}), trackables.end()); }), 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);
}

View file

@ -25,6 +25,10 @@ public:
void removeTrackable(const std::shared_ptr<ITrackable> &trackable); void removeTrackable(const std::shared_ptr<ITrackable> &trackable);
void setViewport(sf::Vector2f center, sf::Vector2f size);
void setViewForWindow();
sf::Vector2f getSize() const; sf::Vector2f getSize() const;
sf::Vector2f getCenter() const; sf::Vector2f getCenter() const;

View file

@ -22,6 +22,9 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig)
MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize); MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize);
PlayerCollection::getInstance()->clear(); PlayerCollection::getInstance()->clear();
// Add views
game->addGameObject(MultiplayerView::getInstance());
// Add rendered level objects // Add rendered level objects
std::shared_ptr<LevelRenderer> levelRenderer = std::make_shared<LevelRenderer>(); std::shared_ptr<LevelRenderer> levelRenderer = std::make_shared<LevelRenderer>();
game->addGameObject(levelRenderer); game->addGameObject(levelRenderer);
@ -54,9 +57,6 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig)
// Add physics simulations // Add physics simulations
game->addGameObject(MapSimulation::getInstance()); game->addGameObject(MapSimulation::getInstance());
// Add views
game->addGameObject(std::make_shared<MultiplayerView>());
LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; LOG(INFO) << "Finished loading level '" << levelConfig.name << "'.";
} }

View file

@ -1 +1,12 @@
#include "level_renderer.hpp" #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);
}
}

View file

@ -6,6 +6,8 @@
class LevelRenderer : public GameObject class LevelRenderer : public GameObject
{ {
public:
void draw(sf::RenderWindow *window) override;
}; };