📄 motion.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 + -