[Add] More basic AI functions.
[Change] Split AI into it's own unit. [Note] Space battles are fun!
This commit is contained in:
parent
03fe164ce1
commit
235b1c6c5b
@ -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
|
||||
|
@ -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) {};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
58
src/ship.cpp
58
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<const Ship*>(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<Ship*>(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;
|
||||
|
@ -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;
|
||||
|
||||
|
145
src/ship_ai.cpp
Normal file
145
src/ship_ai.cpp
Normal file
@ -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<const Ship*>(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<Ship*>(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);
|
||||
}
|
||||
}
|
||||
|
@ -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) },
|
||||
|
Loading…
Reference in New Issue
Block a user