//============================================================================== // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //============================================================================== //============================================================================== // File: cSoldier.cpp // Project: Shooting Star // Author: Jarmo Hekkanen // Copyrights (c) 2003 2ndPoint ry (www.2ndpoint.fi) //------------------------------------------------------------------------------ // Revision history //============================================================================== //============================================================================== // Includes #include "cSoldier.hpp" #include #include "Debug.hpp" #include "cWorld.hpp" #include "cMixer.hpp" #include "cWeapon.hpp" #include "cAnimationManager.hpp" #include "cParticleSystem.hpp" #include "cTextureManager.hpp" #include "cGib.hpp" #include "cBloodPool.hpp" //------------------------------------------------------------------------------ // Namespaces using namespace ShootingStar; // Constants const float TurnSpeed = 0.3f; const float FineTurnSpeed = 0.1f; const float WalkForwardSpeed = 0.2f; const float WalkBackwardSpeed = 0.15f; //============================================================================== //! Constructor cSoldier::cSoldier (string animationPrefix): mTurning (false), mTurningRight (false), mTurnToTarget (false), mTurnTarget (0.0f), mFineAim (false), mStrafe (false), mWalking (false), mWalkingForward (false), mWalkingBackward (false), mWalkingLeft (false), mWalkingRight (false), mCurrentWeapon (-1), mSoundDeath (cMixer::GetInstance ().LoadSound ("death.wav")), mSoundHurt (cMixer::GetInstance ().LoadSound ("hurt.wav")) { SetVelocity (cVector2f (0.0f, 0.0f)); SetCollisionModel (CollisionModel_Circle); SetCollisionRadius (41.0f); SetContactModel (ContactModel_Slide); SetEmittingAngle (18.0f); SetEmittingDistance (40.0f); // Load animations cAnimationManager &animManager = cAnimationManager::GetInstance (); // Stand mStandAnim.SetAnimation (animManager.LoadAnimation (animationPrefix + string ("_stand"))); mStandAnim.SetNumberOfFrames (1); mStandAnim.SetFrameDelay (10000); // Walk mWalkAnim.SetAnimation (animManager.LoadAnimation (animationPrefix + string ("_walk"))); mWalkAnim.SetNumberOfFrames (8); mWalkAnim.SetFrameDelay (100); // Shoot mShootAnim.SetAnimation (animManager.LoadAnimation (animationPrefix + string ("_shoot"))); mShootAnim.SetNumberOfFrames (1); mShootAnim.SetFrameDelay (10000); // Walk & shoot mWalkShootAnim.SetAnimation (animManager.LoadAnimation (animationPrefix + string ("_wshoot"))); mWalkShootAnim.SetNumberOfFrames (7); mWalkShootAnim.SetFrameDelay (100); mAnimation = mStandAnim; mCurrentAnimation = Animation_Stand; // Blood system mBlood = new cParticleSystem (70); mBlood->SetTexture (cTextureManager::GetInstance ().LoadTexture ("tuli2.png")); mBlood->SetEmitDelay (0); mBlood->SetStartColor (1.0f, 0.0f, 0.0f, 0.2f); mBlood->SetEndColor (1.0f, 0.0f, 0.0f, 0.0f); mBlood->SetSpeed (0.2f, 0.5f); mBlood->SetSize (32.0f * rand () / (RAND_MAX + 1.0f), 0.5f); mBlood->SetEnergy (500, 0.2f); mBlood->SetEmitter (this); mBlood->SetLayer (-1); cWorld::GetInstance ().SpawnObject (mBlood); //pBlood->SetBlending (true); }; //! Destructor cSoldier::~cSoldier (void) { }; void cSoldier::PullTrigger (void) { cWeapon *pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->PullTrigger (); } void cSoldier::ReleaseTrigger (void) { cWeapon *pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->ReleaseTrigger (); } //! Rendering interface void cSoldier::Render (Uint32 deltaTime) { // Call base Render glPushMatrix (); glTranslatef (0.0f, -15.0f, 0.0f); cSprite::Render (deltaTime); glPopMatrix (); } float Angle (float angle) { if ( angle > 0.0f ) { while ( angle >= 360.0f ) angle -= 360.0f; } else if ( angle < 0.0f ) { while ( angle <= -360.0f ) angle += 360.0f; angle = 360.0f + angle; } return angle; }; float DeltaAngle (float from, float to) { float delta = Angle (to) - Angle (from); if ( delta > 180.0f ) delta = -360.0f + delta; else if ( delta < -180.0f ) delta = 360.0f + delta; return delta; }; //! Updating interface void cSoldier::Update (Uint32 deltaTime) { if ( mTurning ) { float tmp = TurnSpeed * deltaTime; if ( mFineAim ) tmp = FineTurnSpeed * deltaTime; if ( mTurnToTarget ) { float delta = DeltaAngle (GetRotation (), mTurnTarget); //dbgInfo () << GetID () << " Turn from " << GetRotation () << " to " << mTurnTarget << '\n'; if ( delta > 180.0f ) delta = -360.0f + delta; //dbgInfo () << GetID () << " delta: " << delta << '\n'; if ( delta > 0.0f ) { if ( tmp >= delta ) { SetRotation (mTurnTarget); StopTurning (); } else Rotate (tmp); } else if ( delta < 0.0f ) { if ( tmp >= -delta ) { SetRotation (mTurnTarget); StopTurning (); } else Rotate (-tmp); } } else if ( !mStrafe ) { if ( mTurningRight ) Rotate (tmp); else Rotate (-tmp); } } cVector2f velocity (0.0f, 0.0f); if ( mWalking ) { if ( mWalkingForward ) velocity = GetDirection (0) * WalkForwardSpeed; else if ( mWalkingBackward ) velocity = GetDirection (180) * WalkBackwardSpeed; if ( mWalkingLeft ) velocity += GetDirection (270) * WalkBackwardSpeed; if ( mWalkingRight ) velocity += GetDirection (90) * WalkBackwardSpeed; } if ( mStrafe && mTurning && !mWalkingLeft && !mWalkingRight ) { if ( mTurningRight ) velocity += GetDirection (90) * WalkBackwardSpeed; else velocity += GetDirection (270) * WalkBackwardSpeed; } SetVelocity (velocity); // Set animation bool firing = false; cWeapon *pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) firing = pCurrentWeapon->IsFiring (); if ( mWalking && firing ) { if ( mCurrentAnimation != Animation_WalkShoot ) { mAnimation = mWalkShootAnim; mCurrentAnimation = Animation_WalkShoot; } } else if ( mWalking ) { if ( mCurrentAnimation != Animation_Walk ) { mAnimation = mWalkAnim; mCurrentAnimation = Animation_Walk; } } else if ( firing ) { if ( mCurrentAnimation != Animation_Shoot ) { mAnimation = mShootAnim; mCurrentAnimation = Animation_Shoot; } } else if ( mCurrentAnimation != Animation_Stand ) { mAnimation = mStandAnim; mCurrentAnimation = Animation_Stand; } // Call base Update cSprite::Update (deltaTime); cBurnable::Update (deltaTime); } //! Change to next weapon void cSoldier::NextWeapon (void) { cWeapon *pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->SetActive (false); mCurrentWeapon++; if ( Uint32 (mCurrentWeapon) >= mWeapons.size () ) mCurrentWeapon = 0; pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->SetActive (true); } //! Add weapon void cSoldier::AddWeapon (cWeapon *pWeapon) { dbg::check_ptr (dbg::error, pWeapon, DBG_HERE); for ( unsigned int i = 0; i < mWeapons.size (); i++ ) { if ( mWeapons[i]->GetName () == pWeapon->GetName () ) { mWeapons[i]->AddClips (pWeapon->GetNumberOfClips ()); pWeapon->Kill (); return; } } pWeapon->SetOwner (GetID ()); pWeapon->SetParent (this); pWeapon->SetShooter (this); mWeapons.push_back (cPointer (pWeapon)); if ( mCurrentWeapon == -1 ) NextWeapon (); } //! Change to previous weapon void cSoldier::PreviousWeapon (void) { cWeapon *pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->SetActive (false); mCurrentWeapon--; if ( mCurrentWeapon < 0 ) mCurrentWeapon = mWeapons.size () - 1; pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->SetActive (true); } //! Return current weapon cWeapon * cSoldier::GetCurrentWeapon (void) { if ( mCurrentWeapon >= 0 && Uint32 (mCurrentWeapon) < mWeapons.size () ) return mWeapons[mCurrentWeapon]; return NULL; } void cSoldier::OnLevelChanged (void) { if ( !mBlood->IsAlive () ) cWorld::GetInstance ().SpawnObject (mBlood); } //! Called when object is hurt void cSoldier::OnHurt (int amount, const cVector2f &direction, ObjectID attacker) { if ( direction.GetLenght () != 0.0f ) { //cMixer::GetInstance ().PlaySound (mSoundDeath); // Needs some delay... mBlood->EmitParticles (amount + 10, GetPosition (), direction); } } void cSoldier::OnDeath (void) { if ( !IsAlive () ) return; cWeapon *pCurrentWeapon = GetCurrentWeapon (); if ( pCurrentWeapon != NULL ) pCurrentWeapon->SetActive (false); cMixer::GetInstance ().PlaySound (mSoundDeath); // Call base cHurtable::OnDeath (); // Spawn gibs for ( int i = 0; i < 5; i++ ) { cGib *pGib = new cGib; pGib->SetPosition (GetPosition ()); cWorld::GetInstance ().SpawnObject (pGib); } // Spawn blood pool cBloodPool *pPool = new cBloodPool; pPool->SetPosition (GetPosition ()); cWorld::GetInstance ().SpawnObject (pPool); } //! Remove all weapons void cSoldier::RemoveWeapons (void) { mWeapons.clear (); mCurrentWeapon = -1; } //============================================================================== // EOF //==============================================================================