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

📄 particleexplosionfx.cpp

📁 Blood 2全套源码
💻 CPP
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : ParticleExplosionFX.cpp
//
// PURPOSE : Particle Explosion - Implementation
//
// CREATED : 5/22/98
//
// ----------------------------------------------------------------------- //

#include "ParticleExplosionFX.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "ContainerCodes.h"
#include "ClientServerShared.h"
#include "shareddefs.h"
#include "sfxmgr.h"
#include "bloodclientshell.h"
#include "bloodsplatfx.h"
#include "SoundTypes.h"

extern DVector g_vWorldWindVel;

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CParticleExplosionFX::Init
//
//	PURPOSE:	Init the Particle trail segment
//
// ----------------------------------------------------------------------- //

DBOOL CParticleExplosionFX::Init(SFXCREATESTRUCT* psfxCreateStruct)
{
	if (!CBaseParticleSystemFX::Init(psfxCreateStruct)) return DFALSE;

	PESCREATESTRUCT* pPE = (PESCREATESTRUCT*)psfxCreateStruct;
	ROT_COPY(m_rSurfaceRot, pPE->rSurfaceRot);
	VEC_COPY(m_vPos, pPE->vPos);
	VEC_COPY(m_vColor1, pPE->vColor1);
	VEC_COPY(m_vColor2, pPE->vColor2);
	VEC_COPY(m_vMinVel, pPE->vMinVel);
	VEC_COPY(m_vMaxVel, pPE->vMaxVel);
	VEC_COPY(m_vMinDriftOffset, pPE->vMinDriftOffset);
	VEC_COPY(m_vMaxDriftOffset, pPE->vMaxDriftOffset);
	m_bSmall			= pPE->bSmall;
	m_fLifeTime			= pPE->fLifeTime;
	m_fFadeTime			= pPE->fFadeTime;
	m_fOffsetTime		= pPE->fOffsetTime;
	m_fRadius			= pPE->fRadius;
	m_fGravity			= pPE->fGravity;
	m_nNumPerPuff		= pPE->nNumPerPuff;
	m_nNumEmitters		= (pPE->nNumEmitters > MAX_EMITTERS ? MAX_EMITTERS : pPE->nNumEmitters);
	m_nEmitterFlags		= pPE->nEmitterFlags;
	m_pTextureName		= pPE->pFilename;
	m_bCreateDebris		= pPE->bCreateDebris;
	m_bRotateDebris		= pPE->bRotateDebris;
	m_nSurfaceType		= pPE->nSurfaceType;
	m_bIgnoreWind		= pPE->bIgnoreWind;
	m_nNumSteps			= pPE->nNumSteps;
	m_bBounce			= pPE->bBounce;

	VEC_SET(m_vColorRange, m_vColor2.x - m_vColor1.x, 
						   m_vColor2.y - m_vColor1.y,
						   m_vColor2.z - m_vColor1.z);

	if (m_vColorRange.x < 0.0f) m_vColorRange.x = 0.0f;
	if (m_vColorRange.y < 0.0f) m_vColorRange.y = 0.0f;
	if (m_vColorRange.z < 0.0f) m_vColorRange.z = 0.0f;


	if (m_bRotateDebris)
	{
		m_fPitchVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
		m_fYawVel	= GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
	}

	if (m_bSmall)
	{
		m_fRadius /= 2.0f;
	}

	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CSparksFX::CreateObject
//
//	PURPOSE:	Create object associated the particle system.
//
// ----------------------------------------------------------------------- //

DBOOL CParticleExplosionFX::CreateObject(CClientDE *pClientDE)
{
	DBOOL bRet = CBaseParticleSystemFX::CreateObject(pClientDE);
	if (!bRet) return bRet;

	// Initialize the Emitters velocity ranges based on our rotation...

	DVector vVelMin, vVelMax;
	VEC_COPY(vVelMin, m_vMinVel);
	VEC_COPY(vVelMax, m_vMaxVel);

	// Initialize our Emitters...

	DVector vStartVel;
	for (int i=0; i < m_nNumEmitters; i++)
	{
		if (m_bCreateDebris) 
		{
			m_hDebris[i] = CreateDebris();
		}

		m_ActiveEmitters[i] = DTRUE;
		m_BounceCount[i] = 2;

		VEC_SET(vStartVel, GetRandom(vVelMin.x, vVelMax.x), 
						   GetRandom(vVelMin.y, vVelMax.y), 
						   GetRandom(vVelMin.z, vVelMax.z));

		InitMovingObject(&(m_Emitters[i]), &m_vPos, &vStartVel);
		m_Emitters[i].m_PhysicsFlags |= m_nEmitterFlags;
	}

	return bRet;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CParticleExplosionFX::Update
//
//	PURPOSE:	Update the Particle trail (add Particle)
//
// ----------------------------------------------------------------------- //

DBOOL CParticleExplosionFX::Update()
{
	if (!m_hObject || !m_pClientDE) return DFALSE;

	if (!CBaseParticleSystemFX::Update()) return DFALSE;

	DFLOAT fTime = m_pClientDE->GetTime();

	if (m_bFirstUpdate)
	{
		m_bFirstUpdate = DFALSE;
		m_fStartTime   = fTime;
		m_fLastTime	   = fTime;
	}


	// Check to see if we should start fading the system...

	if (fTime > m_fStartTime + m_fFadeTime)
	{
		DFLOAT fEndTime = m_fStartTime + m_fLifeTime;
		if (fTime > fEndTime)
		{
			return DFALSE;
		}

		DFLOAT fScale = (fEndTime - fTime) / (m_fLifeTime - m_fFadeTime);

		DFLOAT r, g, b, a;
		m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a);
		m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale);
		
		//for (int i=0; i < m_nNumEmitters; i++)
		//{
		//	if (m_hDebris[i])
		//	{
		//		m_pClientDE->GetObjectColor(m_hDebris[i], &r, &g, &b, &a);
		//		m_pClientDE->SetObjectColor(m_hDebris[i], r, g, b, fScale);
		//	}
		//}
	}


	// See if it is time to create a new Particle puff...

	if (fTime >= m_fLastTime + m_fOffsetTime)
	{
		// Loop over our list of Emitters, creating new particles...

		for (int i=0; i < m_nNumEmitters; i++)
		{
			if (m_ActiveEmitters[i])
			{
				AddParticles(&m_Emitters[i]);
			}
		}

		m_fLastTime = fTime;
	}


	// Loop over our list of Emitters, updating the position of each

	for (int i=0; i < m_nNumEmitters; i++)
	{
		if (m_ActiveEmitters[i])
		{
			DBOOL bBounced = DFALSE;

			ClientIntersectInfo info;

			if (bBounced = UpdateEmmitter(&m_Emitters[i], &info))
			{
				if(m_nSurfaceType == SURFTYPE_FLESH)
				{
					CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
					if (!pShell) return DTRUE;
					CSFXMgr* psfxMgr = pShell->GetSFXMgr();
					if (!psfxMgr) return DTRUE;

					char szTemp[256];

					sprintf(szTemp, "sounds\\gibs\\flesh\\gib_impact%d.wav", GetRandom(0,NRES(5)));

					PlaySoundFromPos(&m_Emitters[i].m_Pos, szTemp, 300.0f,SOUNDPRIORITY_MISC_LOW);

					BSCREATESTRUCT splat;
					char* pSplatSprite = DNULL;

					switch(GetRandom(1,3))
					{
						case 1:		pSplatSprite = "sprites\\blood1.spr";	break;
						case 2:		pSplatSprite = "sprites\\blood2.spr";	break;
						case 3:		pSplatSprite = "sprites\\blood3.spr";	break;
						default:	pSplatSprite = "sprites\\blood1.spr";	break;
					}

					VEC_COPY(splat.m_Pos, m_Emitters[i].m_Pos);
					m_pClientDE->AlignRotation(&splat.m_Rotation, &info.m_Plane.m_Normal,&info.m_Plane.m_Normal);
					splat.m_fScale = 0.05f + GetRandom(-0.05f,0.05f);
					splat.m_hstrSprite = m_pClientDE->CreateString(pSplatSprite);
					
					if(info.m_Plane.m_Normal.y > 0.5f)
						splat.m_fGrowScale = 0.01f;

					psfxMgr->CreateSFX(SFX_BLOODSPLAT_ID, &splat, DFALSE, this);
					g_pClientDE->FreeString( splat.m_hstrSprite );
				}

				m_BounceCount[i]--;

				if (m_BounceCount[i] <= 0)
				{
					m_Emitters[i].m_PhysicsFlags |= MO_RESTING;
				}
			}

			if (m_Emitters[i].m_PhysicsFlags & MO_RESTING)
			{
				m_ActiveEmitters[i] = DFALSE;
				if (m_hDebris[i])
				{
					m_pClientDE->DeleteObject(m_hDebris[i]);
					m_hDebris[i] = DNULL;
				}
			}
			else if (m_hDebris[i])
			{
				m_pClientDE->SetObjectPos(m_hDebris[i], &(m_Emitters[i].m_Pos));

				if (m_bRotateDebris)
				{
					if (bBounced)
					{
						// Adjust due to the bounce...

						m_fPitchVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
						m_fYawVel	= GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
					}

					if (m_fPitchVel != 0 || m_fYawVel != 0)
					{
						DFLOAT fDeltaTime = m_pClientDE->GetFrameTime();

						m_fPitch += m_fPitchVel * fDeltaTime;
						m_fYaw   += m_fYawVel * fDeltaTime;

						DRotation rRot;
						m_pClientDE->SetupEuler(&rRot, m_fPitch, m_fYaw, 0.0f);
						m_pClientDE->SetObjectRotation(m_hDebris[i], &rRot);	
					}
				}
			}
		}
	}

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CParticleExplosionFX::UpdateEmmitter
//
//	PURPOSE:	Update emmitter position
//
// ----------------------------------------------------------------------- //

DBOOL CParticleExplosionFX::UpdateEmmitter(MovingObject* pObject, ClientIntersectInfo* pInfo)
{	
	if (!m_pClientDE || !pObject || pObject->m_PhysicsFlags & MO_RESTING) return DFALSE;

	DBOOL bRet = DFALSE;

	DVector vNewPos;
	if (UpdateMovingObject(DNULL, pObject, &vNewPos))
	{
		bRet = BounceMovingObject(DNULL, pObject, &vNewPos, pInfo);

		if(!m_bBounce && bRet)
			pObject->m_PhysicsFlags |= MO_RESTING;

		VEC_COPY(pObject->m_LastPos, pObject->m_Pos);
		VEC_COPY(pObject->m_Pos, vNewPos);

		if (m_pClientDE->GetPointStatus(&vNewPos) == DE_OUTSIDE)
		{
			pObject->m_PhysicsFlags |= MO_RESTING;
		}
	}

	return bRet;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CParticleExplosionFX::AddParticles
//
//	PURPOSE:	Add particles to system
//
// ----------------------------------------------------------------------- //

void CParticleExplosionFX::AddParticles(MovingObject* pObject)
{	
	if (!m_hObject || !m_pClientDE || !pObject || pObject->m_PhysicsFlags & MO_RESTING) return;

	DFLOAT fTime = m_pClientDE->GetTime();

	DVector vCurPos, vLastPos, vPos, vDelta, vTemp, vDriftVel, vColor;

	VEC_COPY(vCurPos, pObject->m_Pos);
	VEC_COPY(vLastPos, pObject->m_LastPos);

	// Calculate Particle puff positions...

	// Current position is relative to the particle system's postion (i.e., 
	// each puff of Particle is some distance away from the particle system's 
	// position)...

	VEC_SUB(vCurPos, vCurPos, m_vPos);
	VEC_SUB(vLastPos, vLastPos, m_vPos);


	// How long has it been since the last Particle puff?

	DFLOAT fTimeOffset = fTime - m_fLastTime;

	
	// Fill the distance between the last projectile position, and it's 
	// current position with Particle puffs...

	VEC_SUB(vTemp, vCurPos, vLastPos);
	VEC_MULSCALAR(vDelta, vTemp, 1.0f/float(m_nNumSteps));

	VEC_COPY(vPos, vLastPos);

	DFLOAT fCurLifeTime    = 10.0f;
	DFLOAT fLifeTimeOffset = fTimeOffset / float(m_nNumSteps);

	DFLOAT fOffset = 0.5f;

	if (m_bSmall)
	{
		fOffset /= 2.0f;
	}

	for (int i=0; i < m_nNumSteps; i++)
	{
		// Build the individual Particle puffs...

		for (int j=0; j < m_nNumPerPuff; j++)
		{
			VEC_COPY(vTemp, vPos);

			VEC_SET(vDriftVel, GetRandom(m_vMinDriftOffset.x, m_vMaxDriftOffset.x), 
							   GetRandom(m_vMinDriftOffset.y, m_vMaxDriftOffset.y), 
							   GetRandom(m_vMinDriftOffset.z, m_vMaxDriftOffset.z));

			if (!m_bIgnoreWind)
			{
				vDriftVel.x += g_vWorldWindVel.x;
				vDriftVel.y += g_vWorldWindVel.y;
				vDriftVel.z += g_vWorldWindVel.z;
			}

			vTemp.x += GetRandom(-fOffset, fOffset);
			vTemp.y += GetRandom(-fOffset, fOffset);
			vTemp.z += GetRandom(-fOffset, fOffset);

			GetRandomColorInRange(vColor);

			m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fCurLifeTime);
		}

		VEC_ADD(vPos, vPos, vDelta);
		fCurLifeTime += fLifeTimeOffset;
	}
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CParticleExplosionFX::CreateDebris
//
//	PURPOSE:	Create a debris model
//
// ----------------------------------------------------------------------- //

HLOCALOBJ CParticleExplosionFX::CreateDebris()
{
	ObjectCreateStruct createStruct;
	INIT_OBJECTCREATESTRUCT(createStruct);

	char* debrisFilename[] =
	{
		"Models\\Props\\debris\\generic1.abc",
		"Models\\Props\\debris\\generic2.abc",
		"Models\\Props\\debris\\generic3.abc",
		"Models\\Props\\debris\\generic4.abc",
		"Models\\Props\\debris\\generic5.abc",
		"Models\\Props\\debris\\generic6.abc",
		"Models\\Props\\debris\\generic7.abc",
		"Models\\Props\\debris\\generic7.abc"
	};

	createStruct.m_ObjectType = OT_MODEL;
	_mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)"models\\gibs\\flesh\\gib1.abc");
	_mbscpy((unsigned char*)createStruct.m_SkinName, (const unsigned char*)"skins\\gibs\\flesh\\gib1.abc");
	createStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT; 
	VEC_COPY(createStruct.m_Pos, m_vPos);

	HLOCALOBJ hObj = m_pClientDE->CreateObject(&createStruct);

//	DFLOAT fVal = m_fRadius / 400.0f;

//	DVector vScale;
//	VEC_SET(vScale, fVal, fVal, fVal);
//	m_pClientDE->SetObjectScale(hObj, &vScale);

	//DFLOAT r, g, b, a;
	//m_pClientDE->GetObjectColor(hObj, &r, &g, &b, &a);
	//m_pClientDE->SetObjectColor(hObj, 1.0f, 0.4f, 0.0f, a);

	return hObj;
}

⌨️ 快捷键说明

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