allow custom orbit rotations directions
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "ModuleOwnerComponent.h"
|
||||
#include "MovementIntentComponent.h"
|
||||
#include "MovementIntentSystem.h"
|
||||
#include "OrbitMath.h"
|
||||
#include "PositionComponent.h"
|
||||
#include "RallyBehavior.h"
|
||||
#include "RepairBehavior.h"
|
||||
@@ -553,12 +554,13 @@ TEST_CASE("BehaviorSystem: repair ship orbits damaged friendly ship",
|
||||
REQUIRE(winnerOf(f.admin, repairShip) == BehaviorKind::Repair);
|
||||
REQUIRE(intent(f.admin, repairShip).active);
|
||||
|
||||
// Orbit at orbit_factor * max repair range (REQ-SHP-ORBIT): the movement
|
||||
// destination lies exactly the orbit radius from the target's center.
|
||||
// Orbit at orbit_factor * max repair range (REQ-SHP-ORBIT): the intent carries
|
||||
// the target's center and the orbit radius; MovementIntentSystem turns these
|
||||
// into a point on the orbit circle when it steers.
|
||||
const float orbitRadius = f.admin.get<RepairBehavior>(repairShip).orbitRadius_tiles;
|
||||
REQUIRE(orbitRadius > 0.0f);
|
||||
REQUIRE((intent(f.admin, repairShip).target - pos(f.admin, friendly).value).length()
|
||||
== Approx(orbitRadius));
|
||||
REQUIRE(intent(f.admin, repairShip).target == pos(f.admin, friendly).value);
|
||||
REQUIRE(intent(f.admin, repairShip).orbitRadius_tiles == Approx(orbitRadius));
|
||||
}
|
||||
|
||||
TEST_CASE("BehaviorSystem: repair ship heals damaged ally within repair range",
|
||||
@@ -821,10 +823,12 @@ TEST_CASE("BehaviorSystem: salvage ship orbits nearest scrap", "[behavior]")
|
||||
REQUIRE(winnerOf(f.admin, ship) == BehaviorKind::SalvageScrap);
|
||||
REQUIRE(intent(f.admin, ship).active);
|
||||
|
||||
// Orbit at orbit_factor * max collection range (REQ-SHP-ORBIT).
|
||||
// Orbit at orbit_factor * max collection range (REQ-SHP-ORBIT): the intent
|
||||
// carries the scrap center and the orbit radius.
|
||||
const float orbitRadius = f.admin.get<SalvageScrapBehavior>(ship).orbitRadius_tiles;
|
||||
REQUIRE(orbitRadius > 0.0f);
|
||||
REQUIRE((intent(f.admin, ship).target - scrapPos).length() == Approx(orbitRadius));
|
||||
REQUIRE(intent(f.admin, ship).target == scrapPos);
|
||||
REQUIRE(intent(f.admin, ship).orbitRadius_tiles == Approx(orbitRadius));
|
||||
}
|
||||
|
||||
TEST_CASE("BehaviorSystem: salvage ship collects scrap on arrival", "[behavior]")
|
||||
@@ -1150,7 +1154,7 @@ TEST_CASE("SensorRange: salvage ship ignores scrap beyond sensor range", "[senso
|
||||
// Orbit movement (REQ-SHP-ORBIT)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("Orbit: combat ship aims at a point on the orbit circle around its target",
|
||||
TEST_CASE("Orbit: combat ship's intent carries the target center and orbit radius",
|
||||
"[orbit]")
|
||||
{
|
||||
Fixture f;
|
||||
@@ -1163,9 +1167,10 @@ TEST_CASE("Orbit: combat ship aims at a point on the orbit circle around its tar
|
||||
REQUIRE(winnerOf(f.admin, player) == BehaviorKind::Attack);
|
||||
const float orbitRadius = f.admin.get<AttackBehavior>(player).orbitRadius_tiles;
|
||||
REQUIRE(orbitRadius > 0.0f);
|
||||
// The movement destination lies exactly the orbit radius from the enemy center.
|
||||
REQUIRE((intent(f.admin, player).target - pos(f.admin, enemy).value).length()
|
||||
== Approx(orbitRadius));
|
||||
// The intent carries the enemy center and the orbit radius; the orbit point is
|
||||
// resolved later by MovementIntentSystem.
|
||||
REQUIRE(intent(f.admin, player).target == pos(f.admin, enemy).value);
|
||||
REQUIRE(intent(f.admin, player).orbitRadius_tiles == Approx(orbitRadius));
|
||||
}
|
||||
|
||||
TEST_CASE("Orbit: rally ship orbits the rally point at the configured rally radius",
|
||||
@@ -1181,7 +1186,8 @@ TEST_CASE("Orbit: rally ship orbits the rally point at the configured rally radi
|
||||
REQUIRE(winnerOf(f.admin, player) == BehaviorKind::Rally);
|
||||
const float orbitRadius = f.admin.get<RallyBehavior>(player).orbitRadius_tiles;
|
||||
REQUIRE(orbitRadius == Approx(static_cast<float>(f.cfg.world.rallyOrbitRadius_tiles)));
|
||||
REQUIRE((intent(f.admin, player).target - rallyPoint).length() == Approx(orbitRadius));
|
||||
REQUIRE(intent(f.admin, player).target == rallyPoint);
|
||||
REQUIRE(intent(f.admin, player).orbitRadius_tiles == Approx(orbitRadius));
|
||||
}
|
||||
|
||||
TEST_CASE("Orbit: combat ship settles near the orbit radius and circles a stationary target",
|
||||
@@ -1218,3 +1224,39 @@ TEST_CASE("Orbit: combat ship settles near the orbit radius and circles a statio
|
||||
// The ship is circling: its angular position around the target has moved.
|
||||
REQUIRE(std::abs(angleAfter - angleBefore) > 0.05f);
|
||||
}
|
||||
|
||||
TEST_CASE("OrbitMath: sign mirrors the orbit destination across the radial",
|
||||
"[orbit]")
|
||||
{
|
||||
const QVector2D center(0.0f, 0.0f);
|
||||
const QVector2D shipPos(5.0f, 0.0f);
|
||||
const float radius = 5.0f;
|
||||
|
||||
const QVector2D ccw = OrbitMath::computeOrbitDestination(shipPos, center, radius, +1.0f);
|
||||
const QVector2D cw = OrbitMath::computeOrbitDestination(shipPos, center, radius, -1.0f);
|
||||
|
||||
// Both lie exactly on the orbit circle.
|
||||
REQUIRE((ccw - center).length() == Approx(radius));
|
||||
REQUIRE((cw - center).length() == Approx(radius));
|
||||
// Opposite tangential lead: CCW leads to +y, CW to -y; x components match.
|
||||
REQUIRE(ccw.y() > 0.0f);
|
||||
REQUIRE(cw.y() < 0.0f);
|
||||
REQUIRE(ccw.y() == Approx(-cw.y()));
|
||||
REQUIRE(ccw.x() == Approx(cw.x()));
|
||||
}
|
||||
|
||||
TEST_CASE("OrbitMath: orbit sign follows the ship's tangential velocity",
|
||||
"[orbit]")
|
||||
{
|
||||
const QVector2D center(0.0f, 0.0f);
|
||||
const QVector2D shipPos(5.0f, 0.0f); // radial points +x
|
||||
|
||||
// Tangential +y velocity is counter-clockwise around the center → +1.
|
||||
REQUIRE(OrbitMath::resolveOrbitSign(shipPos, center, QVector2D(0.0f, 1.0f)) == Approx(1.0f));
|
||||
// Tangential -y velocity is clockwise → -1.
|
||||
REQUIRE(OrbitMath::resolveOrbitSign(shipPos, center, QVector2D(0.0f, -1.0f)) == Approx(-1.0f));
|
||||
// Radial velocity (toward/away from center) is ambiguous → fallback +1.
|
||||
REQUIRE(OrbitMath::resolveOrbitSign(shipPos, center, QVector2D(-1.0f, 0.0f)) == Approx(1.0f));
|
||||
// Zero velocity (e.g. freshly spawned) → fallback +1.
|
||||
REQUIRE(OrbitMath::resolveOrbitSign(shipPos, center, QVector2D(0.0f, 0.0f)) == Approx(1.0f));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user