Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/base/platform.cc')
-rw-r--r--src/game/base/platform.cc66
1 files changed, 44 insertions, 22 deletions
diff --git a/src/game/base/platform.cc b/src/game/base/platform.cc
index b5e92dc..4f18330 100644
--- a/src/game/base/platform.cc
+++ b/src/game/base/platform.cc
@@ -110,53 +110,74 @@ void Platform::frame(const unsigned long elapsed)
continue;
}
- // find a target for this slot
- Ship *current_enemy = 0;
- float current_distance = 0.0f;
-
- math::Vector3f projectile_location(location() + (axis() * slot->location()));
+ // target location in world coordinates
+ Ship *current_enemy = 0; // The enemy ship the slot will be targetting
+ float current_distance = 0.0f; // Distance to the target location
+ math::Vector3f current_aim; // Location to aim at
+
+ // slot and projectile location in world coordinates
+ const math::Vector3f projectile_location(location() + (axis() * slot->location()));
math::Vector3f projectile_direction;
math::Axis projectile_axis(axis() * slot->axis());
-
- math::Vector3f aim_location;
// we only need half the cone angle for the cosine calculation
const float conecos = cosf(slot->cone() * 0.5f);
- for (std::list<Ship *>::const_iterator enemy_it = enemylist.begin(); enemy_it != enemylist.end(); enemy_it++) {
+ for (std::list<Ship *>::const_iterator enemy_it = enemylist.begin(); enemy_it != enemylist.end(); enemy_it++)
+ {
+ // apply aim correction
+ // see https://www.reddit.com/r/gamedev/comments/16ceki/turret_aiming_formula/c7vbu2j
+
+ const math::Vector3f v((*enemy_it)->axis().forward() * (*enemy_it)->speed());
+ const math::Vector3f w((*enemy_it)->location() - projectile_location);
+
+ const float a = v.lengthsquared() - weapon->projectile_speed() * weapon->projectile_speed();
+ const float b = 2.0f * math::dotproduct(v, w);
+ const float c = w.lengthsquared();
- const float d = math::distance((*enemy_it)->location(), projectile_location);
+ const float D = b * b - 4.0f * a * c;
+ if (D < 0.0f)
+ {
+ continue;
+ }
+ const float t = math::min(sqrtf(D) - b , -sqrtf(D) - b) / (2.0f * a);
+ const math::Vector3f hitpoint((*enemy_it)->location() + v * t);
- if (d > weapon->projectile_range() + (*enemy_it)->radius()) {
+ // verify the hitpoint is within weapon's range
+ const float d = math::distance(hitpoint, projectile_location);
+ if (d > weapon->projectile_range() + (*enemy_it)->radius())
+ {
continue;
}
- if ((current_distance > 0) && (d > current_distance)) {
+ if ((current_distance > 0.0f) && (d > current_distance))
+ {
continue;
}
-
- aim_location.assign((*enemy_it)->location() + (*enemy_it)->axis().forward() * ( (*enemy_it)->radius() * 0.25f));
- projectile_direction.assign(aim_location - projectile_location);
+
+ projectile_direction.assign(hitpoint - projectile_location);
projectile_direction.normalize();
+ // verify the hitpoint is in the slot's cone-of-fire
const float cosa = math::dotproduct(projectile_direction, projectile_axis.forward());
-
- // check if the ship is in the slot's cone if fire
- if (cosa >= conecos) {
+ if (cosa >= conecos)
+ {
current_distance = d;
current_enemy = (*enemy_it);
+ current_aim.assign(hitpoint);
}
}
- if (current_enemy) {
- aim_location.assign(current_enemy->location() + current_enemy->axis().forward() * (current_enemy->radius() * 0.25f));
- projectile_direction.assign(aim_location - projectile_location);
+ if (current_enemy)
+ {
+ projectile_direction.assign(current_aim - projectile_location);
projectile_direction.normalize();
const float cosa = math::dotproduct(projectile_direction, projectile_axis.forward());
// point the projectile into the fire direction
math::Vector3f normal(math::crossproduct(projectile_direction, projectile_axis.forward()));
- if (normal.length() > MIN_DELTA) {
+ if (normal.length() > MIN_DELTA)
+ {
float sina = sqrt(1.0f - cosa * cosa);
normal.normalize();
@@ -184,4 +205,5 @@ void Platform::frame(const unsigned long elapsed)
}
}
-}
+} // namespace game
+