00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "HelperFunctions.h"
00023 #include "MilitaryUnit.h"
00024 #include "Player.h"
00025 #include "Sound.h"
00026 #include "BattleEntry.h"
00027 #include "BattleUnitData.h"
00028 #include "GameState.h"
00029
00030 namespace {
00032 const FLOAT overheadMovementRate = 0.15f;
00033 }
00034
00035 MilitaryUnit::MilitaryUnit(Vec3D initalPosition, Player* owner, UnitType unitType, const int armySize, Vec3D unitSize) :
00036 m_currPos(initalPosition),
00037 m_teamColor(owner->color()),
00038 m_unitSize(unitSize),
00039 m_direction(Vec3D(0,90.0f,0)),
00040 m_goalPos(initalPosition),
00041 m_unitType(unitType),
00042 m_armySize(armySize),
00043 m_currState(BUSY),
00044 m_collisionSize(unitSize*2),
00045 m_pOwner(owner),
00046 m_overheadShortcutKey(-1)
00047 {
00048 }
00049
00050 MilitaryUnit::~MilitaryUnit(void)
00051 {
00052 }
00053
00054 void MilitaryUnit::goal(Vec3D dest)
00055 {
00056 this->m_goalPos = dest;
00057 m_currState = BUSY;
00058 }
00059
00060 Vec3D MilitaryUnit::goalPosition() const
00061 {
00062 return this->m_goalPos;
00063 }
00064
00065 bool MilitaryUnit::contains(Vec3D that) const
00066 {
00067
00068 Vec2D pt(math_translateWorldToScreen(that));
00069 Vec2D unitPt(math_translateWorldToScreen(m_currPos));
00070 return math_dist2D(pt,unitPt)<0.03f;
00071 }
00072
00073 bool MilitaryUnit::around(Vec3D that)
00074 {
00075 return math_dist2D(Vec2D(this->m_currPos.x, this->m_currPos.y), Vec2D(that.x, that.y)) < BATTLE_RADIUS;
00076 }
00077
00078 bool MilitaryUnit::collision(const MilitaryUnit* const that) const
00079 {
00080 return (
00081 (m_currPos.z + m_collisionSize.z > that->position().z) &&
00082 (m_currPos.z - m_collisionSize.z < that->position().z) &&
00083 (m_currPos.x + m_collisionSize.x > that->position().x) &&
00084 (m_currPos.x - m_collisionSize.x < that->position().x) &&
00085 (m_currPos.y + m_collisionSize.y > that->position().y) &&
00086 (m_currPos.y - m_collisionSize.y < that->position().y) );
00087 }
00088
00089 bool MilitaryUnit::fightingCollision(const MilitaryUnit* const that) const
00090 {
00091 const FLOAT distanceForAFight(25.0f);
00092 return distanceForAFight > math_distPlanar3D(this->m_currPos, that->m_currPos);
00093 }
00094
00095 bool MilitaryUnit::nearEachOther(const MilitaryUnit* const that) const
00096 {
00097 const FLOAT distance(50.0f);
00098 return distance > math_distPlanar3D(this->m_currPos, that->m_currPos);
00099 }
00100
00101 void MilitaryUnit::move()
00102 {
00103 if (this->m_currState == WANTS_TO_STOP && !OverheadCollisonWithIdleUnit(this) && !OverheadCollisionWithCity(this))
00104 {
00105 m_currState = IDLE;
00106 }
00107 if (this->m_currState != IDLE) {
00108
00109 Vec3D savePos( m_currPos );
00110 Vec3D targetVec = m_goalPos - m_currPos;
00111 FLOAT targetDir = clipAngle( 90-D3DXToDegree( atan2f( targetVec.x, targetVec.y ) ) );
00112 FLOAT currentDir = m_direction.x;
00113 FLOAT delta;
00114 if(targetDir>currentDir)
00115 {
00116 delta = targetDir - currentDir;
00117 if(delta>180.0f) delta = delta - 360.0f;
00118 }
00119 else
00120 {
00121 delta = targetDir - currentDir;
00122 if(delta<-180.0f) delta = 360.0f - delta;
00123 }
00124
00125 const FLOAT turnRate = 0.4f;
00126 FLOAT turnAngle = delta;
00127 if (delta > turnRate ) turnAngle = turnRate;
00128 else if (delta < -turnRate ) turnAngle = -turnRate;
00129 else turnAngle = delta;
00130 m_direction.x = clipAngle( currentDir + turnAngle );
00131
00132
00133 FLOAT speed = 0.0f;
00134 if (absf(delta)<10.0f ) speed = 0.1f;
00135 else if( absf(delta)<90.0f ) speed = 0.06f;
00136 if (D3DXVec3Length(&targetVec) < 3.0f )
00137 {
00138 m_currPos += (m_goalPos-m_currPos) * 0.06f;
00139 speed = 0.0f;
00140 }
00141 if (speed>0.0f)
00142 {
00143 FLOAT rad = D3DXToRadian( m_direction.x );
00144 m_currPos += speed * Vec3D( cosf(rad), sinf(rad), 0.0f );
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 if (!GameState::worldMap().bounds.contains(Vec2D(this->m_currPos.x, this->m_currPos.y)) )
00166 m_currPos = savePos;
00167
00168
00169 FLOAT thresh = 0.1f;
00170 if (this->m_currPos.x <= m_goalPos.x + thresh && this->m_currPos.x >= m_goalPos.x - thresh &&
00171 this->m_currPos.y <= m_goalPos.y + thresh && this->m_currPos.y >= m_goalPos.y - thresh )
00172 {
00173 if (OverheadCollisonWithIdleUnit(this) || OverheadCollisionWithCity(this))
00174 {
00175 this->m_currState = WANTS_TO_STOP;
00176 FLOAT newGoal = sys_randFloat() * 40.0F;
00177 this->m_goalPos = Vec3D(m_currPos.x + newGoal, m_currPos.y + newGoal, 0);
00178 } else
00179 {
00180 m_currState = IDLE;
00181 }
00182 }
00183 } else if (OverheadCollisonWithIdleUnit(this) || OverheadCollisionWithCity(this))
00184 {
00185 this->m_currState = WANTS_TO_STOP;
00186 FLOAT newGoal = sys_randFloat() * 40.0F;
00187 this->m_goalPos = Vec3D(m_currPos.x + newGoal, m_currPos.y + newGoal, 0);
00188 } else
00189 {
00190 this->m_currState = IDLE;
00191 }
00192
00193
00194 m_currPos.z = terrain_getHeight( artWork->worldMap, m_currPos.x, m_currPos.y ) + 0.33f;
00195 }
00196
00197 void MilitaryUnit::drawBox(void) const
00198 {
00199 Vec3D pos = m_currPos;
00200 pos.z += 0.3f;
00201 FLOAT angle = (FLOAT)( (Globals::currGameTick*5) % 360 );
00202 mesh_render( artWork->circle, pos, Vec3D(5.0f,5.0f,0.001f), Vec3D(angle,0,0), artWork->colorGreen );
00203 }
00204
00205 Player* MilitaryUnit::owner(void) const
00206 {
00207 return this->m_pOwner;
00208 }
00209
00210 Vec3D MilitaryUnit::color() const
00211 {
00212 return m_teamColor;
00213 }
00214
00215 Vec3D MilitaryUnit::position(void) const
00216 {
00217 return this->m_currPos;
00218 }
00219
00220 void MilitaryUnit::drawColor() const
00221 {
00222
00223 Vec3D p1(m_currPos), p2(m_currPos), p3(m_currPos), p4(m_currPos);
00224 const int delta = 4;
00225 p1.x -= delta;
00226 p2.y += delta;
00227 p3.x += delta;
00228 p4.y -= delta;
00229 Vec2D s1( math_translateWorldToScreen(p1) );
00230 Vec2D s2( math_translateWorldToScreen(p2) );
00231 Vec2D s3( math_translateWorldToScreen(p3) );
00232 Vec2D s4( math_translateWorldToScreen(p4) );
00233 overlay_line( s1,s2, m_teamColor );
00234 overlay_line( s2,s3, m_teamColor );
00235 overlay_line( s3,s4, m_teamColor );
00236 overlay_line( s4,s1, m_teamColor );
00237 }
00238
00239 void MilitaryUnit::setShortcutKey(int key)
00240 {
00241 m_overheadShortcutKey = key;
00242 }
00243
00244 int MilitaryUnit::shortcutKey() const
00245 {
00246 return m_overheadShortcutKey;
00247 }
00248
00250
00251 LightTank::LightTank(const Vec3D & initialPosition, Player* owner, const int armySize)
00252 : MilitaryUnit(initialPosition, owner, UnitTypes::LIGHT_TANK, armySize, BattleUnitData::getObj().lightTankSize()),
00253 m_turretSize(BattleUnitData::getObj().lightTankTurretSize())
00254 {
00255 }
00256
00257 LightTank::~LightTank(void)
00258 {
00259 }
00260
00261 void LightTank::draw(void) const
00262 {
00263 mesh_render( artWork->lightTank_mesh, this->m_currPos, this->m_unitSize, this->m_direction, artWork->lightTank_texture, 0,
00264 this->color());
00265 mesh_render( artWork->lightTankTurret_mesh, this->m_currPos, this->m_turretSize, this->m_direction, artWork->lightTank_texture, 0,
00266 this->color());
00267 }
00268
00270 HeavyTank::HeavyTank(const Vec3D & initialPosition, Player* owner, const int armySize)
00271 : MilitaryUnit(initialPosition, owner, UnitTypes::HEAVY_TANK, armySize, BattleUnitData::getObj().heavyTankSize()),
00272 m_turretSize(BattleUnitData::getObj().heavyTankTurretSize())
00273 {
00274 }
00275
00276 HeavyTank::~HeavyTank(void)
00277 {
00278 }
00279
00280 void HeavyTank::draw() const
00281 {
00282 mesh_render( artWork->heavyTank_mesh, this->m_currPos, this->m_unitSize, this->m_direction, artWork->heavyTank_texture, 0,
00283 this->color());
00284 mesh_render( artWork->heavyTankTurret_mesh, this->m_currPos, this->m_turretSize, this->m_direction, artWork->heavyTank_texture, 0,
00285 this->color());
00286 }
00287
00289 RocketLauncher::RocketLauncher(const Vec3D & initialPosition, Player* owner, const int armySize)
00290 : MilitaryUnit(initialPosition, owner, UnitTypes::LAUNCHER, armySize, BattleUnitData::getObj().launcherSize())
00291 {
00292 }
00293
00294 RocketLauncher::~RocketLauncher(void)
00295 {
00296 }
00297
00298 void RocketLauncher::draw() const
00299 {
00300 mesh_render( artWork->launcher_mesh, this->m_currPos, this->m_unitSize, this->m_direction, artWork->launcher_texture, 0,
00301 this->color());
00302 }
00303
00305 Artillery::Artillery(const Vec3D & initialPosition, Player* owner, const int armySize)
00306 : MilitaryUnit(initialPosition, owner, UnitTypes::ARTILLERY, armySize, BattleUnitData::getObj().artillerySize()),
00307 m_turretSize(BattleUnitData::getObj().artilleryTurretSize())
00308 {
00309 }
00310
00311 Artillery::~Artillery(void)
00312 {
00313 }
00314
00315 void Artillery::draw() const
00316 {
00317 mesh_render( artWork->artillery_mesh, this->m_currPos, this->m_unitSize, this->m_direction, artWork->artillery_texture, 0,
00318 this->color());
00319 mesh_render( artWork->artilleryTurret_mesh, this->m_currPos, this->m_turretSize, this->m_direction, artWork->artillery_texture, 0,
00320 this->color());
00321 }
00322
00324 Jet::Jet(const Vec3D & initialPosition, Player* owner, const int armySize, const int cityID )
00325 : MilitaryUnit(initialPosition, owner, UnitTypes::JET, armySize, BattleUnitData::getObj().jetSize()),
00326 m_cityCenter(GameState::getCity(cityID)->position()), m_ang(0.0f), m_liftOffAng(0.0f),
00327 m_cityID(cityID), m_jetState(CIRCLE)
00328 {
00329 m_currState = IDLE;
00330
00331 m_distFromCity = ((GameState::getCity(m_cityID)->jetGaurdSize() / 4)+1)*15.0f;
00332 m_currPos.x = m_cityCenter.x + (m_distFromCity * (cosf(m_ang*(D3DX_PI/180))));
00333 m_currPos.y = m_cityCenter.y + (m_distFromCity * (sinf(m_ang*(D3DX_PI/180))));
00334 m_currPos.z = 20.0f;
00335
00336 GameState::getCity(m_cityID)->addJetGaurd();
00337
00338
00339 }
00340
00341
00342 const float Jet::s_dTheta = 0.5f;
00343 const float Jet::s_speed = 0.2f;
00344
00345 Jet::~Jet(void)
00346 {
00347
00348 GameState::getCity(m_cityID)->deleteJetGuard();
00349
00350 }
00351
00352
00353 int Jet::getCityID()
00354 {
00355 return m_cityID;
00356 }
00357
00358 void Jet::draw() const
00359 {
00360 mesh_render( artWork->jet_mesh, this->m_currPos, this->m_unitSize, this->m_direction, artWork->jet_texture, 0,
00361 this->color());
00362 }
00363
00364 void Jet::goal(Vec3D dest)
00365 {
00366 vector<City*>& cities = GameState::cities();
00367 for(CityIter iter=cities.begin(); iter != cities.end(); ++iter)
00368 {
00369
00370 if( (*iter)->color() == this->color() && math_distPlanar3D((*iter)->position(),dest) < 40.0f )
00371 {
00372
00373
00374 GameState::getCity(m_cityID)->deleteJetGuard();
00375 m_currState = BUSY;
00376 m_jetState = LIFTOFF;
00377 m_cityID = (*iter)->uniqueID();
00378 m_cityCenter = (*iter)->position();
00379 (*iter)->addJetGaurd();
00380
00381 m_distFromCity = (((*iter)->jetGaurdSize() / 4)+1)*15.0f;
00382 m_ang = 0.0f;
00383 m_liftOffAng = math_getDir(m_currPos, (*iter)->position());
00384 m_goalPos.x = m_cityCenter.x + (m_distFromCity * (cosf(m_ang*(D3DX_PI/180))));
00385 m_goalPos.y = m_cityCenter.y + (m_distFromCity * (sinf(m_ang*(D3DX_PI/180))));
00386 m_velocity = m_goalPos - m_currPos;
00387 m_velocity *= (1/(sqrtf( m_velocity.x*m_velocity.x + m_velocity.y*m_velocity.y )))*s_speed ;
00388
00389 break;
00390 }
00391
00392
00393 }
00394 }
00395
00396 const float Jet::s_dZ(0.1f);
00397
00398 void Jet::move()
00399 {
00400 if(m_currState == IDLE)
00401 {
00402
00403
00404 m_ang += (OverheadCollisonWithIdleUnit(this) ? (sys_randInt()*s_dTheta) : s_dTheta);
00405 m_direction.x = math_clipAngle(m_ang + 90.0f);
00406 m_currPos.x = m_cityCenter.x + (m_distFromCity * (cosf(m_ang*(D3DX_PI/180))));
00407 m_currPos.y = m_cityCenter.y + (m_distFromCity * (sinf(m_ang*(D3DX_PI/180))));
00408 }
00409 else if (m_currState == BUSY)
00410 {
00411
00412 if(m_jetState == LIFTOFF)
00413 {
00414 if(Helper::abs(m_direction.x - m_liftOffAng) < 1.0f)
00415 {
00416 m_jetState = MOVING;
00417 return;
00418 }
00419 else
00420 {
00421 m_direction.x = math_clipAngle(m_direction.x+1.0f);
00422 m_currPos.z += s_dZ;
00423 }
00424 }
00425 else if(m_jetState == MOVING)
00426 {
00427 if( Helper::abs(m_currPos.x - m_goalPos.x) < 0.1f && Helper::abs(m_currPos.y - m_goalPos.y) < 0.1f )
00428 {
00429 m_jetState = ARRIVE;
00430 }
00431 else
00432 {
00433
00434 m_currPos.x += m_velocity.x;
00435 m_currPos.y += m_velocity.y;
00436 }
00437 }
00438 else if(m_jetState == ARRIVE)
00439 {
00440
00441
00442 bool atHeight = !((m_currPos.z - s_dZ) > 20.0f);
00443 if( !atHeight )
00444 m_currPos.z -= s_dZ;
00445
00446
00447 bool atAng = !(Helper::abs(m_direction.x - 90.0f) > 1.0f);
00448 if( !atAng )
00449 m_direction.x = math_clipAngle(m_direction.x + 1.0f);
00450
00451 if( atHeight && atAng )
00452 {
00453 m_jetState = CIRCLE;
00454 m_currState = IDLE;
00455 }
00456 }
00457
00458 }
00459 }