103 lines
2.8 KiB
C++
103 lines
2.8 KiB
C++
|
#include "collectable_sim_ground.hpp"
|
||
|
|
||
|
#include <utility>
|
||
|
#include "../../../../config.h"
|
||
|
|
||
|
void CollectableSimGround::closeAllHoles()
|
||
|
{
|
||
|
segments.clear();
|
||
|
|
||
|
// Create one segment for the ground
|
||
|
auto groundSegment = std::make_shared<CollectableSimGroundSegment>(world);
|
||
|
groundSegment->body->createSquare(b2_kinematicBody,
|
||
|
{0, -COLLECTABLES_SIM_GROUND_THICKNESS / 2.f},
|
||
|
{groundWidth, COLLECTABLES_SIM_GROUND_THICKNESS});
|
||
|
|
||
|
segments.push_back(groundSegment);
|
||
|
}
|
||
|
|
||
|
CollectableSimGround::CollectableSimGround(std::shared_ptr<b2World> world, float groundWidth)
|
||
|
: world(std::move(world))
|
||
|
{
|
||
|
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();
|
||
|
auto deltaToBorder = borderPoints - abs(leftCenter.x - leftSize.x / 2.f);
|
||
|
|
||
|
// Increase width if positive, decrease if negative
|
||
|
leftSize.x += deltaToBorder;
|
||
|
leftCenter.x -= deltaToBorder / 2.f;
|
||
|
|
||
|
leftSegment->setBoxSize(leftSize);
|
||
|
leftSegment->setCenter(leftCenter);
|
||
|
}
|
||
|
|
||
|
// Right segment
|
||
|
if (outerSegments.right != nullptr)
|
||
|
{
|
||
|
auto rightSegment = outerSegments.right->body;
|
||
|
auto rightCenter = rightSegment->getCenter();
|
||
|
auto rightSize = rightSegment->getSize();
|
||
|
auto deltaToBorder = borderPoints - abs(rightCenter.x + rightSize.x / 2.f);
|
||
|
|
||
|
// Increase width if positive, decrease if negative
|
||
|
rightSize.x += deltaToBorder;
|
||
|
rightCenter.x += deltaToBorder / 2.f;
|
||
|
|
||
|
rightSegment->setBoxSize(rightSize);
|
||
|
rightSegment->setCenter(rightCenter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|