⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 motion.cpp

📁 c++程序
💻 CPP
字号:
// Motion.cpp: Implementierung der Klasse CMotion.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Motion.h"

// Conversion factor for converting between degrees and radians
#define PI_OVER_180 0.0174532925f

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

CMotion::CMotion()
{
	// Init motion behavior with standard values. Every values is meant
	// to be applied in 1000ms

	m_SlowDown               = 7.5f;
	m_MidAirSlowDown         = 0.1f;
	m_GravityAcceleration    = 2.5;
	m_Gravity[x]		     = 0.0f;
	m_Gravity[y]             = -0.15f;
	m_Gravity[z]             = 0.0f;

	// Init other member variables

	m_MidAir                 = FALSE;
	m_SmallestForce          = 0.01f;
	m_AccelerationTime       = 100;
	m_MidAirAccelerationTime = 500;
	m_JumpForce[x]           = 0.0f;
	m_JumpForce[y]           = 1.0f;
	m_JumpForce[z]           = 0.0f;
	m_CurrentGravity[x]      = 0.0f;
	m_CurrentGravity[y]      = 0.0f;
	m_CurrentGravity[z]      = 0.0f;
	m_MaxAccelerationFactor  = 4.0f;
	m_MinimumHeight          = 0.0f;
}

CMotion::~CMotion()
{

}

void CMotion::ApplyMotionPhysics(const DWORD dwTimeElapsed)
{
	// Calculate the movement that would happen in dwTimeElapsed ms
	
	// Copy the current motion vector to cFinalForce
	CForce cFinalForce = m_Force;
	
	// Is camera in the air ?
	CheckMidAir();
	
	// Apply gravity to the final movement vector
	if (m_MidAir)
	{
		// Camera is diving, apply gravity accelleration
		m_CurrentGravity[x] += ScaleToElapsedTime(m_CurrentGravity[x] * m_GravityAcceleration, dwTimeElapsed);
		m_CurrentGravity[y] += ScaleToElapsedTime(m_CurrentGravity[y] * m_GravityAcceleration, dwTimeElapsed);
		m_CurrentGravity[z] += ScaleToElapsedTime(m_CurrentGravity[z] * m_GravityAcceleration, dwTimeElapsed);
		// Apply gravity
		cFinalForce += m_CurrentGravity;
	}
	else
		// Camera is on the ground, set current gravity to default gravity
		m_CurrentGravity = m_Gravity;
	
	// Scale the final motion vector relative to dwTimeElapsed
	cFinalForce[x] = ScaleToElapsedTime(cFinalForce[x], dwTimeElapsed);
	cFinalForce[y] = ScaleToElapsedTime(cFinalForce[y], dwTimeElapsed);
	cFinalForce[z] = ScaleToElapsedTime(cFinalForce[z], dwTimeElapsed);
	
	// Make sure that the motion don't exceed the speed limit
	cFinalForce.SetVectorLength(ScaleToElapsedTime(GetSpeed() * m_MaxAccelerationFactor, dwTimeElapsed));

	if (GetYPos() + cFinalForce[y] < GetSurfaceHeight())
		// No acceleration upwards
		m_Force[y] = 0.0f;

	// Calculate position after motion
	float fNewPosX = GetXPos() + cFinalForce[x];
	float fNewPosZ = GetZPos() + cFinalForce[z];
	float fNewPosY = GetYPos() + cFinalForce[y];

	// Make sure that the new position is inside the landscape borders
	float fStepSize = GetLandscape()->GetStepSize();
	RECT rcLandscape;
	GetLandscape()->GetLandscapeDimensions(&rcLandscape);
	if (fNewPosX < fStepSize / 2.0f)
		fNewPosX = fStepSize / 2.0f;
	if (fNewPosZ < fStepSize / 2.0f)
		fNewPosZ = fStepSize / 2.0f;
	if (fNewPosX > rcLandscape.bottom * fStepSize - fStepSize / 2.0f)
		fNewPosX = rcLandscape.bottom * fStepSize - fStepSize / 2.0f;
	if (fNewPosZ > rcLandscape.right * fStepSize - fStepSize / 2.0f)
		fNewPosZ = rcLandscape.right * fStepSize - fStepSize / 2.0f;

	float fGradient = GetGradient(cFinalForce);

	// Pass the position after the motion to the CCamera class.
	SetXPos(fNewPosX);
	SetYPos(fNewPosY);
	SetZPos(fNewPosZ);

	// Lift the camera up to the terrain if it has descended below it
	float fHeight = GetSurfaceHeight();
	if (GetYPos() < fHeight)
	{
		// Lift camera up
		SetYPos(fHeight);
	}

	//if (m_Force[y] < m_JumpForce[y] / 2.0f && 
	//	GetYPos() - fHeight < ScaleToElapsedTime(m_MinimumHeight, dwTimeElapsed))
	//	SetYPos(fHeight);

	
	if (m_Force[y] < m_JumpForce[y] / 2.0f && 
		m_MidAir == FALSE && fGradient < 0.01f)
		SetYPos(fHeight);


	// Slow the motion down
	
	// Use m_MidAirSlowDown when camera is in the air
	if (m_MidAir)
		// Reduce force as specified in m_MidAirSlowDown. Scale to the elapsed time
		m_Force.SlowDown(ScaleToElapsedTime(m_MidAirSlowDown, dwTimeElapsed));
	else
		// Reduce force as specified in m_SlowDown. Scale to the elapsed time
		m_Force.SlowDown(ScaleToElapsedTime(m_SlowDown, dwTimeElapsed));

	// Set it to zero if it is to small
	if (fabs(m_Force[x]) + fabs(m_Force[y]) +
		fabs(m_Force[z]) < m_SmallestForce)
	m_Force.ResetForce();
	
}

float CMotion::GetGradient(CForce cMotion)
{
	// Return the gradient for a motion to (fNewPosZ, fNewPosX).
	// Return 1.0f if the two heights are equal, return a value
	// smaller than 1.0f if diving, return a value greater than 1.0f
	// if climbing.

	cMotion.SetVectorLength(GetLandscape()->GetStepSize() / 10.0f);

	return GetLandscape()->GetSurfaceHeight(GetZPos(), GetXPos()) -
		   GetLandscape()->GetSurfaceHeight(GetZPos() + cMotion[z], GetXPos() + cMotion[x]);
}

//float CMotion::GetHeightDifference(float fYRotation)
//{
//
//}

/*float CMotion::GetGradient(CForce cMotion)
{
	// Return the gradient for a motion to (fNewPosZ, fNewPosX).
	// Return 1.0f if the two heights are equal, return a value
	// smaller than 1.0f if diving, return a value greater than 1.0f
	// if climbing.

	cMotion.SetVectorLength(GetLandscape()->GetStepSize() / 10.0f);

	return GetLandscape()->GetSurfaceHeight(GetZPos() + cMotion[z], GetXPos() + cMotion[x]) /
		   GetLandscape()->GetSurfaceHeight(GetZPos(), GetXPos());
}*/

void CMotion::SetCustomMotion(float fForwardSpeed, float fBackwardSpeed, float fLeftSpeed, float fRightSpeed,
							  float fUpSpeed, float fDownSpeed, DWORD dwTimeElapsed)
{
	// Add the given forces to the current force. Do scale the given forces relative to the
	// elapsed time.

	// Holds the new motion
	CForce cAddForce;

	// Calculate the given forces
	if (fForwardSpeed > 0.0f)
	{
		CForce cForward;
		cForward[x] = -(sinf(GetYRotation() * PI_OVER_180) * fForwardSpeed);
		cForward[y] = 0.0f;
		cForward[z] = -(cosf(GetYRotation() * PI_OVER_180) * fForwardSpeed);
		cAddForce += cForward;
	}
	if (fBackwardSpeed > 0.0f)
	{
		CForce cBackward;
		cBackward[x] = sinf(GetYRotation() * PI_OVER_180) * fBackwardSpeed;
		cBackward[y] = 0.0f;
		cBackward[z] = cosf(GetYRotation() * PI_OVER_180) * fBackwardSpeed;
		cAddForce += cBackward;
	}
	if (fLeftSpeed > 0.0f)
	{
		CForce cLeft;
		cLeft[x] = sinf((GetYRotation() - 90.0f) * PI_OVER_180) * fLeftSpeed;
		cLeft[y] = 0.0f;
		cLeft[z] = cosf((GetYRotation() - 90.0f) * PI_OVER_180) * fLeftSpeed;
		cAddForce += cLeft;
	}
	if (fRightSpeed > 0.0f)
	{
		CForce cRight;
		cRight[x] = sinf((GetYRotation() + 90.0f) * PI_OVER_180) * fRightSpeed;
		cRight[y] = 0.0f;
		cRight[z] = cosf((GetYRotation() + 90.0f) * PI_OVER_180) * fRightSpeed;
		cAddForce += cRight;
	}
	if (fUpSpeed > 0.0f)
	{
		CForce cUp;
		cUp[x] = 0.0f;
		cUp[y] = fUpSpeed;
		cUp[z] = 0.0f;
		cAddForce += cUp;
	}
	if (fDownSpeed > 0.0f)
	{
		CForce cDown;
		cDown[x] = 0.0f;
		cDown[y] = -fDownSpeed;
		cDown[z] = 0.0f;
		cAddForce += cDown;
	}

	// Is camera in the air ?
	CheckMidAir();

	// Scale length of additional force vector relative to the acceleration time
	if (m_MidAir)
		cAddForce.SetVectorLength((GetSpeed() / m_MidAirAccelerationTime) * dwTimeElapsed);
	else
		cAddForce.SetVectorLength((GetSpeed() / m_AccelerationTime) * dwTimeElapsed);

	// Add the additional force vector to the current force
	m_Force += cAddForce;
}

void CMotion::SetDefaultMotion(bool bForward, bool bBackward, bool bLeft, bool bRight, 
							   bool bUp, bool bDown, DWORD dwTimeElapsed)
{
	// Add the enabled motion vectors with default accelerations to the array
	
	// Convert parameters for SetCustomMotion() and pass them
	SetCustomMotion(bForward * GetSpeed(), bBackward * GetSpeed(), 
		bLeft * GetSpeed(), bRight * GetSpeed(),
		bUp * GetSpeed(), bDown * GetSpeed(), dwTimeElapsed);
}

void CMotion::Jump()
{
	// Add jump acceleration to there current force if player
	// is on the ground

	CheckMidAir();

	if (!m_MidAir)
		m_Force += m_JumpForce;
}

void CMotion::CheckMidAir()
{
	// Checks if the camera is in the air

	// Use offset to avoid calculation accurancy problems
	if (GetYPos() > GetSurfaceHeight() + 0.0000001f)
		m_MidAir = TRUE;
	else
		m_MidAir = FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -