Improved map wallout, fixed spawned player in wall glitch and now actually rendering collectables. Player handling has also been reworked
This commit is contained in:
parent
d3e6e35c9b
commit
414f3b79fc
27 changed files with 345 additions and 111 deletions
|
@ -52,8 +52,6 @@ set(SOURCES
|
|||
src/game/camera/ITrackable.h
|
||||
src/game/input/input_identity.h
|
||||
src/utilities/magic_enum.hpp
|
||||
src/game/player/player_spawner.cpp
|
||||
src/game/player/player_spawner.hpp
|
||||
src/game/camera/tracking_area.h
|
||||
src/game/camera/tracking_view_options.hpp
|
||||
src/game/collectables/collectable.cpp
|
||||
|
@ -96,7 +94,7 @@ set(SOURCES
|
|||
src/game/collectables/collection/collectables_collection.cpp
|
||||
src/game/collectables/collection/collectables_collection.hpp
|
||||
src/game/collectables/collection/collectables_depth_collection.cpp
|
||||
src/game/collectables/collection/collectables_depth_collection.hpp src/game/collectables/collectable_in_level.hpp src/game/collectables/collectable_factory.cpp src/game/collectables/collectable_factory.hpp)
|
||||
src/game/collectables/collection/collectables_depth_collection.hpp src/game/collectables/collectable_in_level.hpp src/game/collectables/collectable_factory.cpp src/game/collectables/collectable_factory.hpp src/game/player/player_collection.cpp src/game/player/player_collection.hpp)
|
||||
|
||||
set(PHYSICS_00_SOURCES
|
||||
src/prototypes/physics_00.cpp)
|
||||
|
|
|
@ -34,8 +34,10 @@
|
|||
#define DEF_TV_MIN_VIEW_SIZE sf::Vector2f(6, 6) * WORLD_TO_ISO_SCALE
|
||||
#define DEF_TV_MAX_VIEW_SIZE sf::Vector2f(0, 0)
|
||||
#define DEF_TV_VIEW_SIZE_PADDING sf::Vector2f(0.5f, 0.5f)
|
||||
#define DEF_TV_ADD_PLAYERS_DYNAMICALLY true
|
||||
|
||||
// Simulations
|
||||
#define MAPSIM_WALL_THICKNESS 3.f
|
||||
#define MAPSIM_VELOCITY_ITERATIONS 6
|
||||
#define MAPSIM_POSITION_ITERATIONS 2
|
||||
#define HOLESIM_VELOCITY_ITERATIONS 8
|
||||
|
|
|
@ -68,3 +68,8 @@ void TranslatedCoordinates::setScreenOffset(IsometricCoordinates offset)
|
|||
{
|
||||
setWorldOffset(CoordinateTransformer::isometricToWorld(offset));
|
||||
}
|
||||
|
||||
TranslatedCoordinates::TranslatedCoordinates(GridCoordinates gridCoordinates)
|
||||
{
|
||||
set(gridCoordinates);
|
||||
}
|
||||
|
|
|
@ -9,12 +9,13 @@ class TranslatedCoordinates
|
|||
{
|
||||
public:
|
||||
explicit TranslatedCoordinates(WorldCoordinates worldCoordinates);
|
||||
explicit TranslatedCoordinates(GridCoordinates gridCoordinates);
|
||||
|
||||
WorldCoordinates world() const;
|
||||
[[nodiscard]] WorldCoordinates world() const;
|
||||
|
||||
IsometricCoordinates isometric() const;
|
||||
[[nodiscard]] IsometricCoordinates isometric() const;
|
||||
|
||||
GridCoordinates grid() const;
|
||||
[[nodiscard]] GridCoordinates grid() const;
|
||||
|
||||
void set(WorldCoordinates newWorldCoordinates);
|
||||
|
||||
|
@ -35,7 +36,7 @@ public:
|
|||
void setScreenOffset(IsometricCoordinates offset);
|
||||
|
||||
private:
|
||||
WorldCoordinates worldCoordinates;
|
||||
WorldCoordinates worldCoordinates{};
|
||||
|
||||
std::shared_ptr<TranslatedCoordinates> parent = nullptr;
|
||||
};
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#include "tracking_view.h"
|
||||
#include "../../utilities/vector_utils.hpp"
|
||||
#include "../player/player_collection.hpp"
|
||||
|
||||
TrackingView::TrackingView(TrackingViewOptions options) : options(options),
|
||||
view(nullptr),
|
||||
hasViewChanged(false),
|
||||
trackables({})
|
||||
{;
|
||||
{
|
||||
;
|
||||
marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow);
|
||||
Game::getInstance()->registerView(this);
|
||||
}
|
||||
|
@ -65,7 +67,8 @@ void TrackingView::setSize(sf::Vector2f newSize)
|
|||
didAspectRationChange = true;
|
||||
}
|
||||
|
||||
if (options.softResizeSpeed != 0 && !didAspectRationChange) {
|
||||
if (options.softResizeSpeed != 0 && !didAspectRationChange)
|
||||
{
|
||||
// Smooth out transition to new size
|
||||
newSize = size + (newSize - size) * options.softResizeSpeed * FRAME_TIME.asSeconds();
|
||||
}
|
||||
|
@ -271,3 +274,39 @@ float TrackingView::getRadius(float threshold) const
|
|||
// Only half of the side, since we are calculating radius
|
||||
return smallestSide / 2.f * threshold;
|
||||
}
|
||||
|
||||
void TrackingView::update()
|
||||
{
|
||||
if (options.addPlayersDynamically)
|
||||
{
|
||||
addPlayersDynamically();
|
||||
}
|
||||
}
|
||||
|
||||
void TrackingView::addPlayersDynamically()
|
||||
{
|
||||
// Update based on PlayerCollection
|
||||
// Add new
|
||||
for (const auto &player: PlayerCollection::getInstance()->getNewPlayers())
|
||||
{
|
||||
if (player->getTrackableState() == TrackableState::TRACKING)
|
||||
{
|
||||
addTrackable(player);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old
|
||||
for (const auto &player: PlayerCollection::getInstance()->getRemovedPlayers())
|
||||
{
|
||||
removeTrackable(player);
|
||||
}
|
||||
}
|
||||
|
||||
void TrackingView::removeTrackable(const std::shared_ptr<ITrackable> &trackable)
|
||||
{
|
||||
trackables.erase(
|
||||
std::remove_if(trackables.begin(), trackables.end(), [&trackable](const std::shared_ptr<ITrackable> &t)
|
||||
{
|
||||
return t == trackable;
|
||||
}), trackables.end());
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
~TrackingView();
|
||||
|
||||
void update() override;
|
||||
|
||||
void draw(sf::RenderWindow *window) override;
|
||||
|
||||
|
@ -24,6 +25,8 @@ public:
|
|||
|
||||
void addTrackable(const std::shared_ptr<ITrackable>& trackable);
|
||||
|
||||
void removeTrackable(const std::shared_ptr<ITrackable> &trackable);
|
||||
|
||||
sf::Vector2f getSize() const;
|
||||
|
||||
sf::Vector2f getCenter() const;
|
||||
|
@ -57,6 +60,8 @@ private:
|
|||
float getRadius(float threshold) const;
|
||||
|
||||
sf::Vector2f getWindowSize() const;
|
||||
|
||||
void addPlayersDynamically();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ struct TrackingViewOptions
|
|||
* Value between 0 and 1 to set relative padding.
|
||||
*/
|
||||
sf::Vector2f viewSizePadding = DEF_TV_VIEW_SIZE_PADDING;
|
||||
|
||||
/**
|
||||
* If set to true, view will add all new players automatically and remove them accordingly, based on PlayerCollection.
|
||||
*/
|
||||
bool addPlayersDynamically = DEF_TV_ADD_PLAYERS_DYNAMICALLY;
|
||||
};
|
||||
|
||||
#endif //HOLESOME_TRACKING_VIEW_OPTIONS_HPP
|
||||
|
|
|
@ -8,11 +8,6 @@ Collectable::Collectable()
|
|||
collectableCount++;
|
||||
}
|
||||
|
||||
void Collectable::draw(sf::RenderWindow *window)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Collectable::setRotation(float angle)
|
||||
{
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ class Collectable : public GameObject
|
|||
public:
|
||||
Collectable();
|
||||
|
||||
void draw(sf::RenderWindow *window) override;
|
||||
|
||||
void setSprite(const std::string &spriteName);
|
||||
|
||||
void setRotation(float angle);
|
||||
|
|
|
@ -66,7 +66,7 @@ void CollectablesCollection::update()
|
|||
void CollectablesCollection::draw(sf::RenderWindow *window)
|
||||
{
|
||||
// Render collectables in reverse order of depth
|
||||
int maxDepth = depthCollections.size();
|
||||
int maxDepth = (int) depthCollections.size();
|
||||
for (int depth = maxDepth - 1; depth >= 0; depth--)
|
||||
{
|
||||
auto depthCollection = depthCollections.at(depth);
|
||||
|
@ -87,3 +87,14 @@ void CollectablesCollection::updateCollectables()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CollectablesDepthCollection> CollectablesCollection::getDepthCollection(int depth)
|
||||
{
|
||||
if (depthCollections.find(depth) == depthCollections.end())
|
||||
{
|
||||
LOG(ERROR) << "Depth collection for depth " << depth << " does not exist! Returning empty collection ...";
|
||||
return std::make_shared<CollectablesDepthCollection>(depth);
|
||||
}
|
||||
|
||||
return depthCollections[depth];
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ public:
|
|||
void add(const std::shared_ptr<Collectable>& collectable);
|
||||
void remove(const std::shared_ptr<Collectable>& collectable);
|
||||
|
||||
std::shared_ptr<CollectablesDepthCollection> getDepthCollection(int depth);
|
||||
|
||||
private:
|
||||
static inline std::shared_ptr<CollectablesCollection> singletonInstance = nullptr;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "game.h"
|
||||
#include "level/level_loader.hpp"
|
||||
#include "physics/map/map_simulation.hpp"
|
||||
#include "../logging/easylogging++.h"
|
||||
|
||||
Game::Game(std::shared_ptr<sf::RenderWindow> window) : window(std::move(window))
|
||||
{
|
||||
|
@ -15,6 +16,7 @@ void Game::run()
|
|||
sf::Clock clock;
|
||||
sf::Time TimeSinceLastUpdate = sf::seconds(0);
|
||||
|
||||
LOG(INFO) << "Game loop started ...";
|
||||
while (window->isOpen())
|
||||
{
|
||||
|
||||
|
@ -29,6 +31,8 @@ void Game::run()
|
|||
}
|
||||
drawFrame();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Game closing ...";
|
||||
}
|
||||
|
||||
void Game::exit()
|
||||
|
@ -83,14 +87,18 @@ void Game::update()
|
|||
}
|
||||
}
|
||||
|
||||
InputMapper::getInstance()->updateIdentities();
|
||||
|
||||
if (isLevelLoaded())
|
||||
// Physics updates
|
||||
for (const auto &gameObject: gameObjects)
|
||||
{
|
||||
MapSimulation::getInstance()->updateSimulation();
|
||||
if (gameObject->getActive())
|
||||
{
|
||||
gameObject->physicsUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
InputMapper::getInstance()->updateIdentities();
|
||||
}
|
||||
|
||||
std::shared_ptr<Game> Game::getInstance()
|
||||
{
|
||||
if (singletonInstance == nullptr)
|
||||
|
|
|
@ -57,3 +57,25 @@ void GameObject::addChild(const std::shared_ptr<GameObject> &child)
|
|||
{
|
||||
addChildWorldOffset(child, {0, 0});
|
||||
}
|
||||
|
||||
void GameObject::removeChild(const std::shared_ptr<GameObject> &child)
|
||||
{
|
||||
auto it = std::find(children.begin(), children.end(), child);
|
||||
if (it != children.end())
|
||||
{
|
||||
children.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void GameObject::clearChildren()
|
||||
{
|
||||
children.clear();
|
||||
}
|
||||
|
||||
void GameObject::physicsUpdate()
|
||||
{
|
||||
for (auto &child: children)
|
||||
{
|
||||
child->physicsUpdate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,16 @@ public:
|
|||
|
||||
virtual void lateUpdate();
|
||||
|
||||
virtual void physicsUpdate();
|
||||
|
||||
void setActive(bool active);
|
||||
bool getActive() const { return isActive; }
|
||||
|
||||
void addChildScreenOffset(const std::shared_ptr<GameObject> &child, IsometricCoordinates offset = {0, 0});
|
||||
void addChildWorldOffset(const std::shared_ptr<GameObject> &child, WorldCoordinates offset);
|
||||
void addChild(const std::shared_ptr<GameObject> &child);
|
||||
void removeChild(const std::shared_ptr<GameObject> &child);
|
||||
void clearChildren();
|
||||
[[nodiscard]] std::vector<std::shared_ptr<GameObject>> getChildren() const { return children; }
|
||||
|
||||
std::shared_ptr<TranslatedCoordinates> coordinates;
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
#include "../game.h"
|
||||
#include "../physics/map/map_simulation.hpp"
|
||||
#include "../../debug/grid_debug_layer.h"
|
||||
#include "../player/player_spawner.hpp"
|
||||
#include "../../levels.hpp"
|
||||
#include "../collectables/collection/collectables_collection.hpp"
|
||||
#include "../collectables/collectable_factory.hpp"
|
||||
#include "../player/player_collection.hpp"
|
||||
#include "../physics/hole/hole_depth_simulation.hpp"
|
||||
|
||||
void LevelLoader::loadLevel(const LevelConfig &levelConfig)
|
||||
{
|
||||
|
@ -16,6 +17,7 @@ void LevelLoader::loadLevel(const LevelConfig& levelConfig)
|
|||
|
||||
game->setLevel(levelConfig);
|
||||
MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize);
|
||||
PlayerCollection::getInstance()->clear();
|
||||
|
||||
// Add basic game objects
|
||||
if (DEVELOPER_MODE)
|
||||
|
@ -24,12 +26,14 @@ void LevelLoader::loadLevel(const LevelConfig& levelConfig)
|
|||
}
|
||||
|
||||
game->addGameObject(std::make_shared<TrackingView>());
|
||||
game->addGameObject(std::make_shared<PlayerSpawner>(levelConfig.playerSpawnPoints));
|
||||
game->addGameObject(PlayerCollection::getInstance());
|
||||
PlayerCollection::getInstance()->setSpawnPoints(levelConfig.playerSpawnPoints);
|
||||
|
||||
// Prepare collectables framework
|
||||
auto maxDepth = levelConfig.worldMapSize.x * 2;
|
||||
CollectablesCollection::getInstance()->createEmpty(maxDepth);
|
||||
game->addGameObject(CollectablesCollection::getInstance());
|
||||
auto maxDepth = (int) levelConfig.worldMapSize.x * 2;
|
||||
auto collectablesCollection = CollectablesCollection::getInstance();
|
||||
collectablesCollection->createEmpty(maxDepth);
|
||||
game->addGameObject(collectablesCollection);
|
||||
|
||||
// Spawn collectibles
|
||||
for (auto const &collectableInfo: levelConfig.collectables)
|
||||
|
@ -37,6 +41,15 @@ void LevelLoader::loadLevel(const LevelConfig& levelConfig)
|
|||
spawnCollectable(collectableInfo);
|
||||
}
|
||||
|
||||
// Add physics simulations
|
||||
game->addGameObject(MapSimulation::getInstance());
|
||||
// For every depth, add a hole depth simulation
|
||||
for (int depth = 0; depth < maxDepth; depth++)
|
||||
{
|
||||
auto depthCollection = collectablesCollection->getDepthCollection(depth);
|
||||
game->addGameObject(std::make_shared<HoleDepthSimulation>(depthCollection));
|
||||
}
|
||||
|
||||
LOG(INFO) << "Finished loading level '" << levelConfig.name << "'.";
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ HoleDepthSimulation::HoleDepthSimulation(std::shared_ptr<CollectablesDepthCollec
|
|||
simWorld = std::make_shared<b2World>(WORLD_GRAVITY);
|
||||
}
|
||||
|
||||
void HoleDepthSimulation::updateSimulation()
|
||||
void HoleDepthSimulation::physicsUpdate()
|
||||
{
|
||||
updateBodiesFromCollectionHistory();
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
/**
|
||||
* @brief Simulates the hole(s) for the specific depth
|
||||
*/
|
||||
class HoleDepthSimulation
|
||||
class HoleDepthSimulation : public GameObject
|
||||
{
|
||||
public:
|
||||
HoleDepthSimulation(std::shared_ptr<CollectablesDepthCollection> collectables);
|
||||
explicit HoleDepthSimulation(std::shared_ptr<CollectablesDepthCollection> collectables);
|
||||
|
||||
void updateSimulation();
|
||||
void physicsUpdate() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<CollectablesDepthCollection> collectables;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "map_simulation.hpp"
|
||||
#include "../../../config.h"
|
||||
#include "../../player/player_collection.hpp"
|
||||
|
||||
MapSimulation::MapSimulation()
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ std::shared_ptr<MapSimulation> MapSimulation::getInstance()
|
|||
return singletonInstance;
|
||||
}
|
||||
|
||||
void MapSimulation::updateSimulation()
|
||||
void MapSimulation::physicsUpdate()
|
||||
{
|
||||
// Update simulation positions
|
||||
for (auto &mapPlayer: mapPlayersById)
|
||||
|
@ -34,15 +35,20 @@ void MapSimulation::updateSimulation()
|
|||
|
||||
void MapSimulation::resetMap(sf::Vector2f worldMapSize)
|
||||
{
|
||||
// Clear all players
|
||||
for (auto &mapPlayer: mapPlayersById)
|
||||
{
|
||||
removePlayer(mapPlayer.second->player);
|
||||
}
|
||||
|
||||
// No gravity, since this a top-down view of the map
|
||||
world = std::make_shared<b2World>(b2Vec2(0.0f, 0.0f));
|
||||
mapPlayersById.clear();
|
||||
|
||||
// Create map borders
|
||||
constructSquareObstacle(-1, 0, 0, worldMapSize.y);
|
||||
constructSquareObstacle(0, -1, worldMapSize.x, 0);
|
||||
constructSquareObstacle(worldMapSize.x, 0, worldMapSize.x + 1, worldMapSize.y);
|
||||
constructSquareObstacle(0, worldMapSize.y, worldMapSize.x, worldMapSize.y + 1);
|
||||
constructSquareObstacle(-MAPSIM_WALL_THICKNESS, -MAPSIM_WALL_THICKNESS, 0, worldMapSize.y + MAPSIM_WALL_THICKNESS); // Bottom left
|
||||
constructSquareObstacle(0, -MAPSIM_WALL_THICKNESS, worldMapSize.x, 0); // Bottom right
|
||||
constructSquareObstacle(worldMapSize.x, -MAPSIM_WALL_THICKNESS, worldMapSize.x + MAPSIM_WALL_THICKNESS, worldMapSize.y + MAPSIM_WALL_THICKNESS); // Top right
|
||||
constructSquareObstacle(0, worldMapSize.y, worldMapSize.x, worldMapSize.y + MAPSIM_WALL_THICKNESS); // Top left
|
||||
}
|
||||
|
||||
void MapSimulation::constructSquareObstacle(float minX, float minY, float maxX, float maxY)
|
||||
|
@ -66,7 +72,30 @@ void MapSimulation::addPlayer(const std::shared_ptr<Player>& player)
|
|||
{
|
||||
b2BodyDef bodyDef;
|
||||
bodyDef.type = b2_dynamicBody;
|
||||
bodyDef.position.Set(player->coordinates->world().x, player->coordinates->world().y);
|
||||
bodyDef.position.Set(player->spawnPosition.world().x, player->spawnPosition.world().y);
|
||||
b2Body *body = world->CreateBody(&bodyDef);
|
||||
mapPlayersById[player->getPlayerId()] = std::make_shared<MapPlayer>(player, body);
|
||||
}
|
||||
|
||||
void MapSimulation::update()
|
||||
{
|
||||
// Update players from player collection
|
||||
// New player
|
||||
for (auto &player: PlayerCollection::getInstance()->getNewPlayers())
|
||||
{
|
||||
addPlayer(player);
|
||||
}
|
||||
// Removed players
|
||||
for (auto &player: PlayerCollection::getInstance()->getRemovedPlayers())
|
||||
{
|
||||
removePlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
void MapSimulation::removePlayer(std::shared_ptr<Player> &player)
|
||||
{
|
||||
// Remove body from simulation
|
||||
int playerId = player->getPlayerId();
|
||||
world->DestroyBody(mapPlayersById[playerId]->body);
|
||||
mapPlayersById.erase(playerId);
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
#include "../../player/player.hpp"
|
||||
#include "map_player.hpp"
|
||||
|
||||
class MapSimulation
|
||||
class MapSimulation : public GameObject
|
||||
{
|
||||
public:
|
||||
MapSimulation();
|
||||
|
||||
void updateSimulation();
|
||||
void update() override;
|
||||
|
||||
void physicsUpdate() override;
|
||||
|
||||
void resetMap(sf::Vector2f worldMapSize);
|
||||
|
||||
|
@ -29,6 +31,7 @@ private:
|
|||
|
||||
void constructSquareObstacle(float minX, float minY, float maxX, float maxY);
|
||||
|
||||
void removePlayer(std::shared_ptr<Player> &player);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
#include "player.hpp"
|
||||
#include "../../config.h"
|
||||
#include "../../logging/easylogging++.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
Player::Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &skinRessourceName,
|
||||
GridCoordinates initCoordinates)
|
||||
: spawnPosition(initCoordinates)
|
||||
{
|
||||
playerId = playerCreationCounter++;
|
||||
this->spawnPosition = initCoordinates;
|
||||
coordinates->set(initCoordinates);
|
||||
coordinates->set(spawnPosition);
|
||||
|
||||
input = std::move(assignedInput);
|
||||
|
||||
skinSprite = std::make_shared<VersatileSprite>(skinRessourceName, getIsoSize());
|
||||
addChildScreenOffset(skinSprite, IsometricCoordinates(-getIsoSize() / 2.f));
|
||||
|
||||
LOG(INFO) << "Player " << playerId << " created.";
|
||||
}
|
||||
|
||||
sf::Vector2f Player::getTrackablePosition() const
|
||||
|
@ -92,3 +94,8 @@ void Player::setWorldRadius(float newWorldRadius)
|
|||
skinSprite->setSize(newSize);
|
||||
skinSprite->coordinates->setScreenOffset(IsometricCoordinates(-newSize / 2.f));
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
LOG(INFO) << "Player " << playerId << " destroyed.";
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ public:
|
|||
Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &skinRessourceName,
|
||||
GridCoordinates initCoordinates);
|
||||
|
||||
~Player();
|
||||
|
||||
void update() override;
|
||||
|
||||
[[nodiscard]] sf::Vector2f getTrackablePosition() const override;
|
||||
|
@ -29,13 +31,12 @@ public:
|
|||
|
||||
[[nodiscard]] float getWorldRadius() const;
|
||||
|
||||
TranslatedCoordinates spawnPosition;
|
||||
private:
|
||||
std::shared_ptr<InputIdentity> input;
|
||||
float radiusInWorld = DEFAULT_PLAYER_RADIUS;
|
||||
std::shared_ptr<VersatileSprite> skinSprite;
|
||||
|
||||
GridCoordinates spawnPosition;
|
||||
|
||||
int playerId;
|
||||
static inline int playerCreationCounter = 0;
|
||||
|
||||
|
|
106
src/game/player/player_collection.cpp
Normal file
106
src/game/player/player_collection.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include "player_collection.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include "../input/input_mapper.h"
|
||||
#include "../../texture_config.h"
|
||||
|
||||
PlayerCollection::PlayerCollection()
|
||||
{
|
||||
// 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);
|
||||
addChild(player);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
PlayerCollection::getInstance()->addPlayer(player);
|
||||
}
|
42
src/game/player/player_collection.hpp
Normal file
42
src/game/player/player_collection.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef HOLESOME_PLAYER_COLLECTION_HPP
|
||||
#define HOLESOME_PLAYER_COLLECTION_HPP
|
||||
|
||||
|
||||
#include "../game_object.h"
|
||||
#include "player.hpp"
|
||||
|
||||
class PlayerCollection : public GameObject
|
||||
{
|
||||
public:
|
||||
PlayerCollection();
|
||||
|
||||
static std::shared_ptr<PlayerCollection> getInstance();
|
||||
|
||||
void setSpawnPoints(std::vector<GridCoordinates> newSpawnPoints);
|
||||
|
||||
void addPlayer(const std::shared_ptr<Player>& player);
|
||||
|
||||
void removePlayer(const std::shared_ptr<Player>& player);
|
||||
|
||||
std::vector<std::shared_ptr<Player>> getNewPlayers() const;
|
||||
|
||||
std::vector<std::shared_ptr<Player>> getRemovedPlayers() const;
|
||||
|
||||
void lateUpdate() override;
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
static inline std::shared_ptr<PlayerCollection> singletonInstance = nullptr;
|
||||
|
||||
std::vector<std::shared_ptr<Player>> newPlayerBuffer = {};
|
||||
std::vector<std::shared_ptr<Player>> removedPlayerBuffer = {};
|
||||
|
||||
std::vector<GridCoordinates> spawnPoints;
|
||||
int nextSpawnPointIndex = 0;
|
||||
|
||||
void spawnPlayer(const std::shared_ptr<InputIdentity> &inputIdentity);
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_PLAYER_COLLECTION_HPP
|
|
@ -1,39 +0,0 @@
|
|||
#include "player_spawner.hpp"
|
||||
#include "player.hpp"
|
||||
#include "../../texture_config.h"
|
||||
#include "../physics/map/map_simulation.hpp"
|
||||
|
||||
PlayerSpawner::PlayerSpawner(std::vector<GridCoordinates> spawnPoints)
|
||||
{
|
||||
this->spawnPoints = spawnPoints;
|
||||
|
||||
// Create player for existing input identities
|
||||
for (auto &inputIdentity: InputMapper::getInstance()->getInputIdentities())
|
||||
{
|
||||
spawnPlayer(inputIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSpawner::update()
|
||||
{
|
||||
// Create player for new input identities
|
||||
for (auto &inputIdentity: InputMapper::getInstance()->newInputIdentities)
|
||||
{
|
||||
spawnPlayer(inputIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSpawner::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);
|
||||
|
||||
MapSimulation::getInstance()->addPlayer(player);
|
||||
Game::getInstance()->addGameObject(player);
|
||||
|
||||
// TODO: Better view handling
|
||||
Game::getInstance()->views[0]->addTrackable(player);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef HOLESOME_PLAYER_SPAWNER_HPP
|
||||
#define HOLESOME_PLAYER_SPAWNER_HPP
|
||||
|
||||
|
||||
#include "../game_object.h"
|
||||
#include "../game.h"
|
||||
|
||||
class PlayerSpawner : public GameObject
|
||||
{
|
||||
public:
|
||||
PlayerSpawner(std::vector<GridCoordinates> spawnPoints);
|
||||
|
||||
void update() override;
|
||||
|
||||
void spawnPlayer(const std::shared_ptr<InputIdentity> &inputIdentity);
|
||||
|
||||
private:
|
||||
std::vector<GridCoordinates> spawnPoints;
|
||||
int nextSpawnPointIndex = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif //HOLESOME_PLAYER_SPAWNER_HPP
|
|
@ -3870,7 +3870,7 @@ class Loggers : base::StaticClass {
|
|||
private:
|
||||
LoggingFlag m_flag;
|
||||
};
|
||||
/// @brief Removes flag and add it when scope goes out
|
||||
/// @brief Removes flag and addPlayer it when scope goes out
|
||||
class ScopedRemoveFlag {
|
||||
public:
|
||||
ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "sprites/configs/sheet_config.hpp"
|
||||
#include "sprites/configs/sprite_config.hpp"
|
||||
|
||||
#define PLAYER_SKIN "hole"
|
||||
#define PLAYER_SKIN "ring"
|
||||
|
||||
/**
|
||||
* All textures used in the game.
|
||||
|
|
Loading…
Reference in a new issue