示例#1
0
//////////////////////////////////////////////////////////////////////////
// renderHUD
void GaGameUnit::renderHUD( ScnCanvasComponentRef Canvas, BcFixed TimeFraction )
{
	if( TeamID_ > 1 )
	{
		return;
	}

	if( Behaviour_ != BEHAVIOUR_DEAD )
	{
		BcU32 TextureIdx = Desc_.Type_;
		BcFixedVec2d GamePosition( getInterpolatedPosition( TimeFraction ) );
		const BcReal ScaleFactor = 32.0f;
		BcVec2d Position( GamePosition.x(), GamePosition.y() );
		BcVec2d Size( Desc_.Size_.x(), Desc_.Size_.y() );

		Position *= ScaleFactor;
		Size *= ScaleFactor;

		// Draw range if selected.
		const BcReal MaxRangeRadius = Desc_.Range_ / ScaleFactor;
		
		
		// Draw health bar.
		BcFixed HealthFraction = Health_ / Desc_.Health_;
		BcVec2d HealthBarPosition = Position - Size * 0.5f + BcVec2d( 2.0f, -6.0f );
		BcVec2d HealthBarSize = BcVec2d( HealthFraction * ( Size.x() - 4.0f ), 2.0f );
		RsColour HealthColour = RsColour::GREEN ;

		if( HealthFraction <= 0.5f )
		{
			HealthColour = RsColour::YELLOW;
		}
		if( HealthFraction <= 0.25f )
		{
			HealthColour = RsColour::RED;
		}

		Canvas->drawSprite( HealthBarPosition, HealthBarSize, 0, HealthColour * RsColour( 1.0f, 1.0f, 1.0f, 0.75f ), 3 );

		// Draw cool down bar.
		BcFixed MaxAttackTime = BcFixed( 1.0f ) / Desc_.RateOfAttack_;
		BcFixed CoolDownFraction = BcFixed( 1.0f ) - ( AttackTimer_ / MaxAttackTime );
		BcVec2d CoolDownBarPosition = Position - Size * 0.5f + BcVec2d( 2.0f, -4.0f );
		BcVec2d CoolDownBarSize = BcVec2d( CoolDownFraction * ( Size.x() - 4.0f ), 2.0f );
		RsColour CoolDownColour = RsColour::PURPLE;

		Canvas->drawSprite( CoolDownBarPosition, CoolDownBarSize, 0, CoolDownColour * RsColour( 1.0f, 1.0f, 1.0f, 0.75f ), 3 );
	}
}
示例#2
0
//////////////////////////////////////////////////////////////////////////
// doAttack
void GaGameUnit::doAttack( BcU32 TargetID )
{
	// Check in range.
	if( inRangeForAttack( TargetID ) == RANGE_IN )
	{
		// If we can attack, launch projectile.
		if( AttackTimer_ <= 0.0f )
		{
			AttackTimer_ = BcFixed( 1.0f ) / Desc_.RateOfAttack_;
	
			GaGameUnit* pTargetUnit = pSimulator_->getUnit( TargetID );

			// Movement prediction.
			BcU32 PredictionIterations = 6;
			BcFixedVec2d TargetPosition = pTargetUnit->CurrState_.Position_;

			for( BcU32 Idx = 0; Idx < PredictionIterations; ++Idx )
			{
				BcFixed FlyDistance = ( TargetPosition - CurrState_.Position_ ).magnitude();
				BcFixed FlyTime = FlyDistance / Desc_.pDamageUnit_->MoveSpeed_;
				TargetPosition = TargetPosition + pTargetUnit->CurrState_.Velocity_ * FlyTime * pSimulator_->getSimulationRate();
			}
			
			// Fire projectile.
			GaGameUnit* pGameProjectile = pSimulator_->addUnit( *Desc_.pDamageUnit_, TeamID_ + 2, CurrState_.Position_ );
			pGameProjectile->setBehaviourDamage( TargetPosition );
		}
	}
}
示例#3
0
//////////////////////////////////////////////////////////////////////////
// tickBehaviour
void GaGameUnit::tickBehaviour( BcFixed Delta )
{
#if PSY_DEBUG
	static BcU32 BreakID = BcErrorCode;
	if( ID_ == BreakID )
	{
		BcBreakpoint;
	}
#endif

	switch( Behaviour_ )
	{
	case BEHAVIOUR_IDLE:
		{
			CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f );
			BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) );
			if( NearestUnit != BcErrorCode )
			{
				doAttack( NearestUnit );
			}
		}
		break;

	case BEHAVIOUR_GUARD:
		{
			CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f );
			BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) );
			if( NearestUnit != BcErrorCode )
			{
				doAttack( NearestUnit );
			}
		}
		break;

	case BEHAVIOUR_MOVE:
		{
			BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) );
			if( IsAttackMove_ && inRangeForAttack( NearestUnit ) == RANGE_IN )
			{
				CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f );

				doAttack( NearestUnit );
			}
			else
			{
				// Reset attack timer.
				AttackTimer_ = BcMax( AttackTimer_,  BcFixed( Desc_.CoolDownMultiplier_ ) / Desc_.RateOfAttack_ );
				
				// Make longer whe moving.
				AttackTimer_ = BcMin( BcFixed( 1.0f ) / Desc_.RateOfAttack_, AttackTimer_ + ( BcFixed( 1.0f ) / Desc_.RateOfAttack_ ) * ( Delta * 0.05f ) );

				// Calculate velocity vector.
				CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_;
				BcFixed MoveDistance = Desc_.MoveSpeed_ * Delta;
				if( ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared() < ( MoveDistance * MoveDistance ) )
				{
					CurrState_.Position_ = MoveTargetPosition_;
					setBehaviourIdle();
				}
			}
		}
		break;

	case BEHAVIOUR_ATTACK:
		{
			TRange Range = inRangeForAttack( TargetUnitID_ );
			if( Range == RANGE_IN )
			{
				doAttack( TargetUnitID_ );
			}
			else
			{
				// Reset attack timer.
				AttackTimer_ = BcMax( AttackTimer_,  BcFixed( Desc_.CoolDownMultiplier_ ) / ( Desc_.RateOfAttack_ ) );

				// Make longer whe moving.
				AttackTimer_ = BcMin( BcFixed( 1.0f ) / Desc_.RateOfAttack_, AttackTimer_ + ( BcFixed( 1.0f ) / Desc_.RateOfAttack_ ) * ( Delta * 0.05f ) );

				// Get unit position.
				GaGameUnit* pUnit = pSimulator_->getUnit( TargetUnitID_ );
				if( pUnit != NULL )
				{
					BcFixedVec2d Direction = ( getPosition() - pUnit->getPosition() ).normal() * ( ( Desc_.MinRange_ + Desc_.Range_ ) * 0.5f );
					MoveTargetPosition_ = pUnit->getPosition() + Direction;
				}
				else
				{
					// Attack move to previous target.
					IsAttackMove_ = BcTrue;
					Behaviour_ = BEHAVIOUR_MOVE;
				}

				// Calculate velocity vector.
				CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_;

				// If we moved further away, then stop and set target.
				BcFixed CurrMagnitudeSquared = ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared();
				BcFixed PrevMagnitudeSquared = ( PrevState_.Position_ - MoveTargetPosition_ ).magnitudeSquared();
				if( CurrMagnitudeSquared > PrevMagnitudeSquared )
				{
					setBehaviourIdle();
				}
			}
		}
		break;

	case BEHAVIOUR_DAMAGE:
		{
			// Calculate velocity vector.
			CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_;
			BcFixed MoveDistance = Desc_.MoveSpeed_ * Delta;
			if( ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared() < ( MoveDistance * MoveDistance ) )
			{
				CurrState_.Position_ = MoveTargetPosition_;

				// Cause damage.
				pSimulator_->applyDamage( MoveTargetPosition_, Desc_.Range_, Desc_.Health_ );

				// Debug point!
				pSimulator_->addDebugPoint( getPosition(), Desc_.Range_, RsColour::YELLOW );

				if( Desc_.pHitSound_ != NULL )
				{
					GaTopState::pImpl()->playSound( Desc_.pHitSound_, MoveTargetPosition_ );
				}

				// Set as dead.
				setBehaviourDead();
			}
		}
		break;
	}

	// Attack timer.
	if( AttackTimer_ > 0.0f )
	{
		AttackTimer_ -= Delta;
	}
	else if( AttackTimer_ < 0.0f )
	{
		AttackTimer_ = 0.0f;
	}

	// Death.
	if( Health_ <= 0.0f )
	{
		Health_ = 0.0f;
		Behaviour_ = BEHAVIOUR_DEAD;
	}
}
示例#4
0
//////////////////////////////////////////////////////////////////////////
// getMaxAttackTime
BcFixed GaGameUnit::getMaxAttackTime() const
{
	return BcFixed( 1.0f ) / Desc_.RateOfAttack_;
}
示例#5
0
//////////////////////////////////////////////////////////////////////////
// onMouseEvent
eEvtReturn GaGameComponent::onMouseEvent( EvtID ID, const OsEventInputMouse& Event )
{
	// Convert to rendering space.
	OsClient* pClient = OsCore::pImpl()->getClient( 0 );
	BcReal HW = static_cast< BcReal >( pClient->getWidth() ) / 2.0f;
	BcReal HH = static_cast< BcReal >( pClient->getHeight() ) / 2.0f;
	CursorPosition_.set( Event.MouseX_ - HW, Event.MouseY_ - HH );
	GameCursorPosition_ = CursorPosition_ / 32.0f;
	EndGameCursorPosition_ = GameCursorPosition_;

	if( MouseDown_ && ( StartGameCursorPosition_ - EndGameCursorPosition_ ).magnitudeSquared() > BcFixed( 8.0f ) )
	{
		BoxSelection_ = BcTrue;
	}

	if( ID == osEVT_INPUT_MOUSEDOWN )
	{
		StartGameCursorPosition_ = GameCursorPosition_;
		MouseDown_ = BcTrue;
		BoxSelection_ = BcFalse;
	}
	else if( ID == osEVT_INPUT_MOUSEUP )
	{
		EndGameCursorPosition_ = GameCursorPosition_;
		MouseDown_ = BcFalse;
		GaGameUnitIDList FoundUnits;

		if( BoxSelection_ )
		{
			pSimulator_->findUnits( FoundUnits, StartGameCursorPosition_, EndGameCursorPosition_, BcErrorCode, 1 << TeamID_ );
		}
		else
		{
			pSimulator_->findUnits( FoundUnits, GameCursorPosition_, 0.8f, BcErrorCode, 1 << TeamID_ );
			while( FoundUnits.size() > 1 )
			{
				FoundUnits.pop_back();
			}
		}

		// If we found units, then set selection.
		if( FoundUnits.size() > 0 )
		{
			UnitSelection_ = FoundUnits;
		}
		else
		{
			// If we aren't box selection do action.
			if( BoxSelection_ == BcFalse )
			{
				BcU32 TargetUnitID = BcErrorCode;

				// Determine if it's an attack move or not.
				pSimulator_->findUnits( FoundUnits, GameCursorPosition_, 0.8f, BcErrorCode, 1 << ( 1 - TeamID_ ) );
				while( FoundUnits.size() > 1 )
				{
					FoundUnits.pop_back();
				}

				if( FoundUnits.size() == 1 )
				{
					TargetUnitID = FoundUnits[ 0 ];
				}

				// Otherwise, tell found units to move.
				BcFixedVec2d CentralPosition;
				BcFixed Divisor;
				for( BcU32 Idx = 0; Idx < UnitSelection_.size(); ++Idx )
				{
					GaGameUnit* pGameUnit( pSimulator_->getUnit( UnitSelection_[ Idx ] ) );
					if( pGameUnit != NULL )
					{
						CentralPosition += pGameUnit->getPosition();
						Divisor += 1.0f;
					}
				}

				if( UnitSelection_.size() > 0 && Divisor > 0.0f )
				{
					CentralPosition /= Divisor;

					GameCursorPosition_ = BcFixedVec2d( ( GameCursorPosition_.x() ), ( GameCursorPosition_.y() ) );

					BcFixed PlayfieldHW = 1280.0f * 0.5f / 32.0f;
					BcFixed PlayfieldHH = 720.0f * 0.5f / 32.0f;

					for( BcU32 Idx = 0; Idx < UnitSelection_.size(); ++Idx )
					{
						GaGameUnit* pGameUnit( pSimulator_->getUnit( UnitSelection_[ Idx ] ) );
						if( pGameUnit != NULL )
						{
							if( TargetUnitID == BcErrorCode )
							{
								GaGameUnitMoveEvent Event;
								Event.UnitID_ = pGameUnit->getID();
								Event.Position_ = ( ( pGameUnit->getPosition() - CentralPosition ) * 0.0f ) + GameCursorPosition_;

								Event.Position_.x( BcClamp( Event.Position_.x(), -PlayfieldHW, PlayfieldHW ) );
								Event.Position_.y( BcClamp( Event.Position_.y(), -PlayfieldHH, PlayfieldHH ) );

								Event.IsAttackMove_ = AttackMove_;
								
								pSimulator_->publish( gaEVT_UNIT_MOVE, Event );
							}
							else
							{
								GaGameUnitAttackEvent Event;
								Event.UnitID_ = pGameUnit->getID();
								Event.TargetUnitID_ = TargetUnitID;
								pSimulator_->publish( gaEVT_UNIT_ATTACK, Event );
							}
						}
					}
				}

				// Toggle off attack move.
				AttackMove_ = BcFalse;
			}
			else
			{
				// If we were box selecting clear selection.
				UnitSelection_.clear();
			}
		}

		BoxSelection_ = BcFalse;
	}
	
	return evtRET_PASS;
}
示例#6
0
*
*
* 
**************************************************************************/

#include "GaGameComponent.h"

#include "GaTopState.h"

//////////////////////////////////////////////////////////////////////////
// Units
static GaGameUnitDescriptor GGameProjectile_Soldier = 
{
	5,
	BcFixedVec2d( 0.5f, 0.5f ),		// Unit size.
	BcFixed( 32.0f ),				// Move speed.
	BcFixed( 2.0f ),				// Rate of attack.
	BcFixed( 1.0f ),				// Cool down mult for rate of attack.
	BcFixed( 0.1f ),				// Range.
	BcFixed( 0.1f ),				// Range.
	BcFixed( 7.0f ),				// Health.
	BcFalse,						// Armoured.
	NULL,

	// Sound
	NULL,
	NULL,
	NULL,
};

static GaGameUnitDescriptor GGameProjectile_Archer =