Esempio n. 1
0
void CEnvironmentSim::Simulate(double dTimeDelta)
{
	if(dTimeDelta<=0)
		return;
	CSceneObject* pScene = CGlobals::GetScene();
	if((pScene == NULL) || pScene->IsScenePaused() || (!(pScene->IsSceneEnabled())) )
		return;

	// physics engine frame move. 
	CGlobals::GetPhysicsWorld()->StepSimulation(dTimeDelta);

	/** advance the game time */
	g_gameTime.FrameMoveDelta((float)dTimeDelta);

	// advance time of day
	pScene->GetSunLight().AdvanceTimeOfDay((float)dTimeDelta);

	/** Check load physics around the current player and the camera position
	* this is very game specific. It only ensures that physics object around the current player and camera is loaded.
	*/
	CBipedObject* pPlayer = pScene->GetCurrentPlayer();
	int nPointCount = 0;
	CShapeSphere points[2];
	if(pPlayer)
	{
		points[nPointCount].Set(pPlayer->GetPosition(), pPlayer->GetPhysicsRadius()*2.f);
		nPointCount++;
	}
	if(pScene->GetCurrentCamera())
	{
		points[nPointCount].Set(pScene->GetCurrentCamera()->GetEyePosition(), pScene->GetCurrentCamera()->GetNearPlane()*2);
		nPointCount++;
	}
	CheckLoadPhysics(points, nPointCount);

	UpdateGameObjects(dTimeDelta);

	{
		PERF1("EnvSim::Frame Move Sentient Objects");

		for (auto itCur = pScene->GetSentientObjects().begin(); itCur != pScene->GetSentientObjects().end();)
		{
			IGameObject* pObj = (*itCur);
			if (!pObj)
			{
				itCur = pScene->GetSentientObjects().erase(itCur);
				OUTPUT_LOG("warn: invalid weak ref found in pScene->GetSentientObjects()\n");
				continue;
			}
			else
			{
				itCur++;
			}
			if(pObj->GetSimTag() != SIM_TAG_FINISHED)
			{
				pScene->SetCurrentActor((CBaseObject*)pObj);

				if(pObj->GetSimTag() == SIM_TAG_START)
				{
					// generate way points
					pObj->PathFinding(dTimeDelta);
					// move the biped according to way point commands
					pObj->AnimateBiped(dTimeDelta);
				}

				// apply AI controller
				if(pObj->GetAIModule())
					pObj->GetAIModule()->FrameMove((float)dTimeDelta);
				if(!pObj->GetPerceiveList().empty())
					pObj->On_Perception();
				// call the frame move script if any.
				pObj->On_FrameMove();
				pObj->SetSimTag(SIM_TAG_FINISHED);

				if(pObj->HasReferences())
				{
					RefList::iterator itCur, itEnd = pObj->GetRefList().end();
					for (itCur = pObj->GetRefList().begin(); itCur!=itEnd; ++itCur)
					{
						if(itCur->m_tag == 0)
						{
							IGameObject* pRefObj = ((CBaseObject*)((*itCur).m_object))->QueryIGameObject();
							if(pRefObj!=0 && !pRefObj->IsSentient() && pRefObj->IsGlobal() && (pRefObj->GetSimTag() == SIM_TAG_START))
							{
								//////////////////////////////////////////////////////////////////////////
								// update reference object in the terrain tile according to its current position
								Vector3 vPos = pRefObj->GetPosition();
								CTerrainTile * pTile = pScene->GetRootTile()->GetTileByPoint(vPos.x, vPos.z);
								if(pTile != NULL)
								{
									pRefObj->SetTileContainer(pTile);
								}

								//////////////////////////////////////////////////////////////////////////
								// basic simulation: path finding, etc.
								pScene->SetCurrentActor((CBaseObject*)pRefObj);
								// generate way points
								pRefObj->PathFinding(dTimeDelta);
								// move the biped according to way point commands
								pRefObj->AnimateBiped(dTimeDelta);
								pRefObj->SetSimTag(SIM_TAG_BASIC);
							}
						}
					}
				}
			}
		}

		if(CGlobals::WillGenReport())
		{
			CGlobals::GetReport()->SetValue("sentient objects", (int)pScene->GetSentientObjects().size());
		}
	}
	/// frame move each unexploded missile objects.
	{
		for (auto pMissile : pScene->GetMissiles())
		{
			if( !pMissile->IsExploded() )
			{
				pMissile->Animate(dTimeDelta);
			}
		}
	}
}
Esempio n. 2
0
// 2007.8.27: logic changes: the current player is always sentient to all other objects and all other objects are sentient to the current player. 
void CEnvironmentSim::UpdateGameObjects(double dTimeDelta)
{
	PERF1("EnvSim::UpdateGameObjects");
	CSceneObject* pScene = CGlobals::GetScene();

	CTerrainTile* duplicateTiles[9];

	for (int i = 0;i < (int)pScene->GetSentientObjects().size(); )
	{
		// for each sentient game objects (sentientObj) in the scene
		IGameObject* sentientObj = pScene->GetSentientObjects()[i];
		if (!sentientObj)
		{
			pScene->GetSentientObjects().erase(i);
			OUTPUT_LOG("warn: invalid weak ref found in pScene->GetSentientObjects()\n");
			continue;
		}

		sentientObj->SetSentientObjCount(0);
		sentientObj->GetPerceiveList().clear();
		
		Vector3 vPos = sentientObj->GetPosition();
		Vector2 vec2Pos(vPos.x, vPos.z);
		// update itself in the terrain tile according to its current position:
		CTerrainTile * pTile = pScene->GetRootTile()->GetTileByPoint(vPos.x, vPos.z);
		if(pTile != NULL)
		{
			sentientObj->SetTileContainer(pTile);

			for(int k=0;k<9;++k)
				duplicateTiles[k]=NULL;

			//for each valid terrain tiles(9 or more) in the neighborhood of sentientObj
			for (int i=0; i<9;++i)
			{
				CTerrainTile* pTileAdjacent = pScene->GetRootTile()->GetAdjacentTile(vPos, (CTerrainTileRoot::DIRECTION)i);

				if(pTileAdjacent!=NULL)
				{
					// check if pTile is a new tile that has not been processed by the current sentient object.
					bool bNewAdjacentTile = true;
					if((pTileAdjacent==sentientObj->GetTileContainer()) || pTileAdjacent->m_fRadius != sentientObj->GetTileContainer()->m_fRadius)
					{
						for(int k=0;k<9 && (duplicateTiles[k]!=NULL);++k)
						{
							if(duplicateTiles[k] == pTileAdjacent){
								bNewAdjacentTile = false;
								break;
							}
						}
					}
					if(bNewAdjacentTile)
					{
						{
							VisitorList_type::iterator itCurCP, itEndCP = pTileAdjacent->m_listVisitors.end();

							for( itCurCP = pTileAdjacent->m_listVisitors.begin(); itCurCP != itEndCP;)
							{
								IGameObject* AnotherObj = (*itCurCP);
								if (AnotherObj != nullptr)
								{
									if (AnotherObj != sentientObj)
									{
										Vector3 vPosAnother = AnotherObj->GetPosition();

										Vector2 vec2PosAnother(vPosAnother.x, vPosAnother.z);
										float fDistSq = (vec2PosAnother - vec2Pos).squaredLength();

										if (!AnotherObj->IsSentient())
										{
											//if sentientObj falls inside the sentient area of AnotherObj
											if ((AnotherObj->IsSentientWith(sentientObj)) && fDistSq <= AnotherObj->GetSentientRadius()*AnotherObj->GetSentientRadius()){
												pScene->AddSentientObject(AnotherObj);
											}
										}

										//if AnotherObj falls inside the sentient area of sentientObj
										if ((sentientObj->IsSentientWith(AnotherObj)) && fDistSq <= sentientObj->GetSentientRadius()*sentientObj->GetSentientRadius())
										{
											sentientObj->SetSentientObjCount(sentientObj->GetSentientObjCount() + 1);

											// if AnotherObj falls inside the perceptive area of sentientObj
											if (fDistSq <= sentientObj->GetPerceptiveRadius()*sentientObj->GetPerceptiveRadius())
											{
												sentientObj->GetPerceiveList().push_back(AnotherObj->GetIdentifier());
											}
										}
									}
									++itCurCP;
								}
								else
									itCurCP = pTileAdjacent->m_listVisitors.erase(itCurCP);
							}
						}
						// skip solid object on the root tile, since they are all global objects, not static objects. 
						if(pTileAdjacent!=pScene->GetRootTile())
						{
							// check collision with other static solid objects.

							for (auto pObject : pTileAdjacent->m_listSolidObj)
							{
								IGameObject* AnotherObj = pObject->QueryIGameObject();
								if(AnotherObj!=NULL && AnotherObj!=sentientObj && sentientObj->IsSentientWith(AnotherObj) )
								{
									Vector3 vPosAnother = AnotherObj->GetPosition();

									Vector2 vec2PosAnother(vPosAnother.x, vPosAnother.z);
									float fDistSq = (vec2PosAnother-vec2Pos).squaredLength();

									//if AnotherObj falls inside the sentient area of sentientObj
									if(fDistSq<= sentientObj->GetSentientRadius()*sentientObj->GetSentientRadius())
									{
										sentientObj->SetSentientObjCount(sentientObj->GetSentientObjCount()+1);

										// if AnotherObj falls inside the perceptive area of sentientObj
										if(fDistSq<= sentientObj->GetPerceptiveRadius()*sentientObj->GetPerceptiveRadius())
										{
											sentientObj->GetPerceiveList().push_back(AnotherObj->GetIdentifier());
										}
									}
								}
							}
						}
						for(int k=0;k<9;++k)
						{
							if(duplicateTiles[k]==NULL)
							{
								duplicateTiles[k] = pTileAdjacent;
								break;
							}
						}
					}//if(bNewAdjacentTile)
				}
			}
		}

		if(sentientObj->GetSentientObjCount()>0 || sentientObj->IsAlwaysSentient())
		{
			++i;

			{ // set the simulation tag of all sentient objects and their referenced objects to SIM_TAG_START state.
				sentientObj->SetSimTag(SIM_TAG_START);
				if(sentientObj->HasReferences())
				{
					RefList::iterator itCur, itEnd = sentientObj->GetRefList().end();
					for (itCur = sentientObj->GetRefList().begin(); itCur!=itEnd; ++itCur)
					{
						if(itCur->m_tag == 0)
						{
							IGameObject* pRefObj = ((CBaseObject*)((*itCur).m_object))->QueryIGameObject();
							if(pRefObj!=0)
							{
								pRefObj->SetSimTag(SIM_TAG_START);
							}
						}
					}
				}
			}
			// call on perceived now or in the next pass. 
		}
		else
		{
			sentientObj->On_LeaveSentientArea();
			pScene->GetSentientObjects().erase(i);
		}
	}
}