[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.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 \
|
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 \
|
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
|
Lephisto3D_LDADD = sbre/libsbre.a collider/libcollider.a libgui.a
|
||||||
|
|
||||||
ModelViewer_SOURCES = sbre_viewer.cpp glfreetype.cpp
|
ModelViewer_SOURCES = sbre_viewer.cpp glfreetype.cpp
|
||||||
|
@ -19,7 +19,7 @@ public:
|
|||||||
virtual void SetPosition(vector3d p) = 0;
|
virtual void SetPosition(vector3d p) = 0;
|
||||||
virtual vector3d GetPosition(void) const = 0; /* Within frame. */
|
virtual vector3d GetPosition(void) const = 0; /* Within frame. */
|
||||||
virtual void SetVelocity(vector3d v) { assert(0); }
|
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 GetRadius(void) const = 0 ;
|
||||||
virtual double GetMass(void) const { assert(0); return 0; }
|
virtual double GetMass(void) const { assert(0); return 0; }
|
||||||
virtual void SetRotMatrix(const matrix4x4d& r) {};
|
virtual void SetRotMatrix(const matrix4x4d& r) {};
|
||||||
|
@ -148,7 +148,7 @@ void DynamicBody::SetRotMatrix(const matrix4x4d& r) {
|
|||||||
SetPosition(pos);
|
SetPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicBody::GetRotMatrix(matrix4x4d& m) {
|
void DynamicBody::GetRotMatrix(matrix4x4d& m) const{
|
||||||
m = m_orient;
|
m = m_orient;
|
||||||
m[12] = 0;
|
m[12] = 0;
|
||||||
m[13] = 0;
|
m[13] = 0;
|
||||||
@ -175,7 +175,7 @@ void DynamicBody::SetMassDistributionFromCollMesh(const CollMesh* m) {
|
|||||||
SetMass(m_mass);
|
SetMass(m_mass);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector3d DynamicBody::GetAngularMomentum(void) {
|
vector3d DynamicBody::GetAngularMomentum(void) const {
|
||||||
return m_angInertia * m_angVel;
|
return m_angInertia * m_angVel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,11 +183,11 @@ DynamicBody::~DynamicBody(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vector3d DynamicBody::GetAngVelocity(void) {
|
vector3d DynamicBody::GetAngVelocity(void) const {
|
||||||
return m_angVel;
|
return m_angVel;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector3d DynamicBody::GetVelocity(void) {
|
vector3d DynamicBody::GetVelocity(void) const {
|
||||||
return m_vel;
|
return m_vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,20 +10,20 @@ public:
|
|||||||
DynamicBody(void);
|
DynamicBody(void);
|
||||||
virtual ~DynamicBody(void);
|
virtual ~DynamicBody(void);
|
||||||
virtual void SetRotMatrix(const matrix4x4d& r);
|
virtual void SetRotMatrix(const matrix4x4d& r);
|
||||||
virtual void GetRotMatrix(matrix4x4d& m);
|
virtual void GetRotMatrix(matrix4x4d& m) const;
|
||||||
virtual void SetVelocity(vector3d v);
|
virtual void SetVelocity(vector3d v);
|
||||||
virtual void SetPosition(vector3d p);
|
virtual void SetPosition(vector3d p);
|
||||||
virtual vector3d GetPosition(void) const;
|
virtual vector3d GetPosition(void) const;
|
||||||
virtual vector3d GetVelocity(void);
|
virtual vector3d GetVelocity(void) const;
|
||||||
vector3d GetAngVelocity(void);
|
vector3d GetAngVelocity(void) const;
|
||||||
void SetAngVelocity(vector3d v);
|
void SetAngVelocity(vector3d v);
|
||||||
void SetMesh(ObjMesh* m);
|
void SetMesh(ObjMesh* m);
|
||||||
virtual bool OnCollision(Body* b, Uint32 flags) { return true; }
|
virtual bool OnCollision(Body* b, Uint32 flags) { return true; }
|
||||||
vector3d GetAngularMomentum(void);
|
vector3d GetAngularMomentum(void) const;
|
||||||
double GetAngularInertia(void) const { return m_angInertia; }
|
double GetAngularInertia(void) const { return m_angInertia; }
|
||||||
void SetMassDistributionFromCollMesh(const CollMesh* m);
|
void SetMassDistributionFromCollMesh(const CollMesh* m);
|
||||||
void DisableBodyOnly(void) { m_enabled = false; }
|
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 Disable(void);
|
||||||
virtual void Enable(void);
|
virtual void Enable(void);
|
||||||
virtual double GetMass(void) const { return m_mass; }
|
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) {
|
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) {
|
void Ship::ClearThrusterState(void) {
|
||||||
@ -325,7 +325,7 @@ void Ship::TimeStepUpdate(const float timeStep) {
|
|||||||
|
|
||||||
const ShipType& stype = GetShipType();
|
const ShipType& stype = GetShipType();
|
||||||
for(int i = 0; i < ShipType::THRUSTER_MAX; i++) {
|
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) {
|
switch(i) {
|
||||||
case ShipType::THRUSTER_REAR:
|
case ShipType::THRUSTER_REAR:
|
||||||
case ShipType::THRUSTER_FRONT:
|
case ShipType::THRUSTER_FRONT:
|
||||||
@ -373,38 +373,6 @@ void Ship::TimeStepUpdate(const float timeStep) {
|
|||||||
if(m_testLanded) TestLanded();
|
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) {
|
void Ship::NotifyDeath(const Body* const dyingBody) {
|
||||||
if(GetNavTarget() == dyingBody)
|
if(GetNavTarget() == dyingBody)
|
||||||
SetNavTarget(0);
|
SetNavTarget(0);
|
||||||
@ -455,28 +423,6 @@ void Ship::SetCombatTarget(Body* const target) {
|
|||||||
L3D::worldView->UpdateCommsOptions();
|
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) {
|
bool Ship::IsFiringLasers(void) {
|
||||||
for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
|
for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
|
||||||
if(m_gunState[i]) return true;
|
if(m_gunState[i]) return true;
|
||||||
|
@ -48,6 +48,8 @@ public:
|
|||||||
FlightState GetFlightState(void) const { return m_flightState; }
|
FlightState GetFlightState(void) const { return m_flightState; }
|
||||||
float GetWheelState(void) const { return m_wheelState; }
|
float GetWheelState(void) const { return m_wheelState; }
|
||||||
void AIFaceDirection(const vector3d& dir);
|
void AIFaceDirection(const vector3d& dir);
|
||||||
|
void AIAccelToModelRelativeVelocity(const vector3d v);
|
||||||
|
void AIModelCoordsMatchSpeedRelTo(const vector3d v, const Ship*);
|
||||||
|
|
||||||
EquipSet m_equipment;
|
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 corporation make a range of lovely ships!
|
||||||
*/
|
*/
|
||||||
"Sirius Interdictor", 61,
|
"Sirius Interdictor", 61,
|
||||||
{ 4e8, -4e8, 1e8, -1e8, -1e8, 1e8 },
|
{ 4e6, -4e6, 1e6, -1e6, -1e6, 1e6 },
|
||||||
1e7,
|
1e7,
|
||||||
{
|
{
|
||||||
{ vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
|
{ vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
|
||||||
@ -22,7 +22,7 @@ const ShipType ShipType::types[] = {
|
|||||||
*/
|
*/
|
||||||
"Ladybird Starfighter",
|
"Ladybird Starfighter",
|
||||||
62,
|
62,
|
||||||
{ 1e8, -1e8, 1e8, -1e8, -1e8, 1e8 },
|
{ 1e6, -1e6, 1e6, -1e6, -1e6, 1e6 },
|
||||||
1e7,
|
1e7,
|
||||||
{
|
{
|
||||||
{ vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
|
{ vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
|
||||||
@ -34,7 +34,7 @@ const ShipType ShipType::types[] = {
|
|||||||
{
|
{
|
||||||
"Flowerfairy Heavy Trader",
|
"Flowerfairy Heavy Trader",
|
||||||
63,
|
63,
|
||||||
{ 1e7, -1e7, 1e6, -1e6, -1e6, 1e6 },
|
{ 1e6, -1e6, 1e6, -1e6, -1e6, 1e6 },
|
||||||
1e7,
|
1e7,
|
||||||
{
|
{
|
||||||
{ vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
|
{ vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
|
||||||
|
Loading…
Reference in New Issue
Block a user