예제 #1
0
	virtual bool CheckFoundation(std::string className)
	{
		CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
		if (cmpPosition.null())
			return false; // error

		if (!cmpPosition->IsInWorld())
			return false; // no obstruction

		CFixedVector2D pos = cmpPosition->GetPosition2D();

		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
		if (cmpPathfinder.null())
			return false; // error

		// Get passability class
		ICmpPathfinder::pass_class_t passClass = cmpPathfinder->GetPassabilityClass(className);

		// Ignore collisions with self, or with non-foundation-blocking obstructions
		SkipTagFlagsObstructionFilter filter(m_Tag, ICmpObstructionManager::FLAG_BLOCK_FOUNDATION);

		if (m_Type == STATIC)
			return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass);
		else
			return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Size0, passClass);
	}
예제 #2
0
파일: View.cpp 프로젝트: Moralitycore/0ad
void AtlasViewGame::Render()
{
	SViewPort vp = { 0, 0, g_xres, g_yres };
	CCamera& camera = GetCamera();
	camera.SetViewPort(vp);
	camera.SetProjection(g_Game->GetView()->GetNear(), g_Game->GetView()->GetFar(), g_Game->GetView()->GetFOV());
	camera.UpdateFrustum();

	// Update the pathfinder display if necessary
	if (!m_DisplayPassability.empty())
	{
		CmpPtr<ICmpObstructionManager> cmpObstructionManager(*GetSimulation2(), SYSTEM_ENTITY);
		if (cmpObstructionManager)
		{
			cmpObstructionManager->SetDebugOverlay(true);
		}

		CmpPtr<ICmpPathfinder> cmpPathfinder(*GetSimulation2(), SYSTEM_ENTITY);
		if (cmpPathfinder)
		{
			cmpPathfinder->SetDebugOverlay(true);
			// Kind of a hack to make it update the terrain grid
			PathGoal goal = { PathGoal::POINT, fixed::Zero(), fixed::Zero() };
			pass_class_t passClass = cmpPathfinder->GetPassabilityClass(m_DisplayPassability);
			cmpPathfinder->SetDebugPath(fixed::Zero(), fixed::Zero(), goal, passClass);
		}
	}

	::Render();
	Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);
}
예제 #3
0
void CSimulation2Impl::UpdateComponents(CSimContext& simContext, fixed turnLengthFixed, const std::vector<SimulationCommand>& commands)
{
	// TODO: the update process is pretty ugly, with lots of messages and dependencies
	// between different components. Ought to work out a nicer way to do this.

	CComponentManager& componentManager = simContext.GetComponentManager();

	CMessageTurnStart msgTurnStart;
	componentManager.BroadcastMessage(msgTurnStart);

	CmpPtr<ICmpPathfinder> cmpPathfinder(simContext, SYSTEM_ENTITY);
	if (cmpPathfinder)
	{
		cmpPathfinder->UpdateGrid();
		cmpPathfinder->FinishAsyncRequests();
	}

	// Push AI commands onto the queue before we use them
	CmpPtr<ICmpAIManager> cmpAIManager(simContext, SYSTEM_ENTITY);
	if (cmpAIManager)
		cmpAIManager->PushCommands();

	CmpPtr<ICmpCommandQueue> cmpCommandQueue(simContext, SYSTEM_ENTITY);
	if (cmpCommandQueue)
		cmpCommandQueue->FlushTurn(commands);

	// Process newly generated move commands so the UI feels snappy
	if (cmpPathfinder)
		cmpPathfinder->ProcessSameTurnMoves();

	// Send all the update phases
	{
		CMessageUpdate msgUpdate(turnLengthFixed);
		componentManager.BroadcastMessage(msgUpdate);
	}
	{
		CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed);
		componentManager.BroadcastMessage(msgUpdate);
	}

	// Process move commands for formations (group proxy)
	if (cmpPathfinder)
		cmpPathfinder->ProcessSameTurnMoves();

	{
		CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed);
		componentManager.BroadcastMessage(msgUpdate);
	}
	{
		CMessageUpdate_Final msgUpdate(turnLengthFixed);
		componentManager.BroadcastMessage(msgUpdate);
	}

	// Process moves resulting from group proxy movement (unit needs to catch up or realign) and any others
	if (cmpPathfinder)
		cmpPathfinder->ProcessSameTurnMoves();

	// Clean up any entities destroyed during the simulation update
	componentManager.FlushDestroyedComponents();
}
예제 #4
0
파일: View.cpp 프로젝트: Moralitycore/0ad
void AtlasViewGame::SetParam(const std::wstring& name, const std::wstring& value)
{
	if (name == L"passability")
	{
		m_DisplayPassability = CStrW(value).ToUTF8();

		CmpPtr<ICmpObstructionManager> cmpObstructionManager(*GetSimulation2(), SYSTEM_ENTITY);
		if (cmpObstructionManager)
			cmpObstructionManager->SetDebugOverlay(!value.empty());

		CmpPtr<ICmpPathfinder> cmpPathfinder(*GetSimulation2(), SYSTEM_ENTITY);
		if (cmpPathfinder)
			cmpPathfinder->SetDebugOverlay(!value.empty());
	}
	else if (name == L"renderpath")
	{
		g_Renderer.SetRenderPath(g_Renderer.GetRenderPathByName(CStrW(value).ToUTF8()));
	}
}
예제 #5
0
	virtual void Init(const CParamNode& paramNode)
	{
		m_FormationController = paramNode.GetChild("FormationController").ToBool();

		m_WalkSpeed = paramNode.GetChild("WalkSpeed").ToFixed();
		m_Speed = m_WalkSpeed;

		if (paramNode.GetChild("Run").IsOk())
		{
			m_RunSpeed = paramNode.GetChild("Run").GetChild("Speed").ToFixed();
		}
		else
		{
			m_RunSpeed = m_WalkSpeed;
		}

		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
		if (!cmpPathfinder.null())
		{
			m_PassClass = cmpPathfinder->GetPassabilityClass(paramNode.GetChild("PassabilityClass").ToUTF8());
			m_CostClass = cmpPathfinder->GetCostClass(paramNode.GetChild("CostClass").ToUTF8());
		}

		CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
		if (!cmpObstruction.null())
			m_Radius = cmpObstruction->GetUnitRadius();

		m_State = STATE_IDLE;
		m_PathState = PATHSTATE_NONE;

		m_ExpectedPathTicket = 0;

		m_TargetEntity = INVALID_ENTITY;

		m_FinalGoal.type = ICmpPathfinder::Goal::POINT;

		m_DebugOverlayEnabled = false;
	}
예제 #6
0
	virtual bool CheckFoundation(std::string className)
	{
		CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
		if (!cmpPosition)
			return false; // error

		if (!cmpPosition->IsInWorld())
			return false; // no obstruction

		CFixedVector2D pos = cmpPosition->GetPosition2D();

		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
		if (!cmpPathfinder)
			return false; // error

		// required precondition to use SkipControlGroupsRequireFlagObstructionFilter
		if (m_ControlGroup == INVALID_ENTITY)
		{
			LOGERROR(L"[CmpObstruction] Cannot test for foundation obstructions; primary control group must be valid");
			return false;
		}

		// Get passability class
		ICmpPathfinder::pass_class_t passClass = cmpPathfinder->GetPassabilityClass(className);

		// Ignore collisions within the same control group, or with other non-foundation-blocking shapes.
		// Note that, since the control group for each entity defaults to the entity's ID, this is typically 
		// equivalent to only ignoring the entity's own shape and other non-foundation-blocking shapes.
		SkipControlGroupsRequireFlagObstructionFilter filter(m_ControlGroup, m_ControlGroup2,
			ICmpObstructionManager::FLAG_BLOCK_FOUNDATION);

		if (m_Type == STATIC)
			return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass);
		else
			return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Size0, passClass);
	}
예제 #7
0
bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationCommand>& commands)
{
	fixed turnLengthFixed = fixed::FromInt(turnLength) / 1000;

	// TODO: the update process is pretty ugly, with lots of messages and dependencies
	// between different components. Ought to work out a nicer way to do this.

	CMessageTurnStart msgTurnStart;
	m_ComponentManager.BroadcastMessage(msgTurnStart);

	CmpPtr<ICmpPathfinder> cmpPathfinder(m_SimContext, SYSTEM_ENTITY);
	if (!cmpPathfinder.null())
		cmpPathfinder->FinishAsyncRequests();

	// Push AI commands onto the queue before we use them
	CmpPtr<ICmpAIManager> cmpAIManager(m_SimContext, SYSTEM_ENTITY);
	if (!cmpAIManager.null())
		cmpAIManager->PushCommands();

	CmpPtr<ICmpCommandQueue> cmpCommandQueue(m_SimContext, SYSTEM_ENTITY);
	if (!cmpCommandQueue.null())
		cmpCommandQueue->FlushTurn(commands);

	// Process newly generated move commands so the UI feels snappy
	if (!cmpPathfinder.null())
		cmpPathfinder->ProcessSameTurnMoves();

	// Send all the update phases
	{
		CMessageUpdate msgUpdate(turnLengthFixed);
		m_ComponentManager.BroadcastMessage(msgUpdate);
	}
	{
		CMessageUpdate_MotionFormation msgUpdate(turnLengthFixed);
		m_ComponentManager.BroadcastMessage(msgUpdate);
	}

	// Process move commands for formations (group proxy)
	if (!cmpPathfinder.null())
		cmpPathfinder->ProcessSameTurnMoves();

	{
		CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed);
		m_ComponentManager.BroadcastMessage(msgUpdate);
	}
	{
		CMessageUpdate_Final msgUpdate(turnLengthFixed);
		m_ComponentManager.BroadcastMessage(msgUpdate);
	}

	// Process moves resulting from group proxy movement (unit needs to catch up or realign) and any others
	if (!cmpPathfinder.null())
		cmpPathfinder->ProcessSameTurnMoves();


	// Clean up any entities destroyed during the simulation update
	m_ComponentManager.FlushDestroyedComponents();

//	if (m_TurnNumber == 0)
//		m_ComponentManager.GetScriptInterface().DumpHeap();

	// Run the GC occasionally
	// (TODO: we ought to schedule this for a frame where we're not
	// running the sim update, to spread the load)
	if (m_TurnNumber % 10 == 0)
		m_ComponentManager.GetScriptInterface().MaybeGC();

	if (m_EnableOOSLog)
		DumpState();

	// Start computing AI for the next turn
	if (!cmpAIManager.null())
		cmpAIManager->StartComputation();

	++m_TurnNumber;

	return true; // TODO: don't bother with bool return
}
예제 #8
0
	virtual CFixedVector3D PickSpawnPoint(entity_id_t spawned)
	{
		// Try to find a free space around the building's footprint.
		// (Note that we use the footprint, not the obstruction shape - this might be a bit dodgy
		// because the footprint might be inside the obstruction, but it hopefully gives us a nicer
		// shape.)

		const CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1));

		CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
		if (!cmpPosition || !cmpPosition->IsInWorld())
			return error;

		CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
		if (!cmpObstructionManager)
			return error;

		entity_pos_t spawnedRadius;
		ICmpObstructionManager::tag_t spawnedTag;

		CmpPtr<ICmpObstruction> cmpSpawnedObstruction(GetSimContext(), spawned);
		if (cmpSpawnedObstruction)
		{
			spawnedRadius = cmpSpawnedObstruction->GetUnitRadius();
			spawnedTag = cmpSpawnedObstruction->GetObstruction();
		}
		// else use zero radius

		// Get passability class from UnitMotion
		CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), spawned);
		if (!cmpUnitMotion)
			return error;

		ICmpPathfinder::pass_class_t spawnedPass = cmpUnitMotion->GetPassabilityClass();
		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
		if (!cmpPathfinder)
			return error;
		
		CFixedVector2D initialPos = cmpPosition->GetPosition2D();
		entity_angle_t initialAngle = cmpPosition->GetRotation().Y;

		// Max spawning distance in tiles
		const i32 maxSpawningDistance = 4;

		if (m_Shape == CIRCLE)
		{
			// Expand outwards from foundation
			for (i32 dist = 0; dist <= maxSpawningDistance; ++dist)
			{
				// The spawn point should be far enough from this footprint to fit the unit, plus a little gap
				entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(2 + (int)TERRAIN_TILE_SIZE*dist);
				entity_pos_t radius = m_Size0 + clearance;

				// Try equally-spaced points around the circle in alternating directions, starting from the front
				const i32 numPoints = 31 + 2*dist;
				for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2]
				{
					entity_angle_t angle = initialAngle + (entity_angle_t::Pi()*2).Multiply(entity_angle_t::FromInt(i)/(int)numPoints);

					fixed s, c;
					sincos_approx(angle, s, c);

					CFixedVector3D pos (initialPos.X + s.Multiply(radius), fixed::Zero(), initialPos.Y + c.Multiply(radius));

					SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
					if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Z, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
						return pos; // this position is okay, so return it
				}
			}
		}
		else
		{
			fixed s, c;
			sincos_approx(initialAngle, s, c);

			// Expand outwards from foundation
			for (i32 dist = 0; dist <= maxSpawningDistance; ++dist)
			{
				// The spawn point should be far enough from this footprint to fit the unit, plus a little gap
				entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(2 + (int)TERRAIN_TILE_SIZE*dist);

				for (i32 edge = 0; edge < 4; ++edge)
				{
					// Try equally-spaced points along the edge in alternating directions, starting from the middle
					const i32 numPoints = 9 + 2*dist;

					// Compute the direction and length of the current edge
					CFixedVector2D dir;
					fixed sx, sy;
					switch (edge)
					{
					case 0:
						dir = CFixedVector2D(c, -s);
						sx = m_Size0;
						sy = m_Size1;
						break;
					case 1:
						dir = CFixedVector2D(-s, -c);
						sx = m_Size1;
						sy = m_Size0;
						break;
					case 2:
						dir = CFixedVector2D(s, c);
						sx = m_Size1;
						sy = m_Size0;
						break;
					case 3:
						dir = CFixedVector2D(-c, s);
						sx = m_Size0;
						sy = m_Size1;
						break;
					}
					CFixedVector2D center = initialPos - dir.Perpendicular().Multiply(sy/2 + clearance);
					dir = dir.Multiply((sx + clearance*2) / (int)(numPoints-1));

					for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2]
					{
						CFixedVector2D pos (center + dir*i);

						SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
						if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
							return CFixedVector3D(pos.X, fixed::Zero(), pos.Y); // this position is okay, so return it
					}
				}
			}
		}

		return error;
	}