Basic multiplayer view scaffolding

This commit is contained in:
Maximilian Giller 2023-06-21 16:05:11 +02:00
parent 62f69a7593
commit 1aae9e6cb6
13 changed files with 134 additions and 50 deletions

View file

@ -98,7 +98,7 @@ set(SOURCES
src/levels.hpp
src/sprites/tiling/tilemap.cpp
src/sprites/tiling/tilemap.hpp
src/sprites/tiling/tilemap_config.hpp src/sprites/tiling/tileset_config.hpp src/sprites/tiling/tileset.cpp src/sprites/tiling/tileset.hpp src/game/frame_counter.cpp src/game/frame_counter.hpp src/game/level/level_renderer.cpp src/game/level/level_renderer.hpp src/sprites/skymap/skymap.cpp src/sprites/skymap/skymap.hpp)
src/sprites/tiling/tilemap_config.hpp src/sprites/tiling/tileset_config.hpp src/sprites/tiling/tileset.cpp src/sprites/tiling/tileset.hpp src/game/frame_counter.cpp src/game/frame_counter.hpp src/game/level/level_renderer.cpp src/game/level/level_renderer.hpp src/sprites/skymap/skymap.cpp src/sprites/skymap/skymap.hpp src/game/camera/multiplayer_view.cpp src/game/camera/multiplayer_view.hpp)
set(PHYSICS_00_SOURCES
src/prototypes/physics_00.cpp)

View file

@ -4,6 +4,10 @@
- [ ] Split screen
## Bugs
- [ ] Player spawns initially at (0,0) and almost fails to jump to target spawn
## High priority
- [ ] Procedural level generation

View file

@ -24,7 +24,7 @@
#define KEY_REPEAT_ENABLED false
// Graphic settings
#define ISOMETRIC_SKEW (15.f/32.f)
#define ISOMETRIC_SKEW (16.f/32.f)
#define MOVEMENT_SKEW sf::Vector2f(1.f, 1/ISOMETRIC_SKEW/2.f)
#define WORLD_TO_ISO_SCALE 50.0f // 50.f, don't change. Rather adjust the zoom of the camera
@ -35,7 +35,8 @@
#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
#define MP_VIEW_ADD_NEW_PLAYERS true
#define MP_VIEW_REMOVE_DISCONNECTED_PLAYERS true
// Simulations
#define MAPSIM_WALL_THICKNESS 3.f

View file

@ -0,0 +1,78 @@
#include "multiplayer_view.hpp"
#include "../player/player_collection.hpp"
#include "ITrackable.h"
std::shared_ptr<MultiplayerView> MultiplayerView::getInstance()
{
if (singletonInstance == nullptr)
{
singletonInstance = std::make_shared<MultiplayerView>();
}
return singletonInstance;
}
void MultiplayerView::update()
{
// Update based on PlayerCollection
// Add new
if (MP_VIEW_ADD_NEW_PLAYERS)
{
for (const auto &player: PlayerCollection::getInstance()->getNewPlayers())
{
if (player->getTrackableState() == TrackableState::TRACKING)
{
addPlayer(player);
}
}
}
// Remove old
if (MP_VIEW_REMOVE_DISCONNECTED_PLAYERS)
{
for (const auto &player: PlayerCollection::getInstance()->getRemovedPlayers())
{
removePlayer(player);
}
}
GameObject::update();
}
void MultiplayerView::addPlayer(const std::shared_ptr<Player> &player)
{
// Player already added?
if (viewsForPlayers.find(player->getPlayerId()) != viewsForPlayers.end())
{
LOG(WARNING) << "Player " << player->getPlayerId() << " already added to MultiplayerView.";
return;
}
// Create new view
auto view = std::make_shared<TrackingView>();
view->addTrackable(player);
// TODO: Set viewport
viewsForPlayers[player->getPlayerId()] = view;
addChild(view);
}
void MultiplayerView::removePlayer(const std::shared_ptr<Player> &player)
{
// Player already removed?
if (viewsForPlayers.find(player->getPlayerId()) == viewsForPlayers.end())
{
LOG(WARNING) << "Player " << player->getPlayerId() << " already removed from MultiplayerView.";
return;
}
// Make view show all remaining players
auto view = viewsForPlayers[player->getPlayerId()];
view->removeTrackable(player);
for (const auto &remainingPlayers: PlayerCollection::getInstance()->getPlayers())
{
view->addTrackable(remainingPlayers);
}
}

View file

@ -0,0 +1,30 @@
#ifndef HOLESOME_MULTIPLAYER_VIEW_HPP
#define HOLESOME_MULTIPLAYER_VIEW_HPP
#include <map>
#include "../game_object.h"
#include "tracking_view.h"
#include "../player/player.hpp"
class MultiplayerView : public GameObject
{
public:
static std::shared_ptr<MultiplayerView> getInstance();
MultiplayerView() = default;
void update() override;
void addPlayer(const std::shared_ptr<Player>& player);
void removePlayer(const std::shared_ptr<Player>& player);
private:
static inline std::shared_ptr<MultiplayerView> singletonInstance = nullptr;
std::map<int, std::shared_ptr<TrackingView>> viewsForPlayers; // Player ID => View
};
#endif //HOLESOME_MULTIPLAYER_VIEW_HPP

View file

@ -7,9 +7,7 @@ TrackingView::TrackingView(TrackingViewOptions options) : options(options),
hasViewChanged(false),
trackables({})
{
;
marker = new CircleObject(DB_CIRCLE_RADIUS, sf::Color::Yellow);
Game::getInstance()->registerView(this);
}
TrackingView::~TrackingView()
@ -275,33 +273,6 @@ float TrackingView::getRadius(float threshold) const
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(

View file

@ -17,8 +17,6 @@ public:
~TrackingView();
void update() override;
void draw(sf::RenderWindow *window) override;
void lateUpdate() override;
@ -60,8 +58,6 @@ private:
float getRadius(float threshold) const;
sf::Vector2f getWindowSize() const;
void addPlayersDynamically();
};

View file

@ -37,11 +37,6 @@ struct TrackingViewOptions
* Value between 0 and 1 to setWorld relative padding.
*/
sf::Vector2f viewSizePadding = DEF_TV_VIEW_SIZE_PADDING;
/**
* If setWorld 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

View file

@ -123,11 +123,6 @@ std::shared_ptr<Game> Game::constructInstance(const std::shared_ptr<sf::RenderWi
return singletonInstance;
}
void Game::registerView(TrackingView *view)
{
views.push_back(view);
}
void Game::clearGameObjects()
{
gameObjects.clear();

View file

@ -32,10 +32,7 @@ public:
void addGameObject(const std::shared_ptr<GameObject>& gameObject);
void registerView(TrackingView *view);
std::shared_ptr<sf::RenderWindow> window;
std::vector<TrackingView*> views = {};
private:
static inline std::shared_ptr<Game> singletonInstance = nullptr;
std::vector<std::shared_ptr<GameObject>> gameObjects = {};

View file

@ -9,6 +9,7 @@
#include "../physics/hole/hole_depth_simulation.hpp"
#include "level_renderer.hpp"
#include "../../sprites/skymap/skymap.hpp"
#include "../camera/multiplayer_view.hpp"
void LevelLoader::loadLevel(const LevelConfig &levelConfig)
{
@ -54,7 +55,7 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig)
game->addGameObject(MapSimulation::getInstance());
// Add views
game->addGameObject(std::make_shared<TrackingView>());
game->addGameObject(std::make_shared<MultiplayerView>());
LOG(INFO) << "Finished loading level '" << levelConfig.name << "'.";
}

View file

@ -104,3 +104,17 @@ void PlayerCollection::spawnPlayer(const std::shared_ptr<InputIdentity> &inputId
auto player = std::make_shared<Player>(inputIdentity, PLAYER_SKIN, spawn);
PlayerCollection::getInstance()->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;
}

View file

@ -18,6 +18,8 @@ public:
void removePlayer(const std::shared_ptr<Player>& player);
std::vector<std::shared_ptr<Player>> getPlayers() const;
std::vector<std::shared_ptr<Player>> getNewPlayers() const;
std::vector<std::shared_ptr<Player>> getRemovedPlayers() const;