Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2013-10-14 20:33:50 +0000
committerStijn Buys <ingar@osirion.org>2013-10-14 20:33:50 +0000
commitaabb379d84afab3679acc6dc4472d886dae88f39 (patch)
treee015d1c0b1ce904f543f50a905634cae68ddcda8
parent0ae585bf90031a95cec165bb6f0e25e337b9ecff (diff)
Separated autopilot from AI code, added basic formation flying.
-rw-r--r--src/game/base/npc.cc75
-rw-r--r--src/game/base/ship.cc142
-rw-r--r--src/game/base/ship.h12
3 files changed, 168 insertions, 61 deletions
diff --git a/src/game/base/npc.cc b/src/game/base/npc.cc
index bb4c180..dba7929 100644
--- a/src/game/base/npc.cc
+++ b/src/game/base/npc.cc
@@ -71,11 +71,8 @@ void NPC::frame(const unsigned long elapsed)
}
} else {
-
- // FIXME verify the leader is still alive
-
- // TODO pilot magic and mood witchcraft
+ // TODO pilot magic and mood witchcraft
if (leader()) {
// verify leader still exists
@@ -87,66 +84,22 @@ void NPC::frame(const unsigned long elapsed)
} else if (leader()->zone() == zone()) {
- // rotate towards leader: direction
- math::Vector3f d(leader()->location() - location());
- float distance = d.length();
-
- d.normalize();
-
- float direction_angle = math::dotproduct(axis().forward(), d);
- float direction_sign = math::sgnf(math::dotproduct(axis().left(), d));
-
- if (direction_sign < 0 ) {
- target_direction = direction_sign;
- } else if (direction_angle + MIN_DELTA < 1.0f ) {
- target_direction = direction_sign * direction_angle;
- } else {
- target_direction = 0.0f;
- }
-
- // rotate towards leader: pitch
- direction_angle = math::dotproduct(axis().forward(), d);
- direction_sign = math::sgnf(math::dotproduct(axis().up(), d));
-
- if (direction_sign < 0 ) {
- target_pitch = direction_sign;
- } else if (direction_angle + MIN_DELTA < 1.0f ) {
- target_pitch = direction_sign * direction_angle;
- } else {
- target_pitch = 0.0f;
- }
-
- const float r = 2.0f * (radius() + leader()->radius());
-
- if (distance > 2.0f * r + 50.0f) {
- if (state() == core::Entity::Normal) {
- // enable impulse drive
- func_impulse();
- }
- } else {
- if (state() == core::Entity::Impulse) {
-
- if (leader()->state() != core::Entity::Impulse) {
- // disbable impulse drive
- func_impulse();
- }
-
- } else if (state() == core::Entity::Normal) {
-
- if ((leader()->state() == core::Entity::Impulse) || (leader()->state() == core::Entity::ImpulseInitiate)) {
- // enable impulse drive
- func_impulse();
- }
+ if (leader()->state() == Docked) {
+
+ // TODO dock where the leader is docked
+ if (leader()->dock()) {
+ frame_autopilot_goto(elapsed, leader()->dock());
}
- }
-
- if (distance > 2.0f * r) {
- target_thrust = 1.0f;
- } else if (distance > r) {
- target_thrust = (distance - r ) / r;
} else {
- target_thrust = 0.0f;
+
+ if (math::distance(location(), leader()->location()) > 4.0f * ( radius() + leader()->radius())) {
+ // goto the leader
+ frame_autopilot_goto(elapsed, leader());
+ } else {
+ // formatian flying
+ frame_autopilot_formation(elapsed, leader());
+ }
}
} else {
diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc
index 6c5598e..23baa5d 100644
--- a/src/game/base/ship.cc
+++ b/src/game/base/ship.cc
@@ -990,4 +990,146 @@ void Ship::frame(const unsigned long elapsed)
}
+void Ship::frame_autopilot_goto(const unsigned long elapsed, const core::Entity *target)
+{
+ // reference radius used in calculations
+ const float r = radius() + target->radius();
+
+ // desired direction
+ math::Vector3f direction(target->location() - location());
+ const float distance = direction.length();
+ direction.normalize();
+
+ // transform direction from world coordinates to local entity coordinates
+ direction = axis().transpose() * direction;
+
+ if (direction.x() < 0) {
+ // target is behind the ship
+ target_direction = math::sgnf(direction.y());
+ target_pitch = 0.0f;
+
+ } else if (direction.x() + MIN_DELTA < 1.0f) {
+ // target is in front of the ship
+ target_direction = direction.y();
+ target_pitch = direction.z();
+ } else {
+ target_direction = 0.0f;
+ target_pitch = 0.0f;
+ }
+
+ target_roll = 0.0f;
+
+ // impulse or thruster
+ if (distance > r + 50.0f) {
+
+ if (state() == core::Entity::Normal) {
+ // enable impulse drive
+ func_impulse();
+ }
+
+ } else {
+
+ if (target->type() == core::Entity::Controlable) {
+
+ const core::EntityControlable *controlable = static_cast<const core::EntityControlable *>(target);
+
+ if (state() == core::Entity::Impulse) {
+
+ if (controlable->state() != core::Entity::Impulse) {
+ // disbable impulse drive
+ func_impulse();
+ }
+
+ } else if (state() == core::Entity::Normal) {
+
+ if ((controlable->state() == core::Entity::Impulse) || (controlable->state() == core::Entity::ImpulseInitiate)) {
+ // enable impulse drive
+ func_impulse();
+ }
+ }
+
+ } else {
+
+ if (state() == core::Entity::Impulse) {
+ func_impulse();
+ }
+ }
+ }
+
+ // thruster
+ if (distance > 4.0f * r) {
+ target_thrust = 1.0f;
+
+ } else if (distance > 2.0f * r ) {
+ target_thrust = (distance - 2.0f * r ) / 2.0f * r;
+
+ } else {
+ target_thrust = 0.0f;
+
+ // TODO autolevel
+ }
+}
+
+void Ship::frame_autopilot_formation(const unsigned long elapsed, const core::Entity *target)
+{
+ // transform the target's axis into local coordinates
+ const math::Axis reference(axis().transpose() * target->axis());
+
+ //const float distance = math::distance(location(), target->location());
+ //const float r = radius() + target->radius();
+
+ if (reference.forward().x() < 0) {
+ // target is behind the ship
+ target_direction = math::sgnf(reference.forward().y());
+ target_pitch = 0.0f;
+ target_roll = 0.0f;
+
+ } else if (reference.forward().x() + MIN_DELTA < 1.0f) {
+ // target is in front of the ship
+ target_direction = reference.forward().y();
+ target_pitch = reference.forward().z();
+ target_roll = 0.0f;
+
+ } else {
+ target_direction = 0.0f;
+ target_pitch = 0.0f;
+
+ if (reference.up().z() < 0) {
+ // upward-down
+ target_roll = math::sgnf(reference.up().y());
+ } else {
+ target_roll = reference.up().y();
+ }
+ }
+
+ if (target->type() == core::Entity::Controlable) {
+
+ const core::EntityControlable *controlable = static_cast<const core::EntityControlable *>(target);
+
+ target_thrust = controlable->thrust();
+
+ if (state() == core::Entity::Impulse) {
+
+ if (controlable->state() != core::Entity::Impulse) {
+ // disbable impulse drive
+ func_impulse();
+ }
+
+ } else if (state() == core::Entity::Normal) {
+
+ if ((controlable->state() == core::Entity::Impulse) || (controlable->state() == core::Entity::ImpulseInitiate)) {
+ // enable impulse drive
+ func_impulse();
+ }
+ }
+
+ } else {
+ if (state() == core::Entity::Impulse) {
+ // disable impulse drive
+ func_impulse();
+ }
+ }
+
+}
+
} // namespace game
diff --git a/src/game/base/ship.h b/src/game/base/ship.h
index 1de208d..ad2c71b 100644
--- a/src/game/base/ship.h
+++ b/src/game/base/ship.h
@@ -181,6 +181,18 @@ public:
void set_spawn(core::Entity *spawn);
+protected:
+
+ /**
+ * @brief autopilot goto target
+ * */
+ void frame_autopilot_goto(const unsigned long elapsed, const core::Entity *target);
+
+ /**
+ * @brief autopilot formation flying
+ * */
+ void frame_autopilot_formation(const unsigned long elapsed, const core::Entity *target);
+
private:
JumpPoint *find_closest_jumppoint();