fix mutually canceling orbits

This commit is contained in:
2026-06-17 20:50:31 +02:00
parent 0cf3d64983
commit e0e11b7933
6 changed files with 54 additions and 11 deletions

View File

@@ -18,24 +18,32 @@ namespace OrbitMath
constexpr float kOrbitLeadAngle_rad = 0.6f;
// Returns the orbit sense (+1 counter-clockwise, -1 clockwise) that matches
// the ship's current movement around `center`, so steering reinforces the
// motion the ship already has. When the velocity is nearly radial or near
// zero (e.g. a head-on approach or a freshly spawned ship) the sense is
// the ship's movement around `center`, so steering reinforces the motion the
// ship already has. The sense is taken from the ship's velocity *relative to
// the center* (`centerVelocity`): for a moving target this both removes the
// target's own motion from the decision and dissolves the degenerate case
// where two ships orbiting each other translate in a straight line — there
// their shared velocity cancels, leaving ~zero relative velocity. When the
// relative velocity is nearly radial or near zero (a head-on approach, a
// freshly spawned ship, or that mutual-translation case) the sense is
// ill-defined; this is an unstable point the ship leaves within a tick or
// two, so a deterministic fallback of +1 is returned.
inline float resolveOrbitSign(const QVector2D& shipPos, const QVector2D& center,
const QVector2D& velocity)
const QVector2D& velocity,
const QVector2D& centerVelocity = QVector2D())
{
const QVector2D radial = shipPos - center;
const QVector2D relativeVelocity = velocity - centerVelocity;
const float radialLength = radial.length();
const float velocityLength = velocity.length();
const float velocityLength = relativeVelocity.length();
if (radialLength < 1.0e-4f || velocityLength < 1.0e-4f)
{
return 1.0f;
}
// z-component of radial x velocity, normalised to sin(angle) between them.
const float cross = radial.x() * velocity.y() - radial.y() * velocity.x();
// z-component of radial x relativeVelocity, normalised to sin(angle).
const float cross = radial.x() * relativeVelocity.y()
- radial.y() * relativeVelocity.x();
const float sinAngle = cross / (radialLength * velocityLength);
constexpr float kRadialEpsilon = 1.0e-3f;