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

📄 client_physics.cpp

📁 Blood 2全套源码
💻 CPP
字号:

#include "de_client.h"
#include "client_physics.h"
#include "ContainerCodes.h"
#include "ClientUtilities.h"


extern PhysicsState	  g_normalPhysicsState;
extern PhysicsState	  g_waterPhysicsState;

void InitMovingObject(MovingObject *pObject, DVector *pPos, DVector *pVelocity)
{
	memset(pObject, 0, sizeof(MovingObject));
	VEC_COPY(pObject->m_Pos, *pPos);
	VEC_COPY(pObject->m_LastPos, *pPos);
	VEC_COPY(pObject->m_Velocity, *pVelocity);

	ClientDE* pClientDE = g_normalPhysicsState.m_pClientDE;
	if (!pClientDE) return;

	// Determine if we are in any containers (like liquid) that would
	// affect physics...

	DDWORD dwUserFlags;
	HLOCALOBJ objList[1];
	DDWORD dwNum = pClientDE->GetPointContainers(&pObject->m_Pos, objList, 1);

	if (dwNum > 0 && objList[0])
	{
		pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags);
	}

	if(dwNum > 0)
	{
		D_WORD code;
		if (pClientDE->GetContainerCode(objList[0], &code))
		{
			ContainerCode eCode = (ContainerCode)code;

			if (IsLiquid(eCode))
			{
				pObject->m_PhysicsFlags |= MO_LIQUID;
			}
		}
	}
}


void SetPhysicsStateTimeStep(PhysicsState *pState, float timeStep)
{
	pState->m_TimeStep = timeStep;
	pState->m_TimeStepIntegral = timeStep*timeStep*0.5f;
}


DBOOL UpdateMovingObject(PhysicsState *pUserState, MovingObject *pObject, DVector *pNewPos)
{
	if (!pObject || !pNewPos) return DFALSE;

	PhysicsState* pState = pUserState ? pUserState : GetCurPhysicsState(pObject);
	if (!pState) return DFALSE;

	DVector vTemp, velocityDelta, posDelta;

	if(pObject->m_PhysicsFlags & MO_RESTING)
		return DFALSE;
	
	// Prevent tiny movements.
	if(VEC_MAGSQR(pObject->m_Acceleration) < 0.01f)
	{
		VEC_INIT(pObject->m_Acceleration);
	}

	if(VEC_MAGSQR(pObject->m_Velocity) < 0.01f)
	{
		VEC_INIT(pObject->m_Velocity);
	}

	// velocityDelta = ( acceleration + accelDelta * 0.5 ) * dt;
	VEC_INIT(vTemp);
	if (!(pObject->m_PhysicsFlags & MO_NOGRAVITY))
	{
		DFLOAT fScale = 0.5f;
		if (pObject->m_PhysicsFlags & MO_HALFGRAVITY)
		{
			fScale = 0.20f;
		}
		VEC_MULSCALAR(vTemp, pState->m_GravityAccel, fScale);
	}
	VEC_ADD(vTemp, vTemp, pObject->m_Acceleration);
	VEC_MULSCALAR(velocityDelta, vTemp, pState->m_TimeStep);

	// Apply the velocity to the position (p = p + vt + 0.5a(t^2)).
	VEC_MULSCALAR(posDelta, pObject->m_Acceleration, pState->m_TimeStepIntegral);
	VEC_ADDSCALED(posDelta, posDelta, pObject->m_Velocity, pState->m_TimeStep);

	// Add the final velocity to the new velocity.
	VEC_ADD(pObject->m_Velocity, pObject->m_Velocity, velocityDelta);

	if(!pNewPos)
		pNewPos = &pObject->m_Pos;

	VEC_ADD(*pNewPos, pObject->m_Pos, posDelta);
	
	// Zero out the acceleration.
	VEC_INIT(pObject->m_Acceleration);

	return DTRUE;
}


DBOOL BounceMovingObject(PhysicsState *pUserState, MovingObject *pObject, 
						 DVector *pNewPos, ClientIntersectInfo* pInfo, SurfaceType *eType)
{

	if (!pObject || !pNewPos || !pInfo) return DFALSE;

	PhysicsState* pState = pUserState ? pUserState : GetCurPhysicsState(pObject);
	if (!pState) return DFALSE;

	ClientIntersectQuery query;
	float dot;

	// Only do an intersection test if the line is long enough (sometimes the 
	// intersection test will fail on really short lines).
	memset(&query, 0, sizeof(query));
	VEC_COPY(query.m_From, pObject->m_Pos);
	VEC_COPY(query.m_To, *pNewPos);

	if (eType)
		query.m_Flags = INTERSECT_HPOLY;

	if (pState->m_pClientDE->IntersectSegment(&query, pInfo))
	{
		// get the surface type
		if (eType)
			*eType = GetSurfaceType(pInfo->m_hObject, pInfo->m_hPoly);

		// Reflect the velocity.
		dot = VEC_DOT(pObject->m_Velocity, pInfo->m_Plane.m_Normal);
		dot *= -2.0f;

		VEC_ADDSCALED(pObject->m_Velocity, pObject->m_Velocity, pInfo->m_Plane.m_Normal, dot);

		// If the plane hit is in the opposite direction of travel, then move back a little...
		if( dot > 0.0f )
		{
			// Move the dest point a little in front of the plane.
			VEC_ADDSCALED(*pNewPos, pInfo->m_Point, pInfo->m_Plane.m_Normal, 0.3f);
		}
	
		// Dampen it.
		VEC_MULSCALAR(pObject->m_Velocity, pObject->m_Velocity, pState->m_VelocityDampen);
		
		// (250 is the max squared magnitude).
		if(pInfo->m_Plane.m_Normal.y > 0.6f && (VEC_MAGSQR(pObject->m_Velocity) < (250.0f)))
		{
			pObject->m_PhysicsFlags |= MO_RESTING;
		}

		return DTRUE;
	}

	return DFALSE;
}

// Based on the current position of the object, determine the physics state
// we should use...

PhysicsState* GetCurPhysicsState(MovingObject *pObject)
{
	if (!pObject) return DNULL;

	return ((pObject->m_PhysicsFlags & MO_LIQUID) ? &g_waterPhysicsState : &g_normalPhysicsState);
}





⌨️ 快捷键说明

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