holesome/src/game/physics/map/map_simulation.cpp

131 lines
3.7 KiB
C++

#include "map_simulation.hpp"
#include "../../../config.h"
#include "../../player/player_collection.hpp"
MapSimulation::MapSimulation()
{
mapPlayersById = std::map<int, std::shared_ptr<MapPlayer>>();
}
std::shared_ptr<MapSimulation> MapSimulation::getInstance()
{
if (singletonInstance == nullptr)
{
singletonInstance = std::make_shared<MapSimulation>();
}
return singletonInstance;
}
void MapSimulation::physicsUpdate()
{
// Update simulation positions
for (auto &mapPlayer: mapPlayersById)
{
mapPlayer.second->updateSimulationPosition();
}
world->Step(FRAME_TIME.asSeconds(), MAPSIM_VELOCITY_ITERATIONS, MAPSIM_POSITION_ITERATIONS);
// Update players
for (auto &mapPlayer: mapPlayersById)
{
mapPlayer.second->updatePlayer();
}
}
void MapSimulation::resetMap(sf::Vector2<int> worldMapSize)
{
// Clear all players
for (auto &[id, _]: mapPlayersById)
{
world->DestroyBody(mapPlayersById[id]->body);
}
mapPlayersById.clear();
// No gravity, since this a top-down view of the map
world = std::make_shared<b2World>(b2Vec2(0.0f, 0.0f));
// Create map borders
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)
{
b2BodyDef bodyDef;
bodyDef.type = b2_staticBody;
bodyDef.position.Set((maxX + minX) / 2.f, (maxY + minY) / 2.f);
b2Body *body = world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox((maxX - minX) / 2.f, (maxY - minY) / 2.f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape;
fixtureDef.density = 1.0f;
body->CreateFixture(&fixtureDef);
}
void MapSimulation::addPlayer(const std::shared_ptr<Player> &player)
{
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
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);
}
std::shared_ptr<MapPlayer> MapSimulation::getMapPlayerByBody(b2Body *body) const
{
for (auto &mapPlayer: mapPlayersById)
{
if (mapPlayer.second->body == body)
{
return mapPlayer.second;
}
}
return nullptr;
}
void MapSimulation::removePlayer(int playerId)
{
// Still in simulation?
if (mapPlayersById.find(playerId) == mapPlayersById.end())
{
return;
}
world->DestroyBody(mapPlayersById[playerId]->body);
mapPlayersById.erase(playerId);
}