holesome/src/game/physics/holes/ground/collectable_sim_ground.cpp

138 lines
3.8 KiB
C++
Raw Normal View History

#include "collectable_sim_ground.hpp"
#include <utility>
#include "../../../../config.h"
2023-07-05 01:06:57 +02:00
#include "../layouts/depth_hole_layout.hpp"
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
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-05 01:06:57 +02:00
leftCorner = hole.x + hole.width / 2.f;
}
// Create segment for the right side
createSegment(leftCorner, groundWidth / 2.f);
}
CollectableSimGround::CollectableSimGround(std::shared_ptr<b2World> world, float groundWidth)
2023-07-05 01:06:57 +02:00
: world(std::move(world)), groundWidth(0)
{
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-05 01:06:57 +02:00
createSegment(-borderPoints, rightPoint, outerSegments.left);
}
// 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-05 01:06:57 +02:00
createSegment(leftPoint, borderPoints, outerSegments.right);
}
}
2023-07-05 01:06:57 +02:00
void CollectableSimGround::createSegment(float leftCorner, float rightCorner,
std::shared_ptr<CollectableSimGroundSegment> segment)
{
if (leftCorner > rightCorner)
{
throw std::runtime_error("Left corner must be less than right corner");
}
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);
}
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;
}