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

103 lines
2.8 KiB
C++
Raw Normal View History

#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;
}