holesome/src/game/player/player_collection.cpp

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;
}