#include "player_collection.hpp" #include #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::getInstance() { if (singletonInstance == nullptr) { singletonInstance = std::make_shared(); } return singletonInstance; } void PlayerCollection::addPlayer(const std::shared_ptr &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(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(child)); removeChild(child); } } } void PlayerCollection::removePlayer(const std::shared_ptr &player) { removedPlayerBuffer.push_back(player); removeChild(player); updateInputIdentityAllowance(); } std::vector> PlayerCollection::getNewPlayers() const { return newPlayerBuffer; } std::vector> PlayerCollection::getRemovedPlayers() const { return removedPlayerBuffer; } void PlayerCollection::setSpawnPoints(std::vector newSpawnPoints) { this->spawnPoints = std::move(newSpawnPoints); nextSpawnPointIndex = 0; } void PlayerCollection::spawnPlayer(const std::shared_ptr &inputIdentity) { // Get proper Spawn point, if available auto spawn = spawnPoints[nextSpawnPointIndex]; nextSpawnPointIndex = static_cast((nextSpawnPointIndex + 1) % spawnPoints.size()); auto player = std::make_shared(inputIdentity, PLAYER_SKIN, spawn); addPlayer(player); } std::vector> PlayerCollection::getPlayers() const { std::vector> players = {}; for (auto &child: getChildren()) { auto player = std::dynamic_pointer_cast(child); if (player != nullptr) { players.push_back(player); } } return players; } std::shared_ptr 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 PlayerCollection::getClosestPlayer(const TranslatedCoordinates& point) const { std::shared_ptr 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; }