diff --git a/src/Makefile.am b/src/Makefile.am index 93f222d..c8f0344 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,7 +20,7 @@ Lephisto3D_SOURCES = main.cpp glfreetype.cpp body.cpp space.cpp ship.cpp player. star.cpp frame.cpp ship_cpanel.cpp sector_view.cpp mtrand.cpp world_view.cpp system_view.cpp \ star_system.cpp sector.cpp system_info_view.cpp generic_system_view.cpp date.cpp space_station.cpp \ space_station_view.cpp model_body.cpp ship_type.cpp info_view.cpp model_coll_mesh_data.cpp \ - object_viewer_view.cpp custom_starsystems.cpp serializer.cpp sfx.cpp + object_viewer_view.cpp custom_starsystems.cpp serializer.cpp sfx.cpp ship_ai.cpp Lephisto3D_LDADD = sbre/libsbre.a collider/libcollider.a libgui.a ModelViewer_SOURCES = sbre_viewer.cpp glfreetype.cpp diff --git a/src/body.h b/src/body.h index b89f56e..bdf6c13 100644 --- a/src/body.h +++ b/src/body.h @@ -19,7 +19,7 @@ public: virtual void SetPosition(vector3d p) = 0; virtual vector3d GetPosition(void) const = 0; /* Within frame. */ virtual void SetVelocity(vector3d v) { assert(0); } - virtual vector3d GetVelocity(void) { assert(0); return vector3d(0.0); } + virtual vector3d GetVelocity(void) const { assert(0); return vector3d(0.0); } virtual double GetRadius(void) const = 0 ; virtual double GetMass(void) const { assert(0); return 0; } virtual void SetRotMatrix(const matrix4x4d& r) {}; diff --git a/src/dynamic_body.cpp b/src/dynamic_body.cpp index 7906396..5c6f565 100644 --- a/src/dynamic_body.cpp +++ b/src/dynamic_body.cpp @@ -148,7 +148,7 @@ void DynamicBody::SetRotMatrix(const matrix4x4d& r) { SetPosition(pos); } -void DynamicBody::GetRotMatrix(matrix4x4d& m) { +void DynamicBody::GetRotMatrix(matrix4x4d& m) const{ m = m_orient; m[12] = 0; m[13] = 0; @@ -175,7 +175,7 @@ void DynamicBody::SetMassDistributionFromCollMesh(const CollMesh* m) { SetMass(m_mass); } -vector3d DynamicBody::GetAngularMomentum(void) { +vector3d DynamicBody::GetAngularMomentum(void) const { return m_angInertia * m_angVel; } @@ -183,11 +183,11 @@ DynamicBody::~DynamicBody(void) { } -vector3d DynamicBody::GetAngVelocity(void) { +vector3d DynamicBody::GetAngVelocity(void) const { return m_angVel; } -vector3d DynamicBody::GetVelocity(void) { +vector3d DynamicBody::GetVelocity(void) const { return m_vel; } diff --git a/src/dynamic_body.h b/src/dynamic_body.h index f3a6aee..3c837c0 100644 --- a/src/dynamic_body.h +++ b/src/dynamic_body.h @@ -10,20 +10,20 @@ public: DynamicBody(void); virtual ~DynamicBody(void); virtual void SetRotMatrix(const matrix4x4d& r); - virtual void GetRotMatrix(matrix4x4d& m); + virtual void GetRotMatrix(matrix4x4d& m) const; virtual void SetVelocity(vector3d v); virtual void SetPosition(vector3d p); virtual vector3d GetPosition(void) const; - virtual vector3d GetVelocity(void); - vector3d GetAngVelocity(void); + virtual vector3d GetVelocity(void) const; + vector3d GetAngVelocity(void) const; void SetAngVelocity(vector3d v); void SetMesh(ObjMesh* m); virtual bool OnCollision(Body* b, Uint32 flags) { return true; } - vector3d GetAngularMomentum(void); + vector3d GetAngularMomentum(void) const; double GetAngularInertia(void) const { return m_angInertia; } void SetMassDistributionFromCollMesh(const CollMesh* m); void DisableBodyOnly(void) { m_enabled = false; } - bool IsEnabled(void) { return m_enabled; } + bool IsEnabled(void) const { return m_enabled; } virtual void Disable(void); virtual void Enable(void); virtual double GetMass(void) const { return m_mass; } diff --git a/src/ship.cpp b/src/ship.cpp index 7a7a0a5..b5d2c78 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -192,7 +192,7 @@ vector3d Ship::CalcRotDamping(void) { } void Ship::SetThrusterState(enum ShipType::Thruster t, float level) { - m_thrusters[t] = level; + m_thrusters[t] = CLAMP(level, 0.0, 1.0); } void Ship::ClearThrusterState(void) { @@ -325,7 +325,7 @@ void Ship::TimeStepUpdate(const float timeStep) { const ShipType& stype = GetShipType(); for(int i = 0; i < ShipType::THRUSTER_MAX; i++) { - float force = timeStep * stype.linThrust[i] * m_thrusters[i]; + float force = stype.linThrust[i]*m_thrusters[i]; switch(i) { case ShipType::THRUSTER_REAR: case ShipType::THRUSTER_FRONT: @@ -373,38 +373,6 @@ void Ship::TimeStepUpdate(const float timeStep) { if(m_testLanded) TestLanded(); } -void Ship::AITimeStep(const float timeStep) { - bool done = false; - - if(m_todo.size() != 0) { - AIInstruction& inst = m_todo.front(); - switch(inst.cmd) { - case DO_KILL: - done = AICmdKill(static_cast(inst.arg)); - break; - case DO_NOTHING: done = true; break; - } - } - if(done) { - printf("AI '%s' succesfully executed %d:'%s'\n", GetLabel().c_str(), m_todo.front().cmd, - static_cast(m_todo.front().arg)->GetLabel().c_str()); - m_todo.pop_front(); - } -} - -bool Ship::AICmdKill(const Ship* enemy) { - /* Needs to deal with frames, large distances, and success. */ - if(GetFrame() == enemy->GetFrame()) { - vector3d dir = vector3d::Normalize(enemy->GetPosition() - GetPosition()); - AIFaceDirection(dir); - } - return false; -} - -void Ship::AIInstruct(enum AICommand cmd, void* arg) { - m_todo.push_back(AIInstruction(cmd, arg)); -} - void Ship::NotifyDeath(const Body* const dyingBody) { if(GetNavTarget() == dyingBody) SetNavTarget(0); @@ -455,28 +423,6 @@ void Ship::SetCombatTarget(Body* const target) { L3D::worldView->UpdateCommsOptions(); } -/* Orient so our -ve z axis == dir. ie.. So that direction points forwards. */ -void Ship::AIFaceDirection(const vector3d& dir) { - matrix4x4d rot; - GetRotMatrix(rot); - rot = rot.InverseOf(); - const vector3d zaxis = vector3d(-rot[2], -rot[6], -rot[10]); - vector3d rotaxis = vector3d::Cross(zaxis, dir); - const float dot = vector3d::Dot(dir, zaxis); - /* If facing > 90 degrees away then max turn rate.. */ - if(dot < 0) rotaxis.Normalize(); - rotaxis = rot*rotaxis; - ClearThrusterState(); - /* We still must apply rotation damping. */ - rotaxis -= CalcRotDamping(); - SetAngThrusterState(0, rotaxis.x); - SetAngThrusterState(1, rotaxis.y); - SetAngThrusterState(2, rotaxis.z); - if(dot > 0) SetThrusterState(ShipType::THRUSTER_REAR, 1.0); - if(dot > 0.95f) SetGunState(0,1); - else SetGunState(0,0); -} - bool Ship::IsFiringLasers(void) { for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { if(m_gunState[i]) return true; diff --git a/src/ship.h b/src/ship.h index d1ba0c0..952b4bf 100644 --- a/src/ship.h +++ b/src/ship.h @@ -48,6 +48,8 @@ public: FlightState GetFlightState(void) const { return m_flightState; } float GetWheelState(void) const { return m_wheelState; } void AIFaceDirection(const vector3d& dir); + void AIAccelToModelRelativeVelocity(const vector3d v); + void AIModelCoordsMatchSpeedRelTo(const vector3d v, const Ship*); EquipSet m_equipment; diff --git a/src/ship_ai.cpp b/src/ship_ai.cpp new file mode 100644 index 0000000..0aaf44b --- /dev/null +++ b/src/ship_ai.cpp @@ -0,0 +1,145 @@ +#include "libs.h" +#include "ship.h" +#include "l3d.h" + +void Ship::AITimeStep(const float timeStep) { + bool done = false; + + if(m_todo.size() != 0) { + AIInstruction& inst = m_todo.front(); + switch(inst.cmd) { + case DO_KILL: + done = AICmdKill(static_cast(inst.arg)); + break; + case DO_NOTHING: done = true; break; + } + } + if(done) { + printf("AI '%s' successfullyexecuted %d:'%s'\n", GetLabel().c_str(), m_todo.front().cmd, + static_cast(m_todo.front().arg)->GetLabel().c_str()); + m_todo.pop_front(); + } +} + +bool Ship::AICmdKill(const Ship* enemy) { + SetGunState(0,0); + /* Needs to deal with frames, large distances and success. */ + if(GetFrame() == enemy->GetFrame()) { + const float dist = (enemy->GetPosition() - GetPosition()).Length(); + vector3d dir = vector3d::Normalize(enemy->GetPosition() - GetPosition()); + if(dist > 500.0) { + AIFaceDirection(dir); + /* Thunder at player at 400m/sec. */ + AIModelCoordsMatchSpeedRelTo(vector3d(0,0,-400), enemy); + /* Fire guns if aiming good enough. */ + matrix4x4d rot; + GetRotMatrix(rot); + const vector3d zaxis = vector3d(-rot[8], -rot[9], -rot[10]); + const float dot = vector3d::Dot(dir, vector3d(-rot[8], -rot[9], -rot[10])); + if(dot > 0.95f) SetGunState(0,1); + } else { + /* If we are too close, turn away! */ + AIFaceDirection(-dir); + AIModelCoordsMatchSpeedRelTo(vector3d(0,0,-1000), enemy); + } + } + return false; +} + +void Ship::AIInstruct(enum AICommand cmd, void* arg) { + m_todo.push_back(AIInstruction(cmd, arg)); +} + +/* Orient so our -ve z axis == dir. ie.. So that direction points forwards. */ +void Ship::AIFaceDirection(const vector3d& dir) { + matrix4x4d rot; + GetRotMatrix(rot); + rot = rot.InverseOf(); + const vector3d zaxis = vector3d(-rot[2], -rot[6], -rot[10]); + vector3d rotaxis = vector3d::Cross(zaxis, dir); + vector3d angVel = rot*GetAngVelocity(); + const float dot = vector3d::Dot(dir, zaxis); + /* If facing > 90 degrees away then max turn rate. */ + if(dot < 0) rotaxis.Normalize(); + rotaxis = rot*rotaxis; + vector3d desiredAngVelChange = 4*(rotaxis - angVel); + ClearThrusterState(); + /* We still must apply rotation damping. */ + rotaxis -= CalcRotDamping(); + SetAngThrusterState(0, desiredAngVelChange.x); + SetAngThrusterState(1, desiredAngVelChange.y); + SetAngThrusterState(2, desiredAngVelChange.z); +} + +void Ship::AIModelCoordsMatchSpeedRelTo(const vector3d v, const Ship* other) { + matrix4x4d m; GetRotMatrix(m); + vector3d relToVel = m.InverseOf() * other->GetVelocity() + v; + AIAccelToModelRelativeVelocity(relToVel); +} + +/* + * Try to reach this model-relative velocity. + * (0,0,-100) would mean going 100m/s forward. + */ +void Ship::AIAccelToModelRelativeVelocity(const vector3d v) { + const ShipType& stype = GetShipType(); + + vector3d relVel = GetVelocity(); // - enemy->GetVelocity(); + matrix4x4d m; GetRotMatrix(m); + relVel = m.InverseOf() * relVel; + + vector3d difVel = v - relVel; + /* We want to change velocity by difVel.. */ + //SetVelocty(m*(relVel+difVel)); + const float invMass = 1.0 / GetMass(); + + if(difVel.x > 0) { + /* Figure out biggest accel can get, and then what we need this timestep. */ + float velChange = L3D::GetTimeStep() * stype.linThrust[ShipType::THRUSTER_RIGHT] * invMass; + float thrust; + if(velChange < difVel.x) thrust = 1.0; + else thrust = difVel.x / velChange; + thrust *= thrust; /* This is just to hide control jiggle. */ + SetThrusterState(ShipType::THRUSTER_RIGHT, thrust); + } else { + float velChange = L3D::GetTimeStep() * stype.linThrust[ShipType::THRUSTER_LEFT] * invMass; + float thrust; + if(velChange > difVel.x) thrust = 1.0; + else thrust = difVel.x / velChange; + thrust *= thrust; + SetThrusterState(ShipType::THRUSTER_LEFT, thrust); + } + + if(difVel.y > 0) { + float velChange = L3D::GetTimeStep() * stype.linThrust[ShipType::THRUSTER_TOP] * invMass; + float thrust; + if(velChange < difVel.y) thrust = 1.0; + else thrust = difVel.y / velChange; + thrust *= thrust; + SetThrusterState(ShipType::THRUSTER_TOP, thrust); + } else { + float velChange = L3D::GetTimeStep() * stype.linThrust[ShipType::THRUSTER_BOTTOM] * invMass; + float thrust; + if(velChange > difVel.y) thrust = 1.0; + else thrust = difVel.y / velChange; + thrust *= thrust; + SetThrusterState(ShipType::THRUSTER_BOTTOM, thrust); + } + + if(difVel.z > 0) { + float velChange = L3D::GetTimeStep() * stype.linThrust[ShipType::THRUSTER_FRONT] * invMass; + float thrust; + if(velChange < difVel.z) thrust = 1.0; + else thrust = difVel.z / velChange; + thrust *= thrust; + SetThrusterState(ShipType::THRUSTER_FRONT, thrust); + } else { + float velChange = L3D::GetTimeStep() * stype.linThrust[ShipType::THRUSTER_REAR] * invMass; + float thrust; + if(velChange > difVel.z) thrust = 1.0; + else thrust = difVel.z / velChange; + thrust *= thrust; + SetThrusterState(ShipType::THRUSTER_REAR, thrust); + } +} + diff --git a/src/ship_type.cpp b/src/ship_type.cpp index 97d6afb..d3f2909 100644 --- a/src/ship_type.cpp +++ b/src/ship_type.cpp @@ -7,7 +7,7 @@ const ShipType ShipType::types[] = { * Sirius corporation make a range of lovely ships! */ "Sirius Interdictor", 61, - { 4e8, -4e8, 1e8, -1e8, -1e8, 1e8 }, + { 4e6, -4e6, 1e6, -1e6, -1e6, 1e6 }, 1e7, { { vector3f(0, -0.5, 0), vector3f(0, 0, -1) }, @@ -22,7 +22,7 @@ const ShipType ShipType::types[] = { */ "Ladybird Starfighter", 62, - { 1e8, -1e8, 1e8, -1e8, -1e8, 1e8 }, + { 1e6, -1e6, 1e6, -1e6, -1e6, 1e6 }, 1e7, { { vector3f(0, -0.5, 0), vector3f(0, 0, -1) }, @@ -34,7 +34,7 @@ const ShipType ShipType::types[] = { { "Flowerfairy Heavy Trader", 63, - { 1e7, -1e7, 1e6, -1e6, -1e6, 1e6 }, + { 1e6, -1e6, 1e6, -1e6, -1e6, 1e6 }, 1e7, { { vector3f(0, -0.5, 0), vector3f(0, 0, -1) },