diff --git a/CMakeLists.txt b/CMakeLists.txt index a708826..f61e70c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,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/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/game/physics/hole/hole_sim_player.cpp src/game/physics/hole/hole_sim_player.hpp src/game/collectables/collectable_sim_parameters.hpp src/game/collectables/sim_collectable.hpp) set(PHYSICS_00_SOURCES src/prototypes/physics_00.cpp) diff --git a/TODO.md b/TODO.md index 27de9e7..22901f9 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,3 @@ # Holesome - ToDos -- [ ] Try button mapping for other controllers \ No newline at end of file +- [ ] Optimize hole depth simulations by not simulating when nothing happens \ No newline at end of file diff --git a/src/config.h b/src/config.h index adb33a4..5cfb151 100644 --- a/src/config.h +++ b/src/config.h @@ -47,6 +47,8 @@ #define HOLESIM_COLLECTABLE_DENSITY 1.f #define HOLESIM_COLLECTABLE_FRICTION 0.3f #define HOLESIM_COLLECTABLE_RESTITUTION 0.5f +#define HOLESIM_FLOOR_THICKNESS 0.5f +#define HOLESIM_WALL_HEIGHT 5.f // Directions #define DIRECTION_HARD_ACTIVATION_THRESHOLD 0.1f diff --git a/src/game/collectables/collectable.cpp b/src/game/collectables/collectable.cpp index 94cdbb6..829a74f 100644 --- a/src/game/collectables/collectable.cpp +++ b/src/game/collectables/collectable.cpp @@ -8,11 +8,6 @@ Collectable::Collectable() collectableCount++; } -void Collectable::setRotation(float angle) -{ - -} - int Collectable::getDepth() const { return static_cast(coordinates->isometric().depth); @@ -26,3 +21,13 @@ void Collectable::setSprite(const std::string &spriteName) auto sprite = std::make_shared(spriteName, size); addChildScreenOffset(sprite, IsometricCoordinates(-sizeWidth / 2.f, -sizeWidth)); } + +int Collectable::getId() const +{ + return collectableId; +} + +void Collectable::setSpriteAngle(float angle) +{ + // TODO +} diff --git a/src/game/collectables/collectable.hpp b/src/game/collectables/collectable.hpp index dbb816d..7e94ec8 100644 --- a/src/game/collectables/collectable.hpp +++ b/src/game/collectables/collectable.hpp @@ -1,8 +1,9 @@ #ifndef HOLESOME_COLLECTABLE_HPP #define HOLESOME_COLLECTABLE_HPP - +#include #include "../game_object.h" +#include "collectable_sim_parameters.hpp" class Collectable : public GameObject { @@ -11,14 +12,13 @@ public: void setSprite(const std::string &spriteName); - void setRotation(float angle); + void setSpriteAngle(float angle); - int getDepth() const; + [[nodiscard]] int getDepth() const; - int getId() const - { - return collectableId; - } + [[nodiscard]] int getId() const; + + CollectableSimParameters simParameters = {}; private: int collectableId = 0; diff --git a/src/game/collectables/collectable_sim_parameters.hpp b/src/game/collectables/collectable_sim_parameters.hpp new file mode 100644 index 0000000..a61cbdc --- /dev/null +++ b/src/game/collectables/collectable_sim_parameters.hpp @@ -0,0 +1,15 @@ +#ifndef HOLESOME_COLLECTABLE_SIM_PARAMETERS_HPP +#define HOLESOME_COLLECTABLE_SIM_PARAMETERS_HPP + +#include + +struct CollectableSimParameters +{ + float angle = 0; + float angularVelocity = 0; + b2Vec2 linearVelocity = {0, 0}; + + CollectableSimParameters() = default; +}; + +#endif //HOLESOME_COLLECTABLE_SIM_PARAMETERS_HPP diff --git a/src/game/collectables/sim_collectable.hpp b/src/game/collectables/sim_collectable.hpp new file mode 100644 index 0000000..3a09c8b --- /dev/null +++ b/src/game/collectables/sim_collectable.hpp @@ -0,0 +1,21 @@ +#ifndef HOLESOME_SIM_COLLECTABLE_HPP +#define HOLESOME_SIM_COLLECTABLE_HPP + +#include "collectable.hpp" +#include + +struct SimCollectable +{ + std::shared_ptr collectable = nullptr; + b2Body *body = nullptr; + + SimCollectable(std::shared_ptr collectable, b2Body *body) + { + this->collectable = std::move(collectable); + this->body = body; + } + + SimCollectable() = default; +}; + +#endif //HOLESOME_SIM_COLLECTABLE_HPP diff --git a/src/game/physics/hole/hole_depth_simulation.cpp b/src/game/physics/hole/hole_depth_simulation.cpp index 3d1c995..3465cee 100644 --- a/src/game/physics/hole/hole_depth_simulation.cpp +++ b/src/game/physics/hole/hole_depth_simulation.cpp @@ -1,5 +1,6 @@ #include "hole_depth_simulation.hpp" #include "../../../config.h" +#include "../../player/player_collection.hpp" HoleDepthSimulation::HoleDepthSimulation(std::shared_ptr collectables) : collectables( std::move(collectables)) @@ -11,6 +12,10 @@ void HoleDepthSimulation::physicsUpdate() { updateBodiesFromCollectionHistory(); + preparePlayers(); + + updateGroundBodies(); + simWorld->Step(FRAME_TIME.asSeconds(), HOLESIM_VELOCITY_ITERATIONS, HOLESIM_POSITION_ITERATIONS); updateCollectables(); @@ -21,20 +26,38 @@ 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()); + auto simCollectable = simCollectables.at(collectable->getId()); + simWorld->DestroyBody(simCollectable.body); + simCollectables.erase(collectable->getId()); } // Create bodies for new collectables for (auto &collectable: collectables->recentlyAdded) { - bodies[collectable->getId()] = createBody(collectable); + simCollectables[collectable->getId()] = SimCollectable(collectable, createBody(collectable)); } } void HoleDepthSimulation::updateCollectables() { + for (auto &[id, simCollectable]: simCollectables) + { + auto collectable = simCollectable.collectable; + auto body = simCollectable.body; + + auto position = body->GetPosition(); + collectable->coordinates->set(IsometricCoordinates{ + position.x, + position.y, + collectable->coordinates->isometric().depth + }); + + collectable->simParameters.angle = body->GetAngle(); + collectable->simParameters.linearVelocity = body->GetLinearVelocity(); + collectable->simParameters.angularVelocity = body->GetAngularVelocity(); + + collectable->setSpriteAngle(collectable->simParameters.angle); + } } b2Body *HoleDepthSimulation::createBody(const std::shared_ptr &collectable) @@ -57,5 +80,57 @@ b2Body *HoleDepthSimulation::createBody(const std::shared_ptr &coll fixtureDef.restitution = HOLESIM_COLLECTABLE_RESTITUTION; body->CreateFixture(&fixtureDef); + // Update simulation parameters from existing collectable + body->SetTransform( + b2Vec2{ + collectable->coordinates->isometric().x, + collectable->coordinates->isometric().y + }, + collectable->simParameters.angle); + body->SetLinearVelocity(collectable->simParameters.linearVelocity); + body->SetAngularVelocity(collectable->simParameters.angularVelocity); + return body; } + +int HoleDepthSimulation::getDepth() const +{ + return collectables->depth; +} + +void HoleDepthSimulation::preparePlayers() +{ + for (const auto &player: PlayerCollection::getInstance()->getPlayers()) + { + if (player->getDepth() == getDepth()) + { + addToSim(player); + } else + { + removeFromSim(player); + } + } +} + +void HoleDepthSimulation::addToSim(const std::shared_ptr &player) +{ + int playerId = player->getPlayerId(); + if (simPlayers.find(playerId) == simPlayers.end()) + { + simPlayers[playerId] = HoleSimPlayer(player); + } +} + +void HoleDepthSimulation::removeFromSim(const std::shared_ptr &player) +{ + int playerId = player->getPlayerId(); + if (simPlayers.find(playerId) != simPlayers.end()) + { + simPlayers.erase(playerId); + } +} + +void HoleDepthSimulation::updateGroundBodies() +{ + +} diff --git a/src/game/physics/hole/hole_depth_simulation.hpp b/src/game/physics/hole/hole_depth_simulation.hpp index 5b62409..23ae5db 100644 --- a/src/game/physics/hole/hole_depth_simulation.hpp +++ b/src/game/physics/hole/hole_depth_simulation.hpp @@ -6,6 +6,8 @@ #include #include #include "../../collectables/collection/collectables_depth_collection.hpp" +#include "hole_sim_player.hpp" +#include "../../collectables/sim_collectable.hpp" /** * @brief Simulates the hole(s) for the specific depth @@ -17,16 +19,27 @@ public: void physicsUpdate() override; + [[nodiscard]] int getDepth() const; + private: std::shared_ptr collectables; std::shared_ptr simWorld; + std::map simPlayers = {}; // Player ID -> HoleSimPlayer void updateBodiesFromCollectionHistory(); void updateCollectables(); - std::map bodies = {}; // Collectable ID -> Body + std::map simCollectables = {}; // Collectable ID -> Body b2Body *createBody(const std::shared_ptr &collectable); + + void preparePlayers(); + + void addToSim(const std::shared_ptr &player); + + void removeFromSim(const std::shared_ptr &player); + + void updateGroundBodies(); }; diff --git a/src/game/physics/hole/hole_sim_player.cpp b/src/game/physics/hole/hole_sim_player.cpp new file mode 100644 index 0000000..c14f013 --- /dev/null +++ b/src/game/physics/hole/hole_sim_player.cpp @@ -0,0 +1,18 @@ +#include "hole_sim_player.hpp" + +void HoleSimPlayer::updateSimulationPosition() +{ + xPosition = player->coordinates->isometric().x; + width = player->getIsoHoleWidth(); +} + +HoleSimPlayer::HoleSimPlayer(std::shared_ptr player) +{ + this->player = std::move(player); + updateSimulationPosition(); +} + +HoleSimPlayer::HoleSimPlayer() +{ + player = nullptr; +} diff --git a/src/game/physics/hole/hole_sim_player.hpp b/src/game/physics/hole/hole_sim_player.hpp new file mode 100644 index 0000000..467b075 --- /dev/null +++ b/src/game/physics/hole/hole_sim_player.hpp @@ -0,0 +1,23 @@ +#ifndef HOLESOME_HOLE_SIM_PLAYER_HPP +#define HOLESOME_HOLE_SIM_PLAYER_HPP + + +#include +#include "../../player/player.hpp" +#include + +struct HoleSimPlayer +{ + HoleSimPlayer(); + + std::shared_ptr player; + float xPosition = 0; + float width = 0; + + explicit HoleSimPlayer(std::shared_ptr player); + + void updateSimulationPosition(); +}; + + +#endif //HOLESOME_HOLE_SIM_PLAYER_HPP diff --git a/src/game/player/player.cpp b/src/game/player/player.cpp index 2099b32..f10f81e 100644 --- a/src/game/player/player.cpp +++ b/src/game/player/player.cpp @@ -99,3 +99,15 @@ Player::~Player() { LOG(INFO) << "Player " << playerId << " destroyed."; } + +float Player::getIsoHoleWidth() const +{ + // Assuming 10% of the player's size is border + float holeFactor = .9f; + return getIsoSize().x * holeFactor; +} + +int Player::getDepth() const +{ + return ceil(coordinates->isometric().depth); +} diff --git a/src/game/player/player.hpp b/src/game/player/player.hpp index 9a92707..a1c8e4a 100644 --- a/src/game/player/player.hpp +++ b/src/game/player/player.hpp @@ -31,6 +31,10 @@ public: [[nodiscard]] float getWorldRadius() const; + [[nodiscard]] float getIsoHoleWidth() const; + + [[nodiscard]] int getDepth() const; + TranslatedCoordinates spawnPosition; private: std::shared_ptr input; diff --git a/src/game/player/player_collection.cpp b/src/game/player/player_collection.cpp index 23118af..c8253ff 100644 --- a/src/game/player/player_collection.cpp +++ b/src/game/player/player_collection.cpp @@ -28,6 +28,7 @@ std::shared_ptr PlayerCollection::getInstance() void PlayerCollection::addPlayer(const std::shared_ptr &player) { newPlayerBuffer.push_back(player); + players.push_back(player); addChild(player); } @@ -37,15 +38,15 @@ void PlayerCollection::clear() removedPlayerBuffer.clear(); // Fill in removed players - for (auto &child: getChildren()) + for (auto &player: players) { - auto player = std::dynamic_pointer_cast(child); if (player != nullptr) { removedPlayerBuffer.push_back(player); } } + players.clear(); clearChildren(); } @@ -67,8 +68,7 @@ void PlayerCollection::lateUpdate() { if (child != nullptr && !child->getActive()) { - removedPlayerBuffer.push_back(std::dynamic_pointer_cast(child)); - removeChild(child); + removePlayer(std::dynamic_pointer_cast(child)); } } } @@ -76,6 +76,7 @@ void PlayerCollection::lateUpdate() void PlayerCollection::removePlayer(const std::shared_ptr &player) { removedPlayerBuffer.push_back(player); + players.erase(std::remove(players.begin(), players.end(), player), players.end()); removeChild(player); } @@ -104,3 +105,8 @@ void PlayerCollection::spawnPlayer(const std::shared_ptr &inputId auto player = std::make_shared(inputIdentity, PLAYER_SKIN, spawn); PlayerCollection::getInstance()->addPlayer(player); } + +std::vector> PlayerCollection::getPlayers() const +{ + return players; +} diff --git a/src/game/player/player_collection.hpp b/src/game/player/player_collection.hpp index 8fcdcda..cfd5068 100644 --- a/src/game/player/player_collection.hpp +++ b/src/game/player/player_collection.hpp @@ -18,9 +18,11 @@ public: void removePlayer(const std::shared_ptr& player); - std::vector> getNewPlayers() const; + [[nodiscard]] std::vector> getPlayers() const; - std::vector> getRemovedPlayers() const; + [[nodiscard]] std::vector> getNewPlayers() const; + + [[nodiscard]] std::vector> getRemovedPlayers() const; void lateUpdate() override; @@ -29,6 +31,7 @@ public: private: static inline std::shared_ptr singletonInstance = nullptr; + std::vector> players = {}; std::vector> newPlayerBuffer = {}; std::vector> removedPlayerBuffer = {};