CFVec2 CSteeringAgent::GetRepulsionBearingEffect() const { CFVec2 vCumulativeRepulsionEffect = fv2EMPTY; const vector<CCircle>& krRepulsionZones = CBlackboard::GetInstance().GetRepulsionZones(); for (unsigned int uiIndex = 0; uiIndex < krRepulsionZones.size(); uiIndex++) { CFVec2 vRepulsionEffect = m_krCat.GetPosition() - krRepulsionZones.at(uiIndex).Centre(); FLOAT32 fDistanceBetweenCenters = vRepulsionEffect.Magnitude(); FLOAT32 fDistanceBetweenBorders = fDistanceBetweenCenters - m_krCat.GetRadius() - krRepulsionZones.at(uiIndex).Radius(); if (m_krCat.GetHeadingVector().DotProduct(vRepulsionEffect) < 0.0f && fDistanceBetweenBorders < m_fRepulsionBufferStatic) { FLOAT32 fDistanceIntoRepulsionBuffer = (m_fRepulsionBufferStatic - fDistanceBetweenBorders) / m_fRepulsionBufferStatic; vRepulsionEffect.Normalise(); vRepulsionEffect *= fDistanceIntoRepulsionBuffer; vCumulativeRepulsionEffect += vRepulsionEffect; } } const vector<const CCat*>& krCats = CBlackboard::GetInstance().GetCats(); for (unsigned int uiIndex = 0; uiIndex < krCats.size(); uiIndex++) { CFVec2 vRepulsionEffect = m_krCat.GetPosition() - krCats.at(uiIndex)->GetPosition(); FLOAT32 fDistanceBetweenCenters = vRepulsionEffect.Magnitude(); // We don't want the cat to repel itself... if (fDistanceBetweenCenters == 0.0f) { continue; } FLOAT32 fDistanceBetweenBorders = fDistanceBetweenCenters - m_krCat.GetRadius() * 2.0f; if (m_krCat.GetHeadingVector().DotProduct(vRepulsionEffect) < 0.0f && fDistanceBetweenBorders < m_fRepulsionBufferDynamic) { FLOAT32 fDistanceIntoRepulsionBuffer = (m_fRepulsionBufferDynamic - fDistanceBetweenBorders) / m_fRepulsionBufferDynamic; vRepulsionEffect.Normalise(); vRepulsionEffect *= fDistanceIntoRepulsionBuffer; vCumulativeRepulsionEffect += vRepulsionEffect; } } if (vCumulativeRepulsionEffect.Magnitude() > 1.0f) { vCumulativeRepulsionEffect.Normalise(); } return vCumulativeRepulsionEffect; }
void CMole::ComputeSeekForce(CFVec2& _vrSeekForce, int _iTargetNodeId) { const Path::TNode& ktrTargetNode = s_pSharedPath->GetNode(_iTargetNodeId); CFVec2 vSeekForce; vSeekForce = ktrTargetNode.vPosition; vSeekForce -= m_vPosition; vSeekForce.Normalise(); _vrSeekForce = vSeekForce; }
CFVec2 CSteeringAgent::GetAbsoluteWhiskerStart(const CFVec2& _krvRelativeWhisker) const { CFVec2 vAbsoluteWhiskerStart = GetAdjustedWhisker(_krvRelativeWhisker); if (vAbsoluteWhiskerStart.Magnitude() != 0.0f) { vAbsoluteWhiskerStart.Normalise(); vAbsoluteWhiskerStart *= m_krCat.GetRadius(); } vAbsoluteWhiskerStart += m_krCat.GetPosition(); return vAbsoluteWhiskerStart; }
CFVec2 CSteeringAgent::GetWhiskerBearingEffect() const { CBlackboard& rBlackboard = CBlackboard::GetInstance(); bool bRotationApplied = false; FLOAT32 fTotalRotation = 0.0f; FLOAT32 fRotation = Math::PI / 2.0f; // 90 degrees for (unsigned int uiIndex = 0 ; uiIndex < SIDE_WHISKER_COUNT; uiIndex++) { FLOAT32 fWhiskerTime = rBlackboard.GetClosestWallIntersectionTime(GetAbsoluteWhiskerStart(m_vWhiskersLeft[uiIndex]), GetAdjustedWhisker(m_vWhiskersLeft[uiIndex])); if (fWhiskerTime != -1.0f) { fTotalRotation += fRotation; bRotationApplied = true; } fWhiskerTime = rBlackboard.GetClosestWallIntersectionTime(GetAbsoluteWhiskerStart(m_vWhiskersRight[uiIndex]), GetAdjustedWhisker(m_vWhiskersRight[uiIndex])); if (fWhiskerTime != -1.0f) { fTotalRotation -= fRotation; bRotationApplied = true; } fRotation /= 5.0f; // TODO MAGIC } if (bRotationApplied) { // If the rotation was cancelled out (accounting for rounding errors). if (abs(fTotalRotation) < 0.0001f) { // The whiskers are intersecting on both sides so chances are we're heading straight for something and we // need to turn. Clockwise 90 degrees sounds good... fTotalRotation += Math::PI / 2.0f; } CFVec2 vWhiskerBearingEffect = m_krCat.GetHeadingVector(); vWhiskerBearingEffect.Normalise(); vWhiskerBearingEffect.RotateZ(fTotalRotation); return vWhiskerBearingEffect; } return fv2EMPTY; }
void CPathFindingAgent::AdvanceDestinationOnPath(float _fDistance) { if (m_iPreviousWaypointIndex == -1) { m_iPreviousWaypointIndex = 0; m_iNextWaypointIndex = 1; } CFVec2 vAdvancement = m_path.at(m_iNextWaypointIndex)->GetPosition() - m_path.at(m_iPreviousWaypointIndex)->GetPosition(); vAdvancement.Normalise(); vAdvancement *= _fDistance; CFVec2 vDestinationCopy = m_vDestination; vDestinationCopy += vAdvancement; float fDistancePastNextWaypoint = (vDestinationCopy - m_path.at(m_iPreviousWaypointIndex)->GetPosition()).Magnitude() - (m_path.at(m_iNextWaypointIndex)->GetPosition() - m_path.at(m_iPreviousWaypointIndex)->GetPosition()).Magnitude(); if (fDistancePastNextWaypoint > 0.0f) { m_vDestination = m_path.at(m_iNextWaypointIndex)->GetPosition(); if (m_path.size() > (unsigned) m_iNextWaypointIndex + 1) { m_iPreviousWaypointIndex++; m_iNextWaypointIndex++; AdvanceDestinationOnPath(fDistancePastNextWaypoint); } } else { m_vDestination += vAdvancement; } }
void CSquirrel::Update( FLOAT32 fTimeDelta ) { if ( 0 == m_uNumLives ) { return; } const static CFVec2 s_vMoveOffsets[] = { SFVec2( -1.0f, 0.0f ), //"Left", SFVec2( 1.0f, 0.0f ), //"Right", SFVec2( 0.0f, -1.0f ), //"Up", SFVec2( 0.0f, 1.0f ), //"Down" }; _COMPILE_ASSERT( _ARRAY_SIZE( s_vMoveOffsets ) == EMove_COUNT ); CFVec2 vMove = SFVec2( 0.0f, 0.0f ); for ( UINT32 i=0; i< EMove_COUNT; i++ ) { if ( m_Movements[i].m_bValue ) { vMove += s_vMoveOffsets[i]; } } // great, now we have the movement direction. if ( vMove.SquareMagnitude() != 0.0f ) { m_fDistTimeMoving += fTimeDelta; vMove.Normalise(); FLOAT32 fStep = 1.0f; CFVec2 vTestedMove = vMove * fTimeDelta * m_fSpeed * fStep; // now check the target position - is it embedded in any walls? CCircle TargetBounds; while ( fStep > 0.0f ) { TargetBounds.Initialise( m_vPosition + vTestedMove, m_fRadius ); if ( false == CMMMContext::GetInstance().CircleIntersectsGeometry( TargetBounds ) ) { break; // found a valid, allowable movement. } fStep -= 0.2f; vTestedMove = vMove * fTimeDelta * m_fSpeed * fStep; } // now update to the new position m_vPosition += vTestedMove; // finally what happens at the new position // is an acorn collected? if ( m_uNumAcorns != m_uMaxAcorns ) { CAcorn* pLevelAcorns; UINT32 uNumLevelAcorns; CMMMContext::GetInstance().GetAcorns( pLevelAcorns, uNumLevelAcorns ); for ( UINT32 i=0; i<uNumLevelAcorns; i++ ) { if ( pLevelAcorns[i].GetState() == CAcorn::ES_Available ) { if ( pLevelAcorns[i].Intersects( TargetBounds ) ) { pLevelAcorns[i].SetState( CAcorn::ES_Carried ); m_ppAcorns[m_uNumAcorns++] = pLevelAcorns+i; if ( m_uNumAcorns == m_uMaxAcorns ) { break; // cannont collect any more! } } } } } // is a tunnel reached? if ( m_uNumAcorns > 0 ) { CTunnel* pTunnels; UINT32 uNumTunnels; CMMMContext::GetInstance().GetTunnels( pTunnels, uNumTunnels ); for ( UINT32 i=0; i<uNumTunnels; i++ ) { if ( pTunnels[i].Intersects( TargetBounds ) ) { // reached the tunnel. for ( UINT32 i=0; i<m_uNumAcorns; i++ ) { m_ppAcorns[i]->SetState( CAcorn::ES_Collected ); m_uScore++; } m_uNumAcorns = 0; } } } } m_fTimeToDisturbance -= fTimeDelta; if ( m_fTimeToDisturbance <= 0.0f ) { // schedule the next disturbance. m_fTimeToDisturbance = FLOAT32(rand())/FLOAT32(RAND_MAX); m_fTimeToDisturbance *= m_fMaxDistSep-m_fMinDistSep; m_fTimeToDisturbance += m_fMinDistSep; // create this disturbance: FLOAT32 fRad = m_fLastDistDelay=0.0f?0.0f:m_fDistTimeMoving/m_fLastDistDelay; // DbgPrint( "Creating Disturbance strength %0.2f, next delay %0.2f\n", fRad,m_fTimeToDisturbance ); fRad *= m_fMaxDistRad-m_fMinDistRad; fRad += m_fMinDistRad; if ( fRad >= 0.0f ) { CCircle Dist; Dist.Initialise( m_vPosition, fRad ); CMMMContext::GetInstance().CreateDisturbance( Dist ); } m_fDistTimeMoving = 0.0f; m_fLastDistDelay = m_fTimeToDisturbance; } }