Sync commit, re-implementing tracking view
This commit is contained in:
parent
15e63094fd
commit
29c5eb7bdd
5 changed files with 84 additions and 95 deletions
|
@ -3,12 +3,21 @@
|
||||||
|
|
||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
|
enum TrackableState
|
||||||
|
{
|
||||||
|
TRACKING,
|
||||||
|
EXCLUDE_FROM_TRACKING,
|
||||||
|
END_TRACKING
|
||||||
|
};
|
||||||
|
|
||||||
class ITrackable
|
class ITrackable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual sf::Vector2f getTrackablePosition() const = 0;
|
virtual sf::Vector2f getTrackablePosition() const = 0;
|
||||||
|
|
||||||
virtual sf::Vector2f getTrackableSize() const = 0;
|
virtual sf::Vector2f getTrackableSize() const = 0;
|
||||||
|
|
||||||
|
virtual inline TrackableState getTrackableState() const { return TrackableState::TRACKING; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //HOLESOME_ITRACKABLE_H
|
#endif //HOLESOME_ITRACKABLE_H
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
#include "tracking_view.h"
|
#include "tracking_view.h"
|
||||||
#include "../../utilities/vector_utils.hpp"
|
#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()
|
TrackingView::~TrackingView()
|
||||||
{
|
{
|
||||||
delete view;
|
delete view;
|
||||||
|
@ -15,10 +24,13 @@ void TrackingView::lateUpdate(Game *game)
|
||||||
initializeView(game);
|
initializeView(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processTrackableStates();
|
||||||
|
|
||||||
// Update size
|
// Update size
|
||||||
|
// TODO: Update size based on distance of tracked objects
|
||||||
setSize(game->window->getSize());
|
setSize(game->window->getSize());
|
||||||
|
|
||||||
if (target != nullptr)
|
if (!trackables.empty())
|
||||||
{
|
{
|
||||||
followTarget();
|
followTarget();
|
||||||
}
|
}
|
||||||
|
@ -52,13 +64,6 @@ void TrackingView::setSize(sf::Vector2u windowSize)
|
||||||
hasViewChanged = true;
|
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
|
sf::Vector2f TrackingView::getSize() const
|
||||||
{
|
{
|
||||||
return view->getSize();
|
return view->getSize();
|
||||||
|
@ -71,16 +76,15 @@ sf::Vector2f TrackingView::getCenter() const
|
||||||
|
|
||||||
void TrackingView::followTarget()
|
void TrackingView::followTarget()
|
||||||
{
|
{
|
||||||
// TODO
|
auto trackingPoint = getCollectiveTrackingPoint();
|
||||||
auto closestPositionInDynamic = getClosestPositionInArea(dynamicFollowArea);
|
marker->coordinates.set(IsometricCoordinates(trackingPoint));
|
||||||
marker->coordinates.set(IsometricCoordinates(closestPositionInDynamic));
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isTargetInArea(freeMoveArea))
|
// if (isTargetInArea(freeMoveArea))
|
||||||
{
|
// {
|
||||||
// Nothing to do
|
// // Nothing to do
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// performHardFollow();
|
// performHardFollow();
|
||||||
// if (isTargetInArea(dynamicFollowArea))
|
// 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)
|
void TrackingView::moveCenter(sf::Vector2<float> delta)
|
||||||
{
|
{
|
||||||
view->move(delta);
|
view->move(delta);
|
||||||
hasViewChanged = true;
|
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
|
void TrackingView::draw(sf::RenderWindow *window) const
|
||||||
{
|
{
|
||||||
marker->draw(window);
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
class TrackingView : public GameObject
|
class TrackingView : public GameObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TrackingView(ITrackable *trackable = nullptr,
|
explicit TrackingView(float freeMoveRadius = 150,
|
||||||
sf::Vector2f freeMoveArea = {200, 200},
|
float dynamicFollowRadius = 300);
|
||||||
sf::Vector2f dynamicFollowArea = {500, 500});
|
|
||||||
|
|
||||||
~TrackingView();
|
~TrackingView();
|
||||||
|
|
||||||
|
@ -20,15 +19,17 @@ public:
|
||||||
void draw(sf::RenderWindow *window) const override;
|
void draw(sf::RenderWindow *window) const override;
|
||||||
void lateUpdate(Game *game) override;
|
void lateUpdate(Game *game) override;
|
||||||
|
|
||||||
|
void addTrackable(ITrackable *trackable);
|
||||||
|
|
||||||
sf::Vector2f getSize() const;
|
sf::Vector2f getSize() const;
|
||||||
sf::Vector2f getCenter() const;
|
sf::Vector2f getCenter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::View *view{};
|
sf::View *view{};
|
||||||
bool hasViewChanged{};
|
bool hasViewChanged{};
|
||||||
sf::Vector2f freeMoveArea;
|
float freeMoveRadius;
|
||||||
sf::Vector2f dynamicFollowArea;
|
float dynamicFollowRadius;
|
||||||
ITrackable *target;
|
std::vector<ITrackable *> trackables;
|
||||||
|
|
||||||
CircleObject *marker;
|
CircleObject *marker;
|
||||||
|
|
||||||
|
@ -51,6 +52,10 @@ private:
|
||||||
void moveCenter(sf::Vector2<float> delta);
|
void moveCenter(sf::Vector2<float> delta);
|
||||||
|
|
||||||
void performDynamicFollow();
|
void performDynamicFollow();
|
||||||
|
|
||||||
|
sf::Vector2f getCollectiveTrackingPoint() const;
|
||||||
|
|
||||||
|
void processTrackableStates();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,3 +45,14 @@ Player::Player(std::shared_ptr<InputIdentity> assignedInput, const sf::Color col
|
||||||
circle = new CircleObject(10, color);
|
circle = new CircleObject(10, color);
|
||||||
circle->coordinates.set(coordinates);
|
circle->coordinates.set(coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrackableState Player::getTrackableState() const
|
||||||
|
{
|
||||||
|
if (isActive)
|
||||||
|
{
|
||||||
|
return TrackableState::TRACKING;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return TrackableState::END_TRACKING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ public:
|
||||||
|
|
||||||
sf::Vector2f getTrackableSize() const override;
|
sf::Vector2f getTrackableSize() const override;
|
||||||
|
|
||||||
|
TrackableState getTrackableState() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CircleObject *circle;
|
CircleObject *circle;
|
||||||
std::shared_ptr<InputIdentity> input;
|
std::shared_ptr<InputIdentity> input;
|
||||||
|
|
Loading…
Reference in a new issue