make ships orbit their targets

This commit is contained in:
2026-06-15 21:09:40 +02:00
parent 6b7c3df64a
commit 4153b7e2f5
17 changed files with 209 additions and 20 deletions

View File

@@ -0,0 +1,45 @@
#pragma once
#include <cmath>
#include <QVector2D>
// Orbit movement helper (REQ-SHP-ORBIT). Behaviors that keep a ship circling a
// target (attack, repair, salvage, rally) feed the result of this function as the
// movement intent destination instead of the target's center.
namespace OrbitMath
{
// Lead angle (radians) by which the radial direction is rotated to produce
// tangential motion. The fixed positive (counter-clockwise) sense makes the
// orbit direction stable for the duration of orbiting a given target.
constexpr float kOrbitLeadAngle_rad = 0.6f;
// Returns a destination on the orbit circle of `radius` around `target`. The
// result always lies exactly `radius` from `target`, so steering toward it
// both corrects the standoff distance and advances the ship tangentially.
// A radius of zero or less falls back to the target center (legacy "approach
// the target" behavior), e.g. when the ship has no tool range to orbit at.
inline QVector2D computeOrbitDestination(const QVector2D& shipPos,
const QVector2D& target, float radius)
{
if (radius <= 0.0f) { return target; }
QVector2D radial = shipPos - target;
float length = radial.length();
if (length < 1.0e-4f)
{
// Ship sits on the target; pick an arbitrary radial direction.
radial = QVector2D(1.0f, 0.0f);
length = 1.0f;
}
const QVector2D radialDirection = radial / length;
const float cosLead = std::cos(kOrbitLeadAngle_rad);
const float sinLead = std::sin(kOrbitLeadAngle_rad);
const QVector2D leadDirection(
radialDirection.x() * cosLead - radialDirection.y() * sinLead,
radialDirection.x() * sinLead + radialDirection.y() * cosLead);
return target + radius * leadDirection;
}
}