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

📄 movement.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------------
//
// 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 + -