00001 /* Crown and Cutlass 00002 * Ship AI Object Code 00003 */ 00004 00005 #include "../Log.h" 00006 #include "../ccmath.h" 00007 #include "../Ship.h" 00008 #include "ShipAI.h" 00009 00010 #define CHASE_RANGE 12 00011 00012 ShipAI::ShipAI(Ship *shipIn, Ship *playerShipIn, float bulletSpeedIn) { 00013 m_ship = shipIn; 00014 m_playerShip = playerShipIn; 00015 00016 m_state = asFight; 00017 00018 m_reloaded = true; 00019 00020 m_bulletSpeed = bulletSpeedIn; 00021 00022 m_shipMaxDamage = m_ship->GetMaxDamage(); 00023 } 00024 00025 ShipAI::~ShipAI() { 00026 // Don't delete the ships, the Battle object will delete them 00027 } 00028 00029 void ShipAI::Update(unsigned int ticks, bool reloadedIn) { 00030 float dX, dZ; 00031 00032 m_reloaded = reloadedIn; 00033 00034 // It's weird that the order of these is reversed, but it works... 00035 dX = m_ship->m_x - m_playerShip->m_x; 00036 dZ = m_playerShip->m_z - m_ship->m_z; 00037 00038 m_distToPlayer = sqrt((dX*dX) + (dZ*dZ)); 00039 00040 if ((m_state != asFlee) && (m_ship->m_damage < (m_shipMaxDamage / 2)) && (m_playerShip->m_damage > (m_ship->m_damage * 1.5))) { 00041 m_state = asFlee; 00042 m_ship->SetSails(FULLSAILS); 00043 } 00044 00045 m_rotToPlayer = m_ship->m_rot - (atan2(dZ, dX) + M_PI); 00046 00047 if (m_rotToPlayer < -M_PI) { 00048 m_rotToPlayer += TWO_PI; 00049 } 00050 if (m_rotToPlayer > M_PI) { 00051 m_rotToPlayer -= TWO_PI; 00052 } 00053 00054 m_rotToHitPlayer = CalcAngleToHit(); 00055 00056 switch (m_state) { 00057 case asFight: 00058 UpdateFight(ticks); 00059 break; 00060 case asFlee: 00061 UpdateFlee(ticks); 00062 break; 00063 case asChase: 00064 UpdateChase(ticks); 00065 break; 00066 } 00067 //Log::logger->message("%d: ship %f, rot %f, rotHit %f, dist %f (%f)", state, ship->rot, rotToPlayer, rotToHitPlayer, distToPlayer, atan2(dZ, dX) + M_PI); 00068 } 00069 00070 void ShipAI::UpdateFight(unsigned int ticks) { 00071 if (m_distToPlayer > CHASE_RANGE) { 00072 m_state = asChase; 00073 m_ship->SetSails(FULLSAILS); 00074 } 00075 00076 if (m_reloaded) { 00077 if (fabs(-1*M_PI_2 - m_rotToHitPlayer) < degreesToRadians(10)) { 00078 m_fire = true; 00079 m_fireAngle = M_PI_2; 00080 } else if (fabs(M_PI_2 - m_rotToHitPlayer) < degreesToRadians(10)) { 00081 m_fire = true; 00082 m_fireAngle = -1*M_PI_2; 00083 } 00084 } 00085 00086 if (((m_rotToHitPlayer < 0) && (m_rotToHitPlayer > -1*M_PI_2)) || ((m_rotToHitPlayer > M_PI_2) && (m_rotToHitPlayer < M_PI))) { 00087 m_ship->SetRudder(RIGHT); 00088 } else { 00089 m_ship->SetRudder(LEFT); 00090 } 00091 } 00092 00093 void ShipAI::UpdateFlee(unsigned int ticks) { 00094 if ((m_rotToPlayer > 0) && (m_rotToPlayer < M_PI-0.03)) { 00095 m_ship->SetRudder(LEFT); 00096 } else if (m_rotToPlayer > 0.03-M_PI) { 00097 m_ship->SetRudder(RIGHT); 00098 } 00099 } 00100 00101 void ShipAI::UpdateChase(unsigned int ticks) { 00102 if (m_distToPlayer < CHASE_RANGE-(CHASE_RANGE*.3)) { 00103 m_state = asFight; 00104 m_ship->SetSails(HALFSAILS); 00105 } 00106 00107 if (m_rotToPlayer < -0.03) { 00108 m_ship->SetRudder(LEFT); 00109 } else if (m_rotToPlayer > 0.03) { 00110 m_ship->SetRudder(RIGHT); 00111 } 00112 } 00113 00114 bool ShipAI::ShouldFire(float *angleOut) { 00115 if (m_fire) { 00116 *angleOut = m_fireAngle; 00117 m_reloaded = false; 00118 m_fire = false; 00119 return true; 00120 } else { 00121 return false; 00122 } 00123 } 00124 00125 float ShipAI::CalcAngleToHit() { 00126 float dAngle; 00127 float drift = m_distToPlayer / m_bulletSpeed * m_ship->m_speed; 00128 00129 dAngle = atan2(drift, m_distToPlayer); 00130 if (m_rotToPlayer < 0) { 00131 dAngle = -1 * dAngle; 00132 } 00133 00134 return dAngle + m_rotToPlayer; 00135 }
1.4.7