From 29c5eb7bdda17f0359d6cc3944cce8fd27f46fed Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Wed, 24 May 2023 01:15:05 +0200 Subject: [PATCH] Sync commit, re-implementing tracking view --- src/game/camera/ITrackable.h | 9 ++ src/game/camera/tracking_view.cpp | 140 +++++++++++------------------- src/game/camera/tracking_view.h | 17 ++-- src/game/player/player.cpp | 11 +++ src/game/player/player.hpp | 2 + 5 files changed, 84 insertions(+), 95 deletions(-) diff --git a/src/game/camera/ITrackable.h b/src/game/camera/ITrackable.h index a143a4c..379a580 100644 --- a/src/game/camera/ITrackable.h +++ b/src/game/camera/ITrackable.h @@ -3,12 +3,21 @@ #include +enum TrackableState +{ + TRACKING, + EXCLUDE_FROM_TRACKING, + END_TRACKING +}; + class ITrackable { public: virtual sf::Vector2f getTrackablePosition() const = 0; virtual sf::Vector2f getTrackableSize() const = 0; + + virtual inline TrackableState getTrackableState() const { return TrackableState::TRACKING; }; }; #endif //HOLESOME_ITRACKABLE_H diff --git a/src/game/camera/tracking_view.cpp b/src/game/camera/tracking_view.cpp index dd1a0b7..45c8b0b 100644 --- a/src/game/camera/tracking_view.cpp +++ b/src/game/camera/tracking_view.cpp @@ -1,6 +1,15 @@ #include "tracking_view.h" #include "../../utilities/vector_utils.hpp" +TrackingView::TrackingView(float freeMoveRadius, float dynamicFollowRadius) : freeMoveRadius(freeMoveRadius), + dynamicFollowRadius(dynamicFollowRadius), + view(nullptr), + hasViewChanged(false) +{ + trackables = std::vector(); + marker = new CircleObject(2, sf::Color::Yellow); +} + TrackingView::~TrackingView() { delete view; @@ -15,10 +24,13 @@ void TrackingView::lateUpdate(Game *game) initializeView(game); } + processTrackableStates(); + // Update size + // TODO: Update size based on distance of tracked objects setSize(game->window->getSize()); - if (target != nullptr) + if (!trackables.empty()) { followTarget(); } @@ -52,13 +64,6 @@ void TrackingView::setSize(sf::Vector2u windowSize) hasViewChanged = true; } -TrackingView::TrackingView(ITrackable *trackable, sf::Vector2f freeMoveArea, sf::Vector2f dynamicFollowArea) - : target(trackable), freeMoveArea(freeMoveArea), dynamicFollowArea(dynamicFollowArea), view(nullptr), - hasViewChanged(false) -{ - marker = new CircleObject(2, sf::Color::Yellow); -} - sf::Vector2f TrackingView::getSize() const { return view->getSize(); @@ -71,16 +76,15 @@ sf::Vector2f TrackingView::getCenter() const void TrackingView::followTarget() { - // TODO - auto closestPositionInDynamic = getClosestPositionInArea(dynamicFollowArea); - marker->coordinates.set(IsometricCoordinates(closestPositionInDynamic)); + auto trackingPoint = getCollectiveTrackingPoint(); + marker->coordinates.set(IsometricCoordinates(trackingPoint)); return; - if (isTargetInArea(freeMoveArea)) - { - // Nothing to do - return; - } +// if (isTargetInArea(freeMoveArea)) +// { +// // Nothing to do +// return; +// } // performHardFollow(); // if (isTargetInArea(dynamicFollowArea)) @@ -94,86 +98,44 @@ void TrackingView::followTarget() // } } -bool TrackingView::isTargetInArea(sf::Vector2f areaSize) -{ - // Assuming target is not null - - // Target specifications - auto targetSize = target->getTrackableSize(); - auto targetTopLeft = target->getTrackablePosition() - targetSize / 2.f; - auto targetBottomRight = targetTopLeft + targetSize; - - // Free Movement Area - auto areaTopLeft = getCenter() - areaSize / 2.f; - auto areaBottomRight = areaTopLeft + areaSize; - - // Check collision of all edges - if (targetTopLeft.x < areaTopLeft.x || - targetTopLeft.y < areaTopLeft.y || - targetBottomRight.x > areaBottomRight.x || - targetBottomRight.y > areaBottomRight.y) - { - return false; - } - - return true; -} - -sf::Vector2f TrackingView::getClosestPositionInArea(sf::Vector2f areaSize) const -{ - // Reduce area to only consider target position, not size - auto positionOnlyAreaSize = areaSize - target->getTrackableSize(); - - // Calculate max-length of rubber to land inside of area - sf::Vector2f rubber = getRubber(); - - // Problem is symmetrical for all corners, so can simplify to use only absolute values and part of the area - auto absRubber = abs(rubber); - auto cornerArea = positionOnlyAreaSize / 2.f; - - // Calculate factor for each dimension, that would scale it to the border - float xScale = INFINITY; - if (absRubber.x > 0) - { - xScale = cornerArea.x / absRubber.x; - } - float yScale = INFINITY; - if (absRubber.y > 0) - { - yScale = cornerArea.y / absRubber.y; - } - - float length = std::min(xScale, yScale); - - return rubber * length; -} - -sf::Vector2f TrackingView::getRubber() const -{ - return normalize(target->getTrackablePosition() - getCenter()); -} - -void TrackingView::performHardFollow() -{ - auto closestPositionInDynamic = getClosestPositionInArea(dynamicFollowArea); - auto delta = getCenter() - closestPositionInDynamic; - moveCenter(-delta); -} - void TrackingView::moveCenter(sf::Vector2 delta) { view->move(delta); hasViewChanged = true; } -void TrackingView::performDynamicFollow() -{ - auto closestPositionInDynamic = getClosestPositionInArea(freeMoveArea); - auto delta = getCenter() - closestPositionInDynamic; - moveCenter(delta * VIEW_RUBBER_FOLLOW_SPEED * FRAME_TIME.asSeconds()); -} - void TrackingView::draw(sf::RenderWindow *window) const { marker->draw(window); } + +void TrackingView::addTrackable(ITrackable *trackable) +{ + trackables.push_back(trackable); +} + +sf::Vector2f TrackingView::getCollectiveTrackingPoint() const +{ + sf::Vector2f collectiveTrackingPoint = {0, 0}; + + for (auto trackable : trackables) + { + if (trackable->getTrackableState() != TrackableState::TRACKING) + { + continue; + } + + collectiveTrackingPoint += trackable->getTrackablePosition(); + } + + return collectiveTrackingPoint / (float) trackables.size(); +} + +void TrackingView::processTrackableStates() +{ + // Remove trackables that have ended tracking + std::remove_if(trackables.begin(), trackables.end(), [](ITrackable *trackable) + { + return trackable->getTrackableState() == TrackableState::END_TRACKING; + }); +} diff --git a/src/game/camera/tracking_view.h b/src/game/camera/tracking_view.h index c62edbb..44ad55d 100644 --- a/src/game/camera/tracking_view.h +++ b/src/game/camera/tracking_view.h @@ -10,9 +10,8 @@ class TrackingView : public GameObject { public: - explicit TrackingView(ITrackable *trackable = nullptr, - sf::Vector2f freeMoveArea = {200, 200}, - sf::Vector2f dynamicFollowArea = {500, 500}); + explicit TrackingView(float freeMoveRadius = 150, + float dynamicFollowRadius = 300); ~TrackingView(); @@ -20,15 +19,17 @@ public: void draw(sf::RenderWindow *window) const override; void lateUpdate(Game *game) override; + void addTrackable(ITrackable *trackable); + sf::Vector2f getSize() const; sf::Vector2f getCenter() const; private: sf::View *view{}; bool hasViewChanged{}; - sf::Vector2f freeMoveArea; - sf::Vector2f dynamicFollowArea; - ITrackable *target; + float freeMoveRadius; + float dynamicFollowRadius; + std::vector trackables; CircleObject *marker; @@ -51,6 +52,10 @@ private: void moveCenter(sf::Vector2 delta); void performDynamicFollow(); + + sf::Vector2f getCollectiveTrackingPoint() const; + + void processTrackableStates(); }; diff --git a/src/game/player/player.cpp b/src/game/player/player.cpp index 699b619..a0bbea8 100644 --- a/src/game/player/player.cpp +++ b/src/game/player/player.cpp @@ -45,3 +45,14 @@ Player::Player(std::shared_ptr assignedInput, const sf::Color col circle = new CircleObject(10, color); circle->coordinates.set(coordinates); } + +TrackableState Player::getTrackableState() const +{ + if (isActive) + { + return TrackableState::TRACKING; + } else + { + return TrackableState::END_TRACKING; + } +} diff --git a/src/game/player/player.hpp b/src/game/player/player.hpp index b07384e..f9d9f88 100644 --- a/src/game/player/player.hpp +++ b/src/game/player/player.hpp @@ -20,6 +20,8 @@ public: sf::Vector2f getTrackableSize() const override; + TrackableState getTrackableState() const override; + private: CircleObject *circle; std::shared_ptr input;