diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b6338..cc6fea8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,16 +87,36 @@ set(SOURCES src/game/level/level_loader.hpp src/levels.hpp src/collectables.hpp src/game/collectables/collectable_config.hpp - src/game/physics/hole/hole_depth_simulation.cpp - src/game/physics/hole/hole_depth_simulation.hpp 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/player/player_collection.cpp src/game/player/player_collection.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 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/game/camera/multiplayer_view.cpp src/game/camera/multiplayer_view.hpp src/game/camera/multiplayer_borders.cpp src/game/camera/multiplayer_borders.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 + src/game/camera/multiplayer_borders.cpp + src/game/camera/multiplayer_borders.hpp + src/game/physics/holes/collectable_simulation.cpp + src/game/physics/holes/collectable_simulation.hpp + src/game/physics/holes/holes_simulation.cpp + src/game/physics/holes/holes_simulation.hpp src/game/physics/holes/layouts/hole_description.hpp src/game/physics/holes/layouts/hole_layout.cpp src/game/physics/holes/layouts/hole_layout.hpp src/game/physics/holes/layouts/depth_hole_layout.hpp src/game/physics/holes/layouts/depth_hole_description.hpp) set(PHYSICS_00_SOURCES src/prototypes/physics_00.cpp) diff --git a/README.md b/README.md index 557a4ce..5ef33a3 100644 --- a/README.md +++ b/README.md @@ -68,3 +68,10 @@ In case of "RandR headers were not found": `sudo apt install xorg-dev`. cmake --build . cmake --build . --target INSTALL ``` + +## Project structure + +- Physics Simulations + - **Map Simulation**: World-bounds collider + - **Holes Simulation**: Creates hole physics by managing all the individual Collectable Simulations + - **Collectable Simulation**: Simulates physics for a single collectable diff --git a/TODO.md b/TODO.md index bfadb70..9622f7e 100644 --- a/TODO.md +++ b/TODO.md @@ -18,6 +18,7 @@ - Game over screen - Proper player graphics - Collectables with graphics +- In-View-Detection for rendering more efficiently ## Low priority diff --git a/src/config.h b/src/config.h index 905e599..72edde3 100644 --- a/src/config.h +++ b/src/config.h @@ -13,7 +13,7 @@ #define PLAYER_RADIUS_PER_LEVEL 0.25f // World -#define WORLD_GRAVITY b2Vec2(0.f, 9.8f) +#define WORLD_GRAVITY b2Vec2(0.f, -9.8f) #define SKY_HEIGHT_SCALE 2.f // FPS @@ -44,13 +44,14 @@ #define MAPSIM_WALL_THICKNESS 3.f #define MAPSIM_VELOCITY_ITERATIONS 6 #define MAPSIM_POSITION_ITERATIONS 2 -#define HOLESIM_VELOCITY_ITERATIONS 8 -#define HOLESIM_POSITION_ITERATIONS 3 -#define HOLESIM_COLLECTABLE_LINEAR_DAMPING 0.5f -#define HOLESIM_COLLECTABLE_ANGULAR_DAMPING 0.5f -#define HOLESIM_COLLECTABLE_DENSITY 1.f -#define HOLESIM_COLLECTABLE_FRICTION 0.3f -#define HOLESIM_COLLECTABLE_RESTITUTION 0.5f +#define COLLECTABLES_SIM_VELOCITY_ITERATIONS 8 +#define COLLECTABLES_SIM_POSITION_ITERATIONS 3 +#define COLLECTABLES_SIM_LINEAR_DAMPING 0.5f +#define COLLECTABLES_SIM_ANGULAR_DAMPING 0.5f +#define COLLECTABLES_SIM_DENSITY 1.f +#define COLLECTABLES_SIM_FRICTION 0.3f +#define COLLECTABLES_SIM_RESTITUTION 0.5f +#define COLLECTABLES_SIM_SLEEPING true // Directions #define DIRECTION_HARD_ACTIVATION_THRESHOLD 0.1f diff --git a/src/game/level/level_loader.cpp b/src/game/level/level_loader.cpp index c4a3bfc..f117449 100644 --- a/src/game/level/level_loader.cpp +++ b/src/game/level/level_loader.cpp @@ -6,10 +6,11 @@ #include "../collectables/collection/collectables_collection.hpp" #include "../collectables/collectable_factory.hpp" #include "../player/player_collection.hpp" -#include "../physics/hole/hole_depth_simulation.hpp" #include "level_renderer.hpp" #include "../../sprites/skymap/skymap.hpp" #include "../camera/multiplayer_view.hpp" +#include "../physics/holes/holes_simulation.hpp" +#include "../physics/holes/layouts/hole_layout.hpp" void LevelLoader::loadLevel(const LevelConfig &levelConfig) { @@ -20,7 +21,9 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig) game->setLevel(levelConfig); MapSimulation::getInstance()->resetMap(levelConfig.worldMapSize); + HolesSimulation::getInstance()->clear(); PlayerCollection::getInstance()->clear(); + HoleLayout::getInstance()->clear(); // Add views game->addGameObject(MultiplayerView::getInstance()); @@ -46,6 +49,11 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig) collectablesCollection->createEmpty(maxDepth); levelRenderer->addChild(collectablesCollection); + // Add physics simulations + game->addGameObject(MapSimulation::getInstance()); + game->addGameObject(HolesSimulation::getInstance()); + game->addGameObject(HoleLayout::getInstance()); + // Spawn collectibles for (auto const &collectableInfo: levelConfig.collectables) { @@ -54,9 +62,6 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig) - // Add physics simulations - game->addGameObject(MapSimulation::getInstance()); - LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; } @@ -78,4 +83,5 @@ void LevelLoader::spawnCollectable(const CollectableInLevel &collectableInfo) auto collectable = CollectableFactory::createFromInLevelConfig(collectableInfo); LOG(DEBUG) << "Has depth " << collectable->getDepth() << "."; CollectablesCollection::getInstance()->add(collectable); + HolesSimulation::getInstance()->addCollectable(collectable); } diff --git a/src/game/physics/hole/hole_depth_simulation.cpp b/src/game/physics/hole/hole_depth_simulation.cpp deleted file mode 100644 index 3d1c995..0000000 --- a/src/game/physics/hole/hole_depth_simulation.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "hole_depth_simulation.hpp" -#include "../../../config.h" - -HoleDepthSimulation::HoleDepthSimulation(std::shared_ptr collectables) : collectables( - std::move(collectables)) -{ - simWorld = std::make_shared(WORLD_GRAVITY); -} - -void HoleDepthSimulation::physicsUpdate() -{ - updateBodiesFromCollectionHistory(); - - simWorld->Step(FRAME_TIME.asSeconds(), HOLESIM_VELOCITY_ITERATIONS, HOLESIM_POSITION_ITERATIONS); - - updateCollectables(); -} - -void HoleDepthSimulation::updateBodiesFromCollectionHistory() -{ - // Remove bodies that are no longer in the collection - for (auto &collectable: collectables->recentlyRemoved) - { - auto body = bodies[collectable->getId()]; - simWorld->DestroyBody(body); - bodies.erase(collectable->getId()); - } - - // Create bodies for new collectables - for (auto &collectable: collectables->recentlyAdded) - { - bodies[collectable->getId()] = createBody(collectable); - } -} - -void HoleDepthSimulation::updateCollectables() -{ -} - -b2Body *HoleDepthSimulation::createBody(const std::shared_ptr &collectable) -{ - b2BodyDef bodyDef; - bodyDef.type = b2_dynamicBody; - bodyDef.position.Set(collectable->coordinates->isometric().x, collectable->coordinates->isometric().y); - bodyDef.linearDamping = HOLESIM_COLLECTABLE_LINEAR_DAMPING; - bodyDef.angularDamping = HOLESIM_COLLECTABLE_ANGULAR_DAMPING; - bodyDef.allowSleep = false; - bodyDef.awake = true; - auto body = simWorld->CreateBody(&bodyDef); - - b2PolygonShape shape; - shape.SetAsBox(1, 1); - b2FixtureDef fixtureDef; - fixtureDef.shape = &shape; - fixtureDef.density = HOLESIM_COLLECTABLE_DENSITY; - fixtureDef.friction = HOLESIM_COLLECTABLE_FRICTION; - fixtureDef.restitution = HOLESIM_COLLECTABLE_RESTITUTION; - body->CreateFixture(&fixtureDef); - - return body; -} diff --git a/src/game/physics/hole/hole_depth_simulation.hpp b/src/game/physics/hole/hole_depth_simulation.hpp deleted file mode 100644 index 5b62409..0000000 --- a/src/game/physics/hole/hole_depth_simulation.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef HOLESOME_HOLE_DEPTH_SIMULATION_HPP -#define HOLESOME_HOLE_DEPTH_SIMULATION_HPP - - -#include -#include -#include -#include "../../collectables/collection/collectables_depth_collection.hpp" - -/** - * @brief Simulates the hole(s) for the specific depth - */ -class HoleDepthSimulation : public GameObject -{ -public: - explicit HoleDepthSimulation(std::shared_ptr collectables); - - void physicsUpdate() override; - -private: - std::shared_ptr collectables; - std::shared_ptr simWorld; - - void updateBodiesFromCollectionHistory(); - - void updateCollectables(); - - std::map bodies = {}; // Collectable ID -> Body - b2Body *createBody(const std::shared_ptr &collectable); -}; - - -#endif //HOLESOME_HOLE_DEPTH_SIMULATION_HPP diff --git a/src/game/physics/holes/collectable_simulation.cpp b/src/game/physics/holes/collectable_simulation.cpp new file mode 100644 index 0000000..191d605 --- /dev/null +++ b/src/game/physics/holes/collectable_simulation.cpp @@ -0,0 +1,49 @@ +#include "collectable_simulation.hpp" + +#include +#include "../../../config.h" + +CollectableSimulation::CollectableSimulation(const std::shared_ptr &collectable) + : collectable(collectable) +{ + // Create simulation + world = std::make_shared(WORLD_GRAVITY); + world->SetAllowSleeping(COLLECTABLES_SIM_SLEEPING); + + // Create body + b2BodyDef bodyDef; + bodyDef.type = b2_dynamicBody; + bodyDef.angularDamping = COLLECTABLES_SIM_ANGULAR_DAMPING; + bodyDef.linearDamping = COLLECTABLES_SIM_LINEAR_DAMPING; +// bodyDef.position.Set(collectable->getPosition().x, collectable->getPosition().y); + body = world->CreateBody(&bodyDef); + + // Create shape + b2CircleShape shape; +// shape.m_radius = collectable->getRadius(); + + // Create fixture + b2FixtureDef fixtureDef; + fixtureDef.shape = &shape; + fixtureDef.friction = COLLECTABLES_SIM_FRICTION; + fixtureDef.restitution = COLLECTABLES_SIM_RESTITUTION; + fixtureDef.density = COLLECTABLES_SIM_DENSITY; + body->CreateFixture(&fixtureDef); +} + +void CollectableSimulation::physicsUpdate() +{ + updateGroundHole(); + + world->Step(FRAME_TIME.asSeconds(), COLLECTABLES_SIM_VELOCITY_ITERATIONS, COLLECTABLES_SIM_POSITION_ITERATIONS); +} + +std::shared_ptr CollectableSimulation::getCollectable() const +{ + return collectable; +} + +void CollectableSimulation::updateGroundHole() +{ + +} diff --git a/src/game/physics/holes/collectable_simulation.hpp b/src/game/physics/holes/collectable_simulation.hpp new file mode 100644 index 0000000..6bf25cf --- /dev/null +++ b/src/game/physics/holes/collectable_simulation.hpp @@ -0,0 +1,28 @@ +#ifndef HOLESOME_COLLECTABLE_SIMULATION_HPP +#define HOLESOME_COLLECTABLE_SIMULATION_HPP + + +#include +#include "../../game_object.h" +#include "../../collectables/collectable.hpp" + +class CollectableSimulation : public GameObject +{ +public: + explicit CollectableSimulation(const std::shared_ptr &collectable); + + void physicsUpdate() override; + + std::shared_ptr getCollectable() const; + +private: + std::shared_ptr world; + b2Body* body; + + std::shared_ptr collectable; + + void updateGroundHole(); +}; + + +#endif //HOLESOME_COLLECTABLE_SIMULATION_HPP diff --git a/src/game/physics/holes/holes_simulation.cpp b/src/game/physics/holes/holes_simulation.cpp new file mode 100644 index 0000000..705fcec --- /dev/null +++ b/src/game/physics/holes/holes_simulation.cpp @@ -0,0 +1,47 @@ +#include "holes_simulation.hpp" + +std::shared_ptr HolesSimulation::getInstance() +{ + if (singletonInstance == nullptr) { + singletonInstance = std::make_shared(); + } + + return singletonInstance; +} + +std::vector> HolesSimulation::getCollectableSimulations() const +{ + std::vector> collectableSimulations{}; + + for (auto &child : getChildren()) { + auto sim = std::dynamic_pointer_cast(child); + collectableSimulations.push_back(sim); + } + return collectableSimulations; +} + +void HolesSimulation::clear() +{ + clearChildren(); +} + +void HolesSimulation::addCollectable(const std::shared_ptr &collectable) +{ + // Create new collectable simulation + auto collectableSim = std::make_shared(collectable); + addChild(collectableSim); +} + +void HolesSimulation::lateUpdate() +{ + // Remove disabled collectables + for (const auto& sim : getCollectableSimulations()) { + if (sim->getCollectable()->getActive()) { + continue; + } + + removeChild(sim); + } + + GameObject::lateUpdate(); +} diff --git a/src/game/physics/holes/holes_simulation.hpp b/src/game/physics/holes/holes_simulation.hpp new file mode 100644 index 0000000..74552cd --- /dev/null +++ b/src/game/physics/holes/holes_simulation.hpp @@ -0,0 +1,27 @@ +#ifndef HOLESOME_HOLES_SIMULATION_HPP +#define HOLESOME_HOLES_SIMULATION_HPP + + +#include +#include "../../game_object.h" +#include "collectable_simulation.hpp" + +class HolesSimulation : public GameObject +{ +public: + static std::shared_ptr getInstance(); + + void addCollectable(const std::shared_ptr &collectable); + + void lateUpdate() override; + + void clear(); + + std::vector> getCollectableSimulations() const; + +private: + static inline std::shared_ptr singletonInstance = nullptr; +}; + + +#endif //HOLESOME_HOLES_SIMULATION_HPP diff --git a/src/game/physics/holes/layouts/depth_hole_description.hpp b/src/game/physics/holes/layouts/depth_hole_description.hpp new file mode 100644 index 0000000..e804a40 --- /dev/null +++ b/src/game/physics/holes/layouts/depth_hole_description.hpp @@ -0,0 +1,11 @@ +#ifndef HOLESOME_DEPTH_HOLE_DESCRIPTION_HPP +#define HOLESOME_DEPTH_HOLE_DESCRIPTION_HPP + +struct DepthHoleDescription +{ + int playerId; + float x; + float width; +}; + +#endif //HOLESOME_DEPTH_HOLE_DESCRIPTION_HPP diff --git a/src/game/physics/holes/layouts/depth_hole_layout.hpp b/src/game/physics/holes/layouts/depth_hole_layout.hpp new file mode 100644 index 0000000..b184c8b --- /dev/null +++ b/src/game/physics/holes/layouts/depth_hole_layout.hpp @@ -0,0 +1,13 @@ +#ifndef HOLESOME_DEPTH_HOLE_LAYOUT_HPP +#define HOLESOME_DEPTH_HOLE_LAYOUT_HPP + +#include +#include "depth_hole_description.hpp" + +struct DepthHoleLayout +{ + float depth; + std::vector holes; +}; + +#endif //HOLESOME_DEPTH_HOLE_LAYOUT_HPP diff --git a/src/game/physics/holes/layouts/hole_description.hpp b/src/game/physics/holes/layouts/hole_description.hpp new file mode 100644 index 0000000..f58c230 --- /dev/null +++ b/src/game/physics/holes/layouts/hole_description.hpp @@ -0,0 +1,25 @@ +#ifndef HOLESOME_HOLE_DESCRIPTION_HPP +#define HOLESOME_HOLE_DESCRIPTION_HPP + + +#include +#include "../../../player/player.hpp" + +struct HoleDescription +{ + int playerId; + sf::Vector2f worldPosition; + float radius; + + explicit HoleDescription(const std::shared_ptr &player) + { + playerId = player->getPlayerId(); + radius = player->getWorldRadius(); + + auto world3d = player->coordinates->world(); + worldPosition = sf::Vector2f(world3d.x, world3d.y); + } +}; + + +#endif //HOLESOME_HOLE_DESCRIPTION_HPP diff --git a/src/game/physics/holes/layouts/hole_layout.cpp b/src/game/physics/holes/layouts/hole_layout.cpp new file mode 100644 index 0000000..30d73fa --- /dev/null +++ b/src/game/physics/holes/layouts/hole_layout.cpp @@ -0,0 +1,37 @@ +#include "hole_layout.hpp" +#include "../../../player/player_collection.hpp" + +std::shared_ptr HoleLayout::getInstance() +{ + if (singletonInstance == nullptr) + { + singletonInstance = std::make_shared(); + } + return singletonInstance; +} + +void HoleLayout::clear() +{ + previousHoles.clear(); + currentHoles.clear(); +} + +void HoleLayout::lateUpdate() +{ + // Move history forward + previousHoles = currentHoles; + currentHoles.clear(); + + // Collect hole descriptions of active players + for (const auto &player: PlayerCollection::getInstance()->getPlayers()) + { + if (player->getActive()) + { + currentHoles.emplace_back(player); + } + } +} + +HoleLayout::HoleLayout() + : currentHoles(), previousHoles() +{} diff --git a/src/game/physics/holes/layouts/hole_layout.hpp b/src/game/physics/holes/layouts/hole_layout.hpp new file mode 100644 index 0000000..793e79f --- /dev/null +++ b/src/game/physics/holes/layouts/hole_layout.hpp @@ -0,0 +1,28 @@ +#ifndef HOLESOME_HOLE_LAYOUT_HPP +#define HOLESOME_HOLE_LAYOUT_HPP + + +#include +#include "../../../game_object.h" +#include "hole_description.hpp" + +class HoleLayout : public GameObject +{ +public: + HoleLayout(); + + static std::shared_ptr getInstance(); + + void lateUpdate() override; + + void clear(); + +private: + static inline std::shared_ptr singletonInstance = nullptr; + + std::vector currentHoles; + std::vector previousHoles; +}; + + +#endif //HOLESOME_HOLE_LAYOUT_HPP