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

📄 triggersystem.cpp

📁 C人工智能游戏开发的一些实例源代码 C Game development in artificial intelligence source code of some examples
💻 CPP
字号:
#include "TriggerSystem.h"
#include "Agent.h"
#include <windows.h>
#include <mmsystem.h>
#include <math.h>
#include <assert.h>


#define DIST(a, b) sqrt( (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y) + (b.z - a.z)*(b.z - a.z) )

unsigned long TriggerRecordStruct::s_nNextTriggerID = 1;

// -----------------------------------------------------------------------

TriggerRecordStruct::TriggerRecordStruct(EnumTriggerType _eTriggerType, 
		unsigned long _idSource, const Vector& _vPos, 
		float _fRadius, float _fDuration, bool _bDynamicSourcePos)
{
	eTriggerType		= _eTriggerType;
	idSource			= _idSource;
	vPos				= _vPos;
	fRadius				= _fRadius;
	nTimeStamp			= timeGetTime();
	bDynamicSourcePos	= _bDynamicSourcePos;

	// Triggers with duration of 0 do not ever expire.
	if(_fDuration != 0.f)
	{
		nExpirationTime = nTimeStamp + (unsigned long)(_fDuration * 1000.f);
	}
	else {
		nExpirationTime = 0;
	}

	// Keep a unique identifier for all triggers.
	nTriggerID = s_nNextTriggerID++;
}

// -----------------------------------------------------------------------

CTriggerSystem::CTriggerSystem()
{
	m_bTriggerCriticalSection = false;
}

CTriggerSystem::~CTriggerSystem()
{
}

// -----------------------------------------------------------------------

unsigned long CTriggerSystem::RegisterTrigger(EnumTriggerType _eTriggerType, unsigned long _nPriority,
									   unsigned long _idSource, const Vector& _vPos, float _fRadius, 
									   float _fDuration, bool _bDynamicSourcePos)
{
	// Create a trigger record, and fill it in.
	TriggerRecordStruct* pTriggerRecord = 
		new	TriggerRecordStruct(_eTriggerType, _idSource, _vPos, 
								_fRadius, _fDuration, _bDynamicSourcePos);

	// Trigger records are sorted by priority.
	m_mapTriggerMap.insert( TRIGGER_MAP::value_type(_nPriority, pTriggerRecord) );

	return pTriggerRecord->nTriggerID;
}

// -----------------------------------------------------------------------

void CTriggerSystem::RemoveTrigger(unsigned long nTriggerID)
{
	assert(m_bTriggerCriticalSection == false);

	TRIGGER_MAP::iterator it = m_mapTriggerMap.begin();
	while( it != m_mapTriggerMap.end() )
	{
		if( it->second->nTriggerID == nTriggerID )
		{
			delete(it->second);
			return;
		}
		else ++it;
	}
}

// ----------------------------------------------------------------------- 

void CTriggerSystem::Update()
{
    CAgent* pAgent	= NULL;
	float fDistance	= 0.f;

	TriggerRecordStruct* pRecord;
	TRIGGER_MAP::iterator it;

	unsigned long nCurTime = timeGetTime();

	//
	// Delete expired trigger records.
	// Records with expiration time 0 never expire.
	//
	// For records that are not expired, update position
	// if the dynamic flag is set.
	//
	it = m_mapTriggerMap.begin();
	while( it != m_mapTriggerMap.end() )
	{
		pRecord = it->second;
		if( (pRecord->nExpirationTime != 0) && (pRecord->nExpirationTime < nCurTime) )
		{
			delete(pRecord);
			it = m_mapTriggerMap.erase(it);
		}
		else {
			// Update position if dynamic flag is set.
			// Reset time-stamp.
			if(pRecord->bDynamicSourcePos == true)
			{
				pRecord->vPos = g_pAgentList[pRecord->idSource]->GetPosition();
				pRecord->nTimeStamp = nCurTime;
			}

			++it;
		}		
	}


	//
	// Trigger Agents.
	//

	// Make sure triggers are not getting removed while in this loop.
	m_bTriggerCriticalSection = true;

	// Loop thru agents.
	for(unsigned long iAgent=0; iAgent < g_nNumAgents; ++iAgent)
	{
		pAgent = g_pAgentList[iAgent];

		// Check if it's time for this Agent to update.
		if( (pAgent->GetTriggerUpdateRate() > 0.f) && (nCurTime > pAgent->GetNextTriggerUpdate()) )
		{
			pAgent->SetNextTriggerUpdate(nCurTime + (unsigned long)(pAgent->GetTriggerUpdateRate() * 1000.f));

			// Loop through existing trigger records.
			for(it = m_mapTriggerMap.begin(); it != m_mapTriggerMap.end(); ++it)
			{
				pRecord = it->second;

				// Check if this Agent responds to this trigger.
				if( !(pRecord->eTriggerType & pAgent->GetTriggerFlags()) )
					continue;
				
				// Check that trigger source is not the Agent itself.
				if( pRecord->idSource == iAgent)
					continue;

				// Check radius.
				fDistance = DIST(pRecord->vPos, pAgent->GetPosition());
				if(fDistance > (pAgent->GetTriggerDistance() + pRecord->fRadius) )
					continue;
				
				// HandleTrigger returns true if the Agent responded to the trigger.
				if( pAgent->HandleTrigger(pRecord) )
				{
					// Only pay attention to the highest priority 
					// trigger at any one instant.
					break;
				}
			}
		}
	}

	m_bTriggerCriticalSection = false;
}

⌨️ 快捷键说明

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