165 lines
4.4 KiB
C++
165 lines
4.4 KiB
C++
#include "player_collection.hpp"
|
|
|
|
#include <utility>
|
|
#include "../input/input_mapper.h"
|
|
#include "../../texture_config.h"
|
|
|
|
PlayerCollection::PlayerCollection(int maxPlayerCount)
|
|
: maxPlayerCount(maxPlayerCount)
|
|
{
|
|
// 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> PlayerCollection::getInstance()
|
|
{
|
|
if (singletonInstance == nullptr)
|
|
{
|
|
singletonInstance = std::make_shared<PlayerCollection>();
|
|
}
|
|
return singletonInstance;
|
|
}
|
|
|
|
void PlayerCollection::addPlayer(const std::shared_ptr<Player> &player)
|
|
{
|
|
newPlayerBuffer.push_back(player);
|
|
addDetachedChild(player);
|
|
updateInputIdentityAllowance();
|
|
}
|
|
|
|
void PlayerCollection::clear()
|
|
{
|
|
newPlayerBuffer.clear();
|
|
removedPlayerBuffer.clear();
|
|
|
|
// Fill in removed players
|
|
for (auto &child: getChildren())
|
|
{
|
|
auto player = std::dynamic_pointer_cast<Player>(child);
|
|
if (player != nullptr)
|
|
{
|
|
removedPlayerBuffer.push_back(player);
|
|
}
|
|
}
|
|
|
|
clearChildren();
|
|
updateInputIdentityAllowance();
|
|
}
|
|
|
|
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<Player>(child));
|
|
removeChild(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayerCollection::removePlayer(const std::shared_ptr<Player> &player)
|
|
{
|
|
removedPlayerBuffer.push_back(player);
|
|
removeChild(player);
|
|
updateInputIdentityAllowance();
|
|
}
|
|
|
|
std::vector<std::shared_ptr<Player>> PlayerCollection::getNewPlayers() const
|
|
{
|
|
return newPlayerBuffer;
|
|
}
|
|
|
|
std::vector<std::shared_ptr<Player>> PlayerCollection::getRemovedPlayers() const
|
|
{
|
|
return removedPlayerBuffer;
|
|
}
|
|
|
|
void PlayerCollection::setSpawnPoints(std::vector<GridCoordinates> newSpawnPoints)
|
|
{
|
|
this->spawnPoints = std::move(newSpawnPoints);
|
|
nextSpawnPointIndex = 0;
|
|
}
|
|
|
|
void PlayerCollection::spawnPlayer(const std::shared_ptr<InputIdentity> &inputIdentity)
|
|
{
|
|
// Get proper Spawn point, if available
|
|
auto spawn = spawnPoints[nextSpawnPointIndex];
|
|
nextSpawnPointIndex = static_cast<int>((nextSpawnPointIndex + 1) % spawnPoints.size());
|
|
|
|
auto player = std::make_shared<Player>(inputIdentity, PLAYER_SKIN, spawn);
|
|
addPlayer(player);
|
|
}
|
|
|
|
std::vector<std::shared_ptr<Player>> PlayerCollection::getPlayers() const
|
|
{
|
|
std::vector<std::shared_ptr<Player>> players = {};
|
|
for (auto &child: getChildren())
|
|
{
|
|
auto player = std::dynamic_pointer_cast<Player>(child);
|
|
if (player != nullptr)
|
|
{
|
|
players.push_back(player);
|
|
}
|
|
}
|
|
return players;
|
|
}
|
|
|
|
std::shared_ptr<Player> PlayerCollection::getPlayerById(int playerId) const
|
|
{
|
|
for (auto &player: getPlayers())
|
|
{
|
|
if (player->getPlayerId() == playerId)
|
|
{
|
|
return player;
|
|
}
|
|
}
|
|
throw std::runtime_error("Player with id " + std::to_string(playerId) + " not found");
|
|
}
|
|
|
|
int PlayerCollection::getMaxPlayerCount() const
|
|
{
|
|
return maxPlayerCount;
|
|
}
|
|
|
|
void PlayerCollection::updateInputIdentityAllowance() const
|
|
{
|
|
InputMapper::getInstance()->allowNewInputIdentities = getPlayers().size() < maxPlayerCount;
|
|
}
|
|
|
|
std::shared_ptr<Player> PlayerCollection::getClosestPlayer(const TranslatedCoordinates& point) const
|
|
{
|
|
std::shared_ptr<Player> closestPlayer = nullptr;
|
|
float closestDistance = INFINITY;
|
|
for (auto &player: getPlayers())
|
|
{
|
|
auto playerCenterGround = player->coordinates->world().toGroundCoordinates();
|
|
auto pointCenterGround = point.world().toGroundCoordinates();
|
|
// Normalize distance by player radius to get a value below 1 for something inside the player
|
|
float distance = length(playerCenterGround - pointCenterGround) / player->getWorldRadius();
|
|
if (distance < closestDistance)
|
|
{
|
|
closestPlayer = player;
|
|
closestDistance = distance;
|
|
}
|
|
}
|
|
return closestPlayer;
|
|
}
|