[Add] More basic AI functions.
[Change] Split AI into it's own unit. [Note] Space battles are fun!
This commit is contained in:
		
							parent
							
								
									27ad4c8450
								
							
						
					
					
						commit
						762d7fcd3e
					
				| @ -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
	 Rtch90
						Rtch90