2023-05-23 23:38:37 +02:00
|
|
|
#include "tracking_view.h"
|
2023-05-14 22:23:25 +02:00
|
|
|
#include "../../utilities/vector_utils.hpp"
|
2023-05-09 20:50:50 +02:00
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
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);
|
2023-05-24 14:00:51 +02:00
|
|
|
Game::getInstance()->registerView(this);
|
2023-05-24 01:15:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-23 23:38:37 +02:00
|
|
|
TrackingView::~TrackingView()
|
2023-05-09 20:50:50 +02:00
|
|
|
{
|
2023-05-10 11:03:14 +02:00
|
|
|
delete view;
|
2023-05-14 22:23:25 +02:00
|
|
|
delete marker;
|
2023-05-09 20:50:50 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 14:00:51 +02:00
|
|
|
void TrackingView::lateUpdate()
|
2023-05-09 20:50:50 +02:00
|
|
|
{
|
2023-05-10 11:30:11 +02:00
|
|
|
// Initialize if necessary
|
2023-05-10 11:03:14 +02:00
|
|
|
if (view == nullptr)
|
|
|
|
{
|
2023-05-24 14:00:51 +02:00
|
|
|
initializeView();
|
2023-05-10 11:03:14 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
processTrackableStates();
|
|
|
|
|
2023-05-10 11:03:14 +02:00
|
|
|
// Update size
|
2023-05-24 15:21:53 +02:00
|
|
|
// TODO: Update size based on length of tracked objects
|
2023-05-24 14:00:51 +02:00
|
|
|
setSize(Game::getInstance()->window->getSize());
|
2023-05-09 20:50:50 +02:00
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
if (!trackables.empty())
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
|
|
|
followTarget();
|
|
|
|
}
|
2023-05-10 11:30:11 +02:00
|
|
|
|
|
|
|
// Update window if necessary
|
|
|
|
if (hasViewChanged)
|
2023-05-09 20:50:50 +02:00
|
|
|
{
|
2023-05-24 14:00:51 +02:00
|
|
|
Game::getInstance()->window->setView(*this->view);
|
2023-05-10 11:30:11 +02:00
|
|
|
hasViewChanged = false;
|
2023-05-09 20:50:50 +02:00
|
|
|
}
|
2023-05-10 11:03:14 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 14:00:51 +02:00
|
|
|
void TrackingView::initializeView()
|
2023-05-10 11:03:14 +02:00
|
|
|
{
|
2023-05-24 14:00:51 +02:00
|
|
|
auto size = Game::getInstance()->window->getView().getSize();
|
2023-05-14 22:23:25 +02:00
|
|
|
view = new sf::View({0, 0}, size);
|
2023-05-09 20:50:50 +02:00
|
|
|
}
|
2023-05-10 11:30:11 +02:00
|
|
|
|
2023-05-23 23:38:37 +02:00
|
|
|
void TrackingView::setSize(sf::Vector2u windowSize)
|
2023-05-10 11:30:11 +02:00
|
|
|
{
|
2023-05-14 22:23:25 +02:00
|
|
|
// TODO: Maybe listen to resize events instead of checking every frame?
|
|
|
|
// Is different?
|
|
|
|
if (view->getSize().x == windowSize.x && view->getSize().y == windowSize.y)
|
|
|
|
{
|
|
|
|
// Nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-10 11:30:11 +02:00
|
|
|
sf::Vector2f viewSize = sf::Vector2f(windowSize.x, windowSize.y);
|
|
|
|
view->setSize(viewSize);
|
|
|
|
hasViewChanged = true;
|
|
|
|
}
|
|
|
|
|
2023-05-23 23:38:37 +02:00
|
|
|
sf::Vector2f TrackingView::getSize() const
|
2023-05-10 11:30:11 +02:00
|
|
|
{
|
2023-05-14 22:23:25 +02:00
|
|
|
return view->getSize();
|
|
|
|
}
|
|
|
|
|
2023-05-23 23:38:37 +02:00
|
|
|
sf::Vector2f TrackingView::getCenter() const
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
|
|
|
return view->getCenter();
|
|
|
|
}
|
|
|
|
|
2023-05-23 23:38:37 +02:00
|
|
|
void TrackingView::followTarget()
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
2023-05-24 01:15:05 +02:00
|
|
|
auto trackingPoint = getCollectiveTrackingPoint();
|
2023-05-24 15:21:53 +02:00
|
|
|
if (DEVELOPER_MODE) {
|
|
|
|
marker->coordinates.set(IsometricCoordinates(trackingPoint));
|
|
|
|
}
|
2023-05-14 22:23:25 +02:00
|
|
|
|
2023-05-24 15:21:53 +02:00
|
|
|
// Calculate distance to target to check how to handle it
|
|
|
|
auto currentCenter = view->getCenter();
|
|
|
|
auto vectorToTarget = trackingPoint - currentCenter;
|
|
|
|
float distanceToTarget = length(vectorToTarget);
|
|
|
|
|
|
|
|
if (distanceToTarget <= freeMoveRadius)
|
|
|
|
{
|
|
|
|
// Nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move view to place tracking-point at edge of area
|
2023-05-24 15:36:49 +02:00
|
|
|
auto deltaToDesiredView = normalize(vectorToTarget);
|
|
|
|
|
|
|
|
if (distanceToTarget <= dynamicFollowRadius) {
|
|
|
|
// Reduce delta to make it less jaring
|
|
|
|
deltaToDesiredView *= VIEW_DYNAMIC_FOLLOW_SPEED * (distanceToTarget - freeMoveRadius);
|
|
|
|
} else {
|
|
|
|
// Hard follow
|
|
|
|
deltaToDesiredView *= dynamicFollowRadius;
|
|
|
|
}
|
2023-05-10 11:30:11 +02:00
|
|
|
|
2023-05-24 15:36:49 +02:00
|
|
|
moveCenter(deltaToDesiredView);
|
2023-05-14 22:23:25 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
void TrackingView::moveCenter(sf::Vector2<float> delta)
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
2023-05-24 01:15:05 +02:00
|
|
|
view->move(delta);
|
|
|
|
hasViewChanged = true;
|
2023-05-14 22:23:25 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
void TrackingView::draw(sf::RenderWindow *window) const
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
2023-05-24 15:21:53 +02:00
|
|
|
if (!DEVELOPER_MODE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
marker->draw(window);
|
2023-05-14 22:23:25 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
void TrackingView::addTrackable(ITrackable *trackable)
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
2023-05-24 01:15:05 +02:00
|
|
|
trackables.push_back(trackable);
|
2023-05-14 22:23:25 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
sf::Vector2f TrackingView::getCollectiveTrackingPoint() const
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
2023-05-24 14:29:08 +02:00
|
|
|
sf::Vector2f minPoint = trackables[0]->getTrackablePosition();
|
|
|
|
sf::Vector2f maxPoint = minPoint;
|
2023-05-14 22:23:25 +02:00
|
|
|
|
2023-05-24 14:29:08 +02:00
|
|
|
// Find min and max point coordinates for x and y axis over all trackables
|
2023-05-24 01:15:05 +02:00
|
|
|
for (auto trackable : trackables)
|
|
|
|
{
|
2023-05-24 14:29:08 +02:00
|
|
|
auto trackableCoordinates = trackable->getTrackablePosition();
|
|
|
|
auto trackableSize = trackable->getTrackableSize();
|
|
|
|
|
|
|
|
auto minPointX = trackableCoordinates.x - trackableSize.x / 2.f;
|
|
|
|
auto maxPointX = trackableCoordinates.x + trackableSize.x / 2.f;
|
|
|
|
auto minPointY = trackableCoordinates.y - trackableSize.y / 2.f;
|
|
|
|
auto maxPointY = trackableCoordinates.y + trackableSize.y / 2.f;
|
|
|
|
|
|
|
|
if (minPointX < minPoint.x)
|
2023-05-24 01:15:05 +02:00
|
|
|
{
|
2023-05-24 14:29:08 +02:00
|
|
|
minPoint.x = minPointX;
|
|
|
|
}
|
|
|
|
if (maxPointX > maxPoint.x)
|
|
|
|
{
|
|
|
|
maxPoint.x = maxPointX;
|
|
|
|
}
|
|
|
|
if (minPointY < minPoint.y)
|
|
|
|
{
|
|
|
|
minPoint.y = minPointY;
|
|
|
|
}
|
|
|
|
if (maxPointY > maxPoint.y)
|
|
|
|
{
|
|
|
|
maxPoint.y = maxPointY;
|
2023-05-24 01:15:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-24 14:29:08 +02:00
|
|
|
return minPoint + (maxPoint - minPoint) / 2.f;
|
2023-05-14 22:23:25 +02:00
|
|
|
}
|
|
|
|
|
2023-05-24 01:15:05 +02:00
|
|
|
void TrackingView::processTrackableStates()
|
2023-05-14 22:23:25 +02:00
|
|
|
{
|
2023-05-24 01:15:05 +02:00
|
|
|
// Remove trackables that have ended tracking
|
|
|
|
std::remove_if(trackables.begin(), trackables.end(), [](ITrackable *trackable)
|
|
|
|
{
|
|
|
|
return trackable->getTrackableState() == TrackableState::END_TRACKING;
|
|
|
|
});
|
2023-05-14 22:23:25 +02:00
|
|
|
}
|
2023-05-24 15:21:53 +02:00
|
|
|
|
|
|
|
void TrackingView::setCenter(sf::Vector2<float> newCenter)
|
|
|
|
{
|
|
|
|
view->setCenter(newCenter);
|
|
|
|
hasViewChanged = true;
|
|
|
|
}
|