コード例 #1
0
void CDockingPorts::UpdateDockingManeuvers (CSpaceObject *pOwner, DockingPort &Port)

//	UpdateDockingManeuvers
//
//	Updates the motion of a ship docking with a port

	{
	CShip *pShip = Port.pObj->AsShip();

	ASSERT(pShip);
	if (pShip == NULL)
		return;

	CVector vDest = pOwner->GetPos() + Port.vPos;
	CVector vDestVel = pOwner->GetVel();

	//	Figure out how far we are from where we want to be

	CVector vDelta = vDest - pShip->GetPos();

	//	Figure out if we're aligned

	int iFinalRotation = pShip->AlignToRotationAngle(Port.iRotation);

	//	If the docking object is within the appropriate threshold 
	//	of the port, then complete the docking sequence.

	Metric rDelta2 = vDelta.Length2();
	if (rDelta2 < DOCKING_THRESHOLD2 
			&& (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation()))
		{
		pShip->Place(vDest);
		pShip->UnfreezeControls();
		IShipController *pController = pShip->GetController();
		pController->SetManeuver(IShipController::NoRotation);

		Port.iStatus = psInUse;

		//	Tell the owner that somone has docked with it first
		//	(We do this because sometimes we want to handle stuff
		//	in OnObjDocked before we show the player a dock screen)

		if (pOwner 
				&& pOwner->HasOnObjDockedEvent() 
				&& pOwner != pShip
				&& !pOwner->IsDestroyed()
				&& pShip->IsSubscribedToEvents(pOwner))
			pOwner->FireOnObjDocked(pShip, pOwner);

		//	Set the owner as "explored" (if the ship is the player)

		if (pShip->IsPlayer())
			pOwner->SetExplored();

		//	Dock

		pShip->OnDocked(pOwner);

		//	Notify other subscribers

		pShip->NotifyOnObjDocked(pOwner);
		}

	//	Otherwise accelerate the ship towards the docking port

	else
		{
		Metric rMaxSpeed = pShip->GetMaxSpeed();
		Metric rMinSpeed = rMaxSpeed / 10.0;

		//	We slow down as we get closer

		Metric rSpeed;
		if (rDelta2 < FINAL_DOCKING2)
			rSpeed = rMinSpeed;
		else if (rDelta2 < FINAL_APPROACH2)
			{
			Metric rSpeedRange = rMaxSpeed - rMinSpeed;
			Metric rDelta = sqrt(rDelta2);
			rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING));
			}
		else
			rSpeed = rMaxSpeed;

		//	Figure out the ideal velocity vector that we want to
		//	be following.

		CVector vIdealVel = vDelta.Normal() * rSpeed;

		//	Calculate the delta v that we need

		CVector vDeltaV = vIdealVel - pShip->GetVel();

		//	Rotate

		if (!pShip->IsPlayer())
			{
			IShipController *pController = pShip->GetController();

			//	If we're close enough, align to rotation angle

			if (rDelta2 < FINAL_APPROACH2)
				pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle()));

			//	Otherwise, align along delta v

			else
				pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle()));

			//	Don't let the AI thrust

			pController->SetThrust(false);
			}

		//	Accelerate

		pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate);
		pShip->ClipSpeed(rSpeed);
		}
	}
コード例 #2
0
void CDockingPorts::UpdateAll (CSpaceObject *pOwner)

//	UpdateAll
//
//	UpdateAll 

	{
	int i, j;

	for (i = 0; i < m_iPortCount; i++)
		{
		if (m_pPort[i].iStatus == psDocking)
			{
			CShip *pShip = m_pPort[i].pObj->AsShip();

			ASSERT(pShip);
			if (pShip == NULL)
				continue;

			CVector vDest = pOwner->GetPos() + m_pPort[i].vPos;
			CVector vDestVel = pOwner->GetVel();

			//	Figure out how far we are from where we want to be

			CVector vDelta = vDest - pShip->GetPos();

			//	Figure out if we're aligned

			int iFinalRotation = pShip->AlignToRotationAngle(m_pPort[i].iRotation);

			//	If the docking object is within the appropriate threshold 
			//	of the port, then complete the docking sequence.

			Metric rDelta2 = vDelta.Length2();
			if (rDelta2 < DOCKING_THRESHOLD2 
					&& (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation()))
				{
				pShip->Place(vDest);
				pShip->UnfreezeControls();
				IShipController *pController = pShip->GetController();
				pController->SetManeuver(IShipController::NoRotation);

				m_pPort[i].iStatus = psInUse;

				//	Tell the owner that somone has docked with it first
				//	(We do this because sometimes we want to handle stuff
				//	in OnObjDocked before we show the player a dock screen)

				if (pOwner && pOwner->HasOnObjDockedEvent() && pOwner != pShip)
					pOwner->OnObjDocked(pShip, pOwner);

				//	Dock

				pShip->OnDocked(pOwner);

				//	Tell all objects in the system that a ship has docked

				CSystem *pSystem = pShip->GetSystem();
				for (j = 0; j < pSystem->GetObjectCount(); j++)
					{
					CSpaceObject *pObj = pSystem->GetObject(j);

					if (pObj && pObj->HasOnObjDockedEvent() && pObj != pShip && pObj != pOwner)
						pObj->OnObjDocked(pShip, pOwner);
					}
				}

			//	Otherwise accelerate the ship towards the docking port

			else
				{
				Metric rMaxSpeed = pShip->GetMaxSpeed();
				Metric rMinSpeed = rMaxSpeed / 10.0;

				//	We slow down as we get closer

				Metric rSpeed;
				if (rDelta2 < FINAL_DOCKING2)
					rSpeed = rMinSpeed;
				else if (rDelta2 < FINAL_APPROACH2)
					{
					Metric rSpeedRange = rMaxSpeed - rMinSpeed;
					Metric rDelta = sqrt(rDelta2);
					rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING));
					}
				else
					rSpeed = rMaxSpeed;

				//	Figure out the ideal velocity vector that we want to
				//	be following.

				CVector vIdealVel = vDelta.Normal() * rSpeed;

				//	Calculate the delta v that we need

				CVector vDeltaV = vIdealVel - pShip->GetVel();

				//	Rotate

				if (pShip != g_pUniverse->GetPlayer())
					{
					IShipController *pController = pShip->GetController();

					//	If we're close enough, align to rotation angle

					if (rDelta2 < FINAL_APPROACH2)
						pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle()));

					//	Otherwise, align along delta v

					else
						pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle()));
					}

				//	Accelerate

				pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate);

				pShip->ClipSpeed(rSpeed);
				}
			}
		}
	}