2023-07-03 01:16:44 +02:00
|
|
|
#include "collectable_sim_ground.hpp"
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
#include "../../../../config.h"
|
2023-07-05 01:06:57 +02:00
|
|
|
#include "../layouts/depth_hole_layout.hpp"
|
2023-07-03 01:16:44 +02:00
|
|
|
|
|
|
|
void CollectableSimGround::closeAllHoles()
|
|
|
|
{
|
2023-07-05 01:06:57 +02:00
|
|
|
// Create one segment for the ground
|
|
|
|
createSegment(-groundWidth / 2.f, groundWidth / 2.f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CollectableSimGround::createLayout(DepthHoleLayout &layout)
|
|
|
|
{
|
|
|
|
// TODO: Check if layout changed at all before clearing segments
|
2023-07-03 01:16:44 +02:00
|
|
|
segments.clear();
|
|
|
|
|
2023-07-05 01:06:57 +02:00
|
|
|
if (layout.holes.empty())
|
|
|
|
{
|
|
|
|
closeAllHoles();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort holes from left to right
|
|
|
|
std::sort(layout.holes.begin(), layout.holes.end(),
|
|
|
|
[](DepthHoleDescription a, DepthHoleDescription b)
|
|
|
|
{
|
|
|
|
return a.x < b.x;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create segments for holes
|
|
|
|
float leftCorner = -groundWidth / 2.f;
|
|
|
|
for (auto &hole: layout.holes)
|
|
|
|
{
|
|
|
|
auto rightCorner = hole.x - hole.width / 2.f;
|
|
|
|
createSegment(leftCorner, rightCorner);
|
2023-07-03 01:16:44 +02:00
|
|
|
|
2023-07-05 01:06:57 +02:00
|
|
|
leftCorner = hole.x + hole.width / 2.f;
|
|
|
|
}
|
|
|
|
// Create segment for the right side
|
|
|
|
createSegment(leftCorner, groundWidth / 2.f);
|
2023-07-03 01:16:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CollectableSimGround::CollectableSimGround(std::shared_ptr<b2World> world, float groundWidth)
|
2023-07-05 01:06:57 +02:00
|
|
|
: world(std::move(world)), groundWidth(0)
|
2023-07-03 01:16:44 +02:00
|
|
|
{
|
|
|
|
setGroundWidth(groundWidth);
|
|
|
|
closeAllHoles();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CollectableSimGround::setGroundWidth(float width)
|
|
|
|
{
|
|
|
|
if (width <= 0)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Ground width must be greater than 0");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width == groundWidth)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
groundWidth = width;
|
|
|
|
updateOuterSegmentsToWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CollectableSimGround::updateOuterSegmentsToWidth()
|
|
|
|
{
|
|
|
|
auto outerSegments = getOuterSegments();
|
|
|
|
auto borderPoints = groundWidth / 2.f;
|
|
|
|
|
|
|
|
// Left segment
|
|
|
|
if (outerSegments.left != nullptr)
|
|
|
|
{
|
|
|
|
auto leftSegment = outerSegments.left->body;
|
|
|
|
auto leftCenter = leftSegment->getCenter();
|
|
|
|
auto leftSize = leftSegment->getSize();
|
2023-07-05 01:06:57 +02:00
|
|
|
auto rightPoint = leftCenter.x + leftSize.x / 2.f;
|
2023-07-03 01:16:44 +02:00
|
|
|
|
2023-07-05 01:06:57 +02:00
|
|
|
createSegment(-borderPoints, rightPoint, outerSegments.left);
|
2023-07-03 01:16:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Right segment
|
|
|
|
if (outerSegments.right != nullptr)
|
|
|
|
{
|
|
|
|
auto rightSegment = outerSegments.right->body;
|
|
|
|
auto rightCenter = rightSegment->getCenter();
|
|
|
|
auto rightSize = rightSegment->getSize();
|
2023-07-05 01:06:57 +02:00
|
|
|
auto leftPoint = rightCenter.x - rightSize.x / 2.f;
|
2023-07-03 01:16:44 +02:00
|
|
|
|
2023-07-05 01:06:57 +02:00
|
|
|
createSegment(leftPoint, borderPoints, outerSegments.right);
|
|
|
|
}
|
|
|
|
}
|
2023-07-03 01:16:44 +02:00
|
|
|
|
2023-07-05 01:06:57 +02:00
|
|
|
void CollectableSimGround::createSegment(float leftCorner, float rightCorner,
|
|
|
|
std::shared_ptr<CollectableSimGroundSegment> segment)
|
|
|
|
{
|
|
|
|
if (leftCorner > rightCorner)
|
|
|
|
{
|
2023-07-05 15:21:45 +02:00
|
|
|
// Segment would have negative width, don't create it and leave empty instead
|
|
|
|
return;
|
2023-07-03 01:16:44 +02:00
|
|
|
}
|
2023-07-05 01:06:57 +02:00
|
|
|
|
|
|
|
if (segment == nullptr)
|
|
|
|
{
|
|
|
|
segment = std::make_shared<CollectableSimGroundSegment>(world);
|
|
|
|
segments.push_back(segment);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto center = sf::Vector2f((leftCorner + rightCorner) / 2.f, -COLLECTABLES_SIM_GROUND_THICKNESS / 2.f);
|
|
|
|
auto size = sf::Vector2f(rightCorner - leftCorner, COLLECTABLES_SIM_GROUND_THICKNESS);
|
|
|
|
|
|
|
|
segment->body->createSquare(b2_kinematicBody, center, size);
|
2023-07-03 01:16:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CollectableSimGround::SideSegments CollectableSimGround::getOuterSegments(int holeId)
|
|
|
|
{
|
|
|
|
SideSegments sideSegments;
|
|
|
|
|
|
|
|
for (const auto &segment: segments)
|
|
|
|
{
|
|
|
|
// If valid holeId, match left hole id
|
|
|
|
// If invalid holeId, get outer segment
|
|
|
|
if ((segment->leftHoleId == holeId && holeId >= 0)
|
|
|
|
|| (segment->rightHoleId < 0 && holeId < 0))
|
|
|
|
{
|
|
|
|
sideSegments.right = segment;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((segment->rightHoleId == holeId && holeId >= 0)
|
|
|
|
|| (segment->leftHoleId < 0 && holeId < 0))
|
|
|
|
{
|
|
|
|
sideSegments.left = segment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sideSegments;
|
|
|
|
}
|