Multiplayer viewports rendering now
This commit is contained in:
parent
1aae9e6cb6
commit
26561f5d13
7 changed files with 95 additions and 13 deletions
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 << "'.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
class LevelRenderer : public GameObject
|
class LevelRenderer : public GameObject
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
void draw(sf::RenderWindow *window) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue