Пример #1
0
/**
 *	Check this wall with an infinite ray, given in parametric form and return the collision if applicable.
 *	@param vRayStart	Start point for parametric equation of infinite ray.
 *	@param vRayEnd		Direction vector (coefficient of t) for paremetric equation of infinitie ray.
 *	@param fT			To be filled in with the time (paremetric T) of intersection.
 *	@return				True if the intersection occurs within this line segment.
 */
bool CWall::GetLineIntersectionTime(  CFVec2Arg vRayStart, CFVec2Arg vRayOffset, FLOAT32& fT ) const
{
	// http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
	const CFVec2& P1 = m_vEnd[0];
	const CFVec2& P2 = m_vEnd[1];
	const CFVec2& P3 = vRayStart;
	// no P4 required..
	const CFVec2 V1 = P2-P1;
	const CFVec2& V2 = vRayOffset;
	
	const FLOAT32 fDenom = V2.Y()*V1.X() - V2.X()*V1.Y();
	
	if ( fDenom == 0.0f )
	{
		return false; // no intersections, or the lines are the same!
	}

	const FLOAT32 fDRecip = 1.0f/fDenom;
	// and then, finally Q (for x/y1 - x/y3)
	const CFVec2 Q = P1-P3;

	const FLOAT32 fTimeThis = (V2.X()*Q.Y() - V2.Y()*Q.X())*fDRecip;

	if ( fTimeThis < 0.0f || fTimeThis > 1.0f )
	{
		// outside of the wall line segment.
		return false;
	}
	fT = (V1.X()*Q.Y() - V1.Y()*Q.X())*fDRecip;
	return true;
}
Пример #2
0
bool	CBox2D::Intersects( const CCircle& Circle ) const
{
	CFVec2 vOffset = (Circle.Centre() - m_vCentre);
	vOffset.SetAbs();
	vOffset -= m_vExtents;
	return ( vOffset.X() < Circle.Radius() && vOffset.Y() < Circle.Radius() );
}
Пример #3
0
CFVec2 CSteeringAgent::GetAdjustedWhisker(const CFVec2& _krvWhisker) const
{
	CFVec2 vAdjustedWhisker = _krvWhisker;
	vAdjustedWhisker.RotateZ(m_krCat.GetHeadingRadians());

	return vAdjustedWhisker;
}
Пример #4
0
void CMole::Update(FLOAT32 _fTimeDelta)
{
	m_pMoleAgent->Update(_fTimeDelta);

	// Turn.
	m_fHeading += m_pMoleAgent->GetRotationalSpeed() * _fTimeDelta;

	// Update position.
	CFVec2 vHeading;
	vHeading.SetToRotationZ(m_fHeading);
	CFVec2 vVelocity = vHeading * m_pMoleAgent->GetSpeed() * _fTimeDelta;
	m_vPosition += vVelocity;

	if ((m_vDestination - m_vPosition).Magnitude() < fMOLE_RADIUS)
	{
		Messages::send(DESTINATION_REACHED_EVENT, this);
	}

	// finally check if that pesky rodent got caught:
	CCircle Bounds;
	Bounds.Initialise( m_vPosition, fMOLE_RADIUS );
	if ( CMMMContext::GetInstance().GetSquirrel()->Intersects( Bounds ) )
	{
		CMMMContext::GetInstance().GetSquirrel()->LoseLife();
		Messages::send(DESTINATION_REACHED_EVENT, this);
	}
}
Пример #5
0
void
CMole::UpdateRotation(float _fTimeDelta, const CFVec2& _kvrForce)
{
	if (_kvrForce.X() != 0.0f ||
		_kvrForce.Y() != 0.0f)
	{
		// Create heading vector
		CFVec2 vHeading(0.0f, -1.0f);
		vHeading.RotateZ(m_fHeading);


		// Cross
		float fCross = 0.0f;
		fCross  = vHeading.X() * _kvrForce.Y();
		fCross -= _kvrForce.X() * vHeading.Y();


		float fRotationVelocity = m_fRotationVelocity + fDegsToRad(static_cast<float>(DIFFICULTY_ROTATION_VELOCITY_INCR * m_iDifficultyLevel));


		if (fCross > 0.0f)
		{
			// Turn left
			m_fHeading += fRotationVelocity * _fTimeDelta;
		}
		else
		{
			// Turn right
			m_fHeading += fRotationVelocity * - _fTimeDelta;
		}
	}
}
Пример #6
0
bool	CBox2D::ContainsPoint( CFVec2Arg vPoint ) const
{
	CFVec2 vOffset = (vPoint - m_vCentre);
	vOffset.SetAbs();
	vOffset -= m_vExtents;
	return ( vOffset.X() < 0.0f && vOffset.Y() < 0.0f );

}
Пример #7
0
/**
 *	@param fX Filled with the mouse X coordinate.
 *	@param fY Filled with the mouse Y coordinate.
 *	@param bWasClicked Filled with a bool to say if the mouse was clicked.
 */
bool CGameBoard::GetMouseInfo( FLOAT32& fX, FLOAT32& fY, bool& bWasClicked ) const
{
	CFVec2 vMousePos;
	CConnect4Context::GetInstance().GetMouse()->GetPosition( vMousePos );
	bWasClicked = CConnect4Context::GetInstance().GetMouse()->WasClicked();
	fX = vMousePos.X();
	fY = vMousePos.Y();
	return true;	
}
Пример #8
0
bool	CBox2D::Intersects( const CBox2D& Box ) const
{
	CFVec2 vOffset = (Box.m_vCentre - m_vCentre);
	vOffset.SetAbs();
	vOffset -= m_vExtents;
	vOffset -= Box.m_vExtents;
	return ( vOffset.X() < 0.0f && vOffset.Y() < 0.0f );

}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
void CAddWallTool::NotifyLeftClick( void )
{
	CFVec2 vPos = CMMMContext::GetInstance().GetMouse()->GetPosition();
	if ( m_uNumPoints > 1 && vPos.SquareDistance( m_vSegmentEnds[0] ) < fHANDLE_DIST*fHANDLE_DIST )
	{
		// close the wall segment.
		m_vSegmentEnds[m_uNumPoints++] = m_vSegmentEnds[0];
		CMMMContext::GetInstance().CreateWalls( m_vSegmentEnds, m_uNumPoints/2 );
#pragma warnmsg( "TODO: closed wall segments: fill?" )
		m_uNumPoints = 0;
		return;
	}
	// start the next segment:
	m_vSegmentEnds[m_uNumPoints++] = vPos;
	if ( m_uNumPoints > 1 )
	{
		// and finish the last one:
		m_vSegmentEnds[m_uNumPoints++] = vPos;
	}
}
Пример #14
0
void CAddWallTool::Render( void )
{
	if ( 0 == m_uNumPoints )
	{
		return;
	}

	CFVec2 vPos = CMMMContext::GetInstance().GetMouse()->GetPosition();
	m_vSegmentEnds[m_uNumPoints] = vPos;
	if ( vPos.SquareDistance( m_vSegmentEnds[0] ) < fHANDLE_DIST*fHANDLE_DIST )
	{
		// close the wall segment, so show the snap.
		m_vSegmentEnds[m_uNumPoints] = m_vSegmentEnds[0];
	}

	for ( UINT32 i=0; i<m_uNumPoints; i+=2 )
	{
		// draw in red
		CMMMContext::GetInstance().DrawLine( m_vSegmentEnds[i], m_vSegmentEnds[i+1], 0xFFFF0000 );
	}	
}
Пример #15
0
/**
 *	@param vRayStart	Start point of an infinite ray.
 *	@param vRayOffset	Direction of the ray, parametric t multiplier.
 *	@param fT0			Filled in with time of first intersection (if present).
 *	@param fT1			Filled in with time of second intersection (if present).
 *	@return				The number of intersections found.
 */
UINT32 CCircle::GetLineIntersectionTimes(CFVec2Arg vRayStart, CFVec2Arg vRayOffset, GDE::FLOAT32 &fT0, GDE::FLOAT32 &fT1) const
{
	const CFVec2 vToRay = vRayStart - m_vCentre;
	// TODO: reformulate without the square root?
	const FLOAT32 fExtentsRecip = 1.0f/vRayOffset.Magnitude();
	const FLOAT32 fRayDotToRay = vToRay.DotProduct( vRayOffset ) * fExtentsRecip;
	const FLOAT32 fDiscr = fRayDotToRay*fRayDotToRay - (vToRay.SquareMagnitude()-m_fRadius*m_fRadius);
	if ( fDiscr < 0.0f )
	{
		return 0;	// no intersections.
	}
	if ( fDiscr == 0.0f )
	{
		fT0 = -fRayDotToRay * fExtentsRecip;
		return 1;	// one intersection, just touching
	} else
	{
		const FLOAT32 fRoot = sqrtf( fDiscr );
		fT0 = (-fRayDotToRay - fRoot) * fExtentsRecip;
		fT1 = (-fRayDotToRay + fRoot) * fExtentsRecip;
		return 2;	// two intersections.
	}
}
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;
	}
}
Пример #17
0
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;
	}



}
Пример #18
0
void
CMole::ComputeWallForce(CFVec2& _vrRepelForce)
{
	for (unsigned int i = 0; i < MAX_WHISKER; ++ i)
	{
		CFVec2 vLineRepelForce;
		CWall* pClosestWall = 0;
		float fImpactTime = 0;
		bool bIntersected = FindWiskerClosestWall(static_cast<EWhisker>(i), pClosestWall, fImpactTime);


		if (bIntersected)
		{
			// Time radio
			float fTimeRatio = 1.0f - (fImpactTime / 1.0f);
			fTimeRatio *= 1.8f;


			if (fTimeRatio > 1.0f)
			{
				fTimeRatio = 1.0f;
			}


			CFVec2 vPointDisplacement(pClosestWall->GetStartPoint());
			vPointDisplacement -= pClosestWall->GetEndPoint();


			// Line direction
			CFVec2 vLineDirection(vPointDisplacement);
			vLineDirection.Normalise();


			// Get Normal
			CFVec2 vLineNormal(pClosestWall->GetNormal());
			vLineNormal.Normalise();


			CFVec2 vStart = pClosestWall->GetStartPoint();
			CFVec2 vEnd = pClosestWall->GetEndPoint();


			// Which side is the cat on
			float fPerpendicularDot = (vEnd.X() - vStart.X()) * (m_vPosition.Y() - vStart.Y()) - (vEnd.Y() - vStart.Y()) * (m_vPosition.X() - vStart.X());


			bool bOnNormalSide = (fPerpendicularDot > 0);

			
			// Cat going against the normal
			if (bOnNormalSide)
			{
				// Cat has to be on normal side
				vLineRepelForce = vLineNormal;
				vLineRepelForce.RotateZ(fDegsToRad(180.0f));
			}


			// Cat going towards normal
			else
			{
				// Cat has to be not on normal side
				vLineRepelForce = vLineNormal;
			}


			// Scale based on collision time
			//vLineRepelForce *= 1.25f;
			vLineRepelForce *= fTimeRatio;


			_vrRepelForce += vLineRepelForce;
			m_pWhiskers[i].SetColour(0xFFFF0000);
		}
	}
}