////////////////////////////////////////////////////////////////////////// // 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; }
////////////////////////////////////////////////////////////////////////// // tickState void GaGameUnit::tickState( BcFixed Delta ) { PrevState_ = CurrState_; NextState_ = CurrState_; //if( NextState_.Velocity_.magnitudeSquared() > 0.0f ) { NextState_.Position_ += NextState_.Velocity_ * Delta; if( Behaviour_ != BEHAVIOUR_DAMAGE ) { // Check new state is valid. BcFixedVec2d Min( NextState_.Position_ - ( Desc_.Size_ * 0.9f ) ); BcFixedVec2d Max( NextState_.Position_ + ( Desc_.Size_ * 0.9f ) ); GaGameUnitIDList FoundUnits; pSimulator_->findUnits( FoundUnits, Min, Max, ID_, 0x3 ); // Move unit away from it's nearest one. if( FoundUnits.size() != 0 ) { BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 0x3 ); GaGameUnit* pGameUnit = pSimulator_->getUnit( NearestUnit ); if( pGameUnit != NULL ) { BcFixedVec2d Direction = ( CurrState_.Position_ - pGameUnit->CurrState_.Position_ ).normal(); if( Direction.dot( NextState_.Velocity_.normal() ) > 0.0f || NextState_.Velocity_.magnitudeSquared() == 0.0f ) { BcFixedVec2d RandomOffset( (int)( pSimulator_->rand() % 64 ), (int)( pSimulator_->rand() % 64 ) ); NextState_ = CurrState_; NextState_.Velocity_ = NextState_.Velocity_ * 0.4f + ( Direction * Desc_.MoveSpeed_ ) * 0.6f; NextState_.Position_ += NextState_.Velocity_ * Delta + ( RandomOffset / 4096.0f ); } } else { NextState_ = CurrState_; } } } } // WalkTimer_ -= NextState_.Velocity_.magnitude() * Delta; if( WalkTimer_ < 0.0f ) { GaTopState::pImpl()->playSound( "Walk", getPosition() ); WalkTimer_ += ( Desc_.MoveSpeed_ + (BcAbs( BcRandom::Global.randReal() ) * 0.02f ) ) * 0.2f; } // Clamp position and move away. BcFixed HW = ( 1280.0f * 0.5f ) / 32.0f - 1.0f; BcFixed HH = ( 720.0f * 0.5f ) / 32.0f - 1.0f; BcFixedVec2d ClampedPosition; ClampedPosition.x( BcClamp( NextState_.Position_.x(), -HW, HW ) ); ClampedPosition.y( BcClamp( NextState_.Position_.y(), -HH, HH ) ); if( NextState_.Position_ != ClampedPosition ) { BcFixedVec2d RandomOffset( (int)( pSimulator_->rand() % 64 ), (int)( pSimulator_->rand() % 64 ) ); NextState_.Velocity_ += RandomOffset / 4096.0f; NextState_.Position_ = ClampedPosition; } }
////////////////////////////////////////////////////////////////////////// // GaGameComponent //virtual void GaGameComponent::update( BcReal Tick ) { BcU32 Param = FontMaterial_->findParameter( "aAlphaTestStep" ); FontMaterial_->setParameter( Param, BcVec2d( 0.4f, 0.5f ) ); if( GameState_ == GS_PLAYING ) { pSimulator_->tick( Tick ); if( pSimulator_->getTimeOut() > 5.0f ) { GameState_ = GS_TIMEOUT; } if( pSimulator_->getUnitCount( TeamID_ ) == 0 || pSimulator_->getUnitCount( 1 - TeamID_ ) == 0 ) { GameState_ = GS_OVER; } if( !Networked_ ) { AITickTime_ -= Tick; if( AITickTime_ < 0.0f ) { pSimulator_->runAI( 1 - TeamID_ ); AITickTime_ = AITickMaxTime_; } } } //if( TeamID_ == 0 ) { if( CanvasComponent_.isValid() ) { OsClient* pClient = OsCore::pImpl()->getClient( 0 ); BcReal HW = static_cast< BcReal >( pClient->getWidth() ) / 2.0f; BcReal HH = static_cast< BcReal >( pClient->getHeight() ) / 2.0f; BcReal AspectRatio = HW / HH; BcMat4d Ortho; Ortho.orthoProjection( -HW, HW, HH, -HH, -1.0f, 1.0f ); // Clear canvas and push projection matrix. CanvasComponent_->clear(); CanvasComponent_->pushMatrix( Ortho ); CanvasComponent_->setMaterialComponent( BackgroundMaterial_ ); CanvasComponent_->drawSpriteCentered( BcVec2d( 0.0f, 0.0f ), BcVec2d( 1280.0f, 720.0f ), 0, RsColour( 1.0f, 1.0f, 1.0f, 1.0f ), 0 ); CanvasComponent_->setMaterialComponent( SpriteSheetMaterials_[ 0 ] ); pSimulator_->render( CanvasComponent_, 0 ); CanvasComponent_->setMaterialComponent( SpriteSheetMaterials_[ 1 ] ); pSimulator_->render( CanvasComponent_, 1 ); // Find unit over mouse. GaGameUnitIDList SelectionList; if( MouseDown_ ) { if( BoxSelection_ ) { pSimulator_->findUnits( SelectionList, StartGameCursorPosition_, EndGameCursorPosition_, BcErrorCode, BcErrorCode ); } } else { pSimulator_->findUnits( SelectionList, GameCursorPosition_, 0.8f, BcErrorCode, BcErrorCode ); while( SelectionList.size() > 1 ) { SelectionList.pop_back(); } } for( BcU32 Idx = 0; Idx < UnitSelection_.size(); ++Idx ) { SelectionList.push_back( UnitSelection_[ Idx ] ); } CanvasComponent_->setMaterialComponent( HUDMaterial_ ); pSimulator_->renderHUD( CanvasComponent_, SelectionList, TeamID_ ); } switch( GameState_ ) { case GS_PLAYING: { // Draw cursor. CanvasComponent_->setMaterialComponent( HUDMaterial_ ); CanvasComponent_->drawSpriteCentered( BcVec2d( CursorPosition_.x(), CursorPosition_.y() ), BcVec2d( 64.0f, 64.0f ), 1, AttackMove_ ? RsColour::RED : RsColour::WHITE, 10 ); // Draw selection box. if( MouseDown_ && BoxSelection_ ) { BcVec2d Min = BcVec2d( StartGameCursorPosition_.x(), StartGameCursorPosition_.y() ) * 32.0f; BcVec2d Max = BcVec2d( GameCursorPosition_.x(), GameCursorPosition_.y() ) * 32.0f; CanvasComponent_->drawSprite( Min, Max - Min, 0, RsColour::GREEN * RsColour( 1.0f, 1.0f, 1.0f, 0.1f ), 11 ); } std::string Text0 = TeamID_ == 0 ? "YOU ARE RED!" : "YOU ARE BLUE!"; BcVec2d TextSize0 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text0, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize0 / 2.0f ) + BcVec2d( 0.0f, -350.0f ), Text0, TeamID_ == 0 ? RsColour::RED : RsColour::BLUE, BcFalse ); } break; case GS_TIMEOUT: { std::string Text0 = "Connection timed out :("; std::string Text1 = "Press ESC to Quit."; BcVec2d TextSize0 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text0, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize0 / 2.0f ) + BcVec2d( 0.0f, -64.0f ), Text0, RsColour::WHITE, BcFalse ); BcVec2d TextSize1 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text1, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize1 / 2.0f ) + BcVec2d( 0.0f, 64.0f ), Text1, RsColour::WHITE, BcFalse ); } break; case GS_OVER: { if( pSimulator_->getUnitCount( TeamID_ ) > 0 ) { std::string Text0 = "You Won! :D"; std::string Text1 = "Press ESC to Quit."; BcVec2d TextSize0 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text0, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize0 / 2.0f ) + BcVec2d( 0.0f, -64.0f ), Text0, RsColour::WHITE, BcFalse ); BcVec2d TextSize1 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text1, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize1 / 2.0f ) + BcVec2d( 0.0f, 64.0f ), Text1, RsColour::WHITE, BcFalse ); } else { std::string Text0 = "You Lost! :<"; std::string Text1 = "Press ESC to Quit."; BcVec2d TextSize0 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text0, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize0 / 2.0f ) + BcVec2d( 0.0f, -64.0f ), Text0, RsColour::WHITE, BcFalse ); BcVec2d TextSize1 = Font_->draw( CanvasComponent_, BcVec2d( 0.0f, 0.0f ), Text1, RsColour::WHITE, BcTrue ); Font_->draw( CanvasComponent_, ( -TextSize1 / 2.0f ) + BcVec2d( 0.0f, 64.0f ), Text1, RsColour::WHITE, BcFalse ); } } break; } } }