📄 movement.cpp
字号:
//----------------------------------------------------------
//
// MODULE : Movement.cpp
//
// PURPOSE : CMovement class
//
// CREATED : 9/23/97
//
//----------------------------------------------------------
#include <stdio.h>
#include <math.h>
#include "movement.h"
#include "cpp_server_de.h"
#include "generic_msg_de.h"
#include "clientdebugline.h"
#include "objectutilities.h"
#include "windows.h"
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::EngineMessageFn
//
// PURPOSE: Handle message from the engine
//
// ----------------------------------------------------------------------- //
DDWORD CMovement::EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, DFLOAT fData)
{
switch(messageID)
{
case MID_UPDATE:
Update();
break;
case MID_SAVEOBJECT:
Save((HMESSAGEWRITE)pData, (DDWORD)fData);
break;
case MID_LOADOBJECT:
Load((HMESSAGEREAD)pData, (DDWORD)fData);
break;
}
return Aggregate::EngineMessageFn(pObject, messageID, pData, fData);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::ObjectMessageFn
//
// PURPOSE: Handle object-to-object messages
//
// ----------------------------------------------------------------------- //
DDWORD CMovement::ObjectMessageFn(LPBASECLASS pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
return Aggregate::ObjectMessageFn(pObject, hSender, messageID, hRead);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::Init
//
// PURPOSE: Initialize object
//
// ----------------------------------------------------------------------- //
DBOOL CMovement::Init(HOBJECT hObject)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!hObject || !pServerDE) return DFALSE;
m_hObject = hObject;
VEC_INIT(m_vLastPos);
// See if it's a player object
if(pServerDE->IsKindOf(pServerDE->GetObjectClass(hObject), pServerDE->GetClass("CBaseCharacter")))
{
m_pOwner = (CBaseCharacter*)pServerDE->HandleToObject(hObject);
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::Update
//
// PURPOSE: Update the object
//
// ----------------------------------------------------------------------- //
void CMovement::Update()
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE || !m_hObject) return;
// Save our last position...
VEC_COPY(m_vLastPos,m_vPos);
pServerDE->GetObjectPos(m_hObject, &m_vPos);
// Retrieve object vectors for current frame..
pServerDE->GetObjectRotation(m_hObject, &m_rRot);
pServerDE->GetRotationVectors(&m_rRot, &m_vUp, &m_vRight, &m_vForward);
return;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::CalculatePath
//
// PURPOSE: Precalculate path to vDestPos
//
// ----------------------------------------------------------------------- //
DBOOL CMovement::CalculatePath(DVector vDestPos)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE) return DFALSE;
DVector vDims, vTest;
DRotation rRot;
//sanity check to make sure vDestPos is valid
VEC_INIT(vTest);
if(VEC_DIST(vTest, vDestPos) <= 0)
return DFALSE;
IntersectQuery IQuery;
IntersectInfo IInfo;
IQuery.m_Flags = INTERSECT_OBJECTS;
IQuery.m_FilterFn = DNULL;
// LARGE_INTEGER start;
// QueryPerformanceCounter(&start);
//clear the path list out
Term();
//get the parent's dims
pServerDE->GetObjectDims(m_hObject,&vDims);
DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f;
if(!ClearToPoint(m_vPos, vDestPos,vDims, &IInfo))
{
VEC_ADDSCALED(IInfo.m_Point,IInfo.m_Point, IInfo.m_Plane.m_Normal, fDim - 0.1f)
AddPosToPathList(IInfo.m_Point);
//align a test rotation to the obstacles normal and retrieve the rotation vectors
VEC_MULSCALAR(IInfo.m_Plane.m_Normal, IInfo.m_Plane.m_Normal, -1.0f);
pServerDE->AlignRotation(&rRot, &(IInfo.m_Plane.m_Normal), &m_vUp);
DVector vTurnPoint = FindShortestTurn(IInfo.m_Point, &rRot, fDim);
if(VEC_DIST(vTurnPoint, IInfo.m_Point) <= 0.0f)
return DFALSE;
AddPosToPathList(vTurnPoint);
DVector vU,vR,vF;
pServerDE->GetRotationVectors(&rRot,&vU,&vR,&vF);
vTurnPoint = FindTurn(vTurnPoint, vF, IInfo.m_Plane.m_Normal, fDim, fDim);
if(VEC_DIST(vTurnPoint, vDestPos) <= 0.0f)
return DFALSE;
if(ClearToPoint(vTurnPoint, vDestPos, vDims, &IInfo))
{
AddPosToPathList(vTurnPoint);
AddPosToPathList(vDestPos);
// ConsolidatePath();
}
else
return DFALSE;
}
else
AddPosToPathList(vDestPos);
/* LARGE_INTEGER end;
QueryPerformanceCounter(&end);
pServerDE->DebugOut("Shortest Path Computed: %u ticks\r\n", (unsigned long)(end.QuadPart - start.QuadPart));
*/
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::FindPosAroundObj
//
// PURPOSE: Find nearest point on other side of object in vDir
//
// ----------------------------------------------------------------------- //
DVector CMovement::FindPosAroundObj(DVector vStart, DVector vDir)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE) return vStart;
DVector vDims, vPoint, vColor;
m_nWidthPoints = 10;
//get the parent's dims
pServerDE->GetObjectDims(m_hObject,&vDims);
DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f;
VEC_ADDSCALED(vPoint, vStart, vDir, fDim);
while(m_nWidthPoints)
{
if(pServerDE->GetPointShade(&vPoint,&vColor))
{
return vPoint;
}
else
{
VEC_ADDSCALED(vPoint, vPoint, vDir, fDim);
}
m_nWidthPoints--;
}
return vStart;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::ClearToPoint
//
// PURPOSE: check if it is clear and wide enough to destination
//
// ----------------------------------------------------------------------- //
DBOOL CMovement::ClearToPoint(DVector vStart, DVector vDestPos, DVector vDims, IntersectInfo* IInfo)
{
GlobalFilterFnData globalFilterFnData;
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE) return DFALSE;
DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f;
IntersectQuery IQuery;
IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
IQuery.m_FilterFn = GlobalFilterFn;
globalFilterFnData.m_dwFlags = IGNORE_CHARACTER;
globalFilterFnData.m_nIgnoreObjects = 1;
globalFilterFnData.m_hIgnoreObjects = &m_hObject;
IQuery.m_pUserData = &globalFilterFnData;
DVector vDir;
DRotation rRot;
VEC_SUB(vDir, vDestPos, vStart);
VEC_NORM(vDir);
pServerDE->AlignRotation(&rRot, &vDir, &m_vUp);
DVector vU,vR,vF;
pServerDE->GetRotationVectors(&rRot,&vU,&vR,&vF);
//check the right side
VEC_ADDSCALED(IQuery.m_From, vStart, vR, fDim);
VEC_ADDSCALED(IQuery.m_To, vDestPos, vR, fDim);
if(pServerDE->IntersectSegment(&IQuery, IInfo))
{
return DFALSE;
}
//check the left side
VEC_ADDSCALED(IQuery.m_From, vStart, vR, (fDim * -1.0f));
VEC_ADDSCALED(IQuery.m_To,vDestPos, vR, (fDim * -1.0f));
if(pServerDE->IntersectSegment(&IQuery, IInfo))
{
return DFALSE;
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CMovement::FindShortestTurn
//
// PURPOSE: find pos closest to turn around
//
// ----------------------------------------------------------------------- //
DVector CMovement::FindShortestTurn(DVector vStart, DRotation* prRot, DFLOAT fMoveLen)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE) return vStart;
DVector vDir, vEnd, vCurPos;
DVector vUp,vRight,vForward,vLeft;
VEC_COPY(vCurPos, vStart);
IntersectQuery IQuery;
IntersectInfo ii;
DFLOAT fLeftDist = 0.0f, fRightDist = 0.0f, fMaxDist = 0.0f;
pServerDE->GetRotationVectors(prRot,&vUp,&vRight,&vForward);
VEC_MULSCALAR(vLeft,vRight,-1.0f); //create the left rotation vector
IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -