src/StateBattle/ShipAI.cpp

Go to the documentation of this file.
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 }

Generated on Mon Jan 8 22:34:12 2007 for CrownandCutlass by  doxygen 1.4.7