Sync commit, re-implementing tracking view

This commit is contained in:
Maximilian Giller 2023-05-24 01:15:05 +02:00
parent 15e63094fd
commit 29c5eb7bdd
5 changed files with 84 additions and 95 deletions

View file

@ -3,12 +3,21 @@
#include <SFML/System/Vector2.hpp>
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

View file

@ -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<ITrackable *>();
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<float> 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;
});
}

View file

@ -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<ITrackable *> trackables;
CircleObject *marker;
@ -51,6 +52,10 @@ private:
void moveCenter(sf::Vector2<float> delta);
void performDynamicFollow();
sf::Vector2f getCollectiveTrackingPoint() const;
void processTrackableStates();
};

View file

@ -45,3 +45,14 @@ Player::Player(std::shared_ptr<InputIdentity> 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;
}
}

View file

@ -20,6 +20,8 @@ public:
sf::Vector2f getTrackableSize() const override;
TrackableState getTrackableState() const override;
private:
CircleObject *circle;
std::shared_ptr<InputIdentity> input;