PathEngine home previous: 'TestApplication'next: 'PathStress'
Contents, Programmers Guide, Example Projects, Other Examples, 'Swarm'

'Swarm'

Description

Implementing a basic queueing behaviour.
This example is based on tutorial 2.
An agent may be placed and moved around the environment under user control. (As in tutorial 2.)
A group of 'swarmer' agents is added which either chase or flee from the user controlled agent, based on a user toggleable flag.

The 'swarmer' agents demonstrate a simple but effective queuing mechanism.
The trick is that a group of agents sharing the same goals should not treat each other as fixed obstacles.
When one agents is blocked by another, the situation can often be resolved by the blocked agent simply waiting for the blocking agent to move on.

In some situations agents will be 'mutually blocking'.
In this situation for example, neither agent can continue on their path without colliding with the other:

A situation like this can be resolved by one agent pathfinding around the other:

This mechanism is implemented by the following code snippet:
(from main.cpp)

iCollisionInfo *collisioninfo=swarmer_agents[i]->advanceAlongPath(swarmer_paths[i],5.0f,context);
if(collisioninfo)
{
	iAgent *blocking_agent=collisioninfo->getCollidingAgent();
	delete collisioninfo;

	if(swarmers_attack && blocking_agent==agent)
		blocking_agent=0;

	if(blocking_agent)
	{
		temporary_context->addAgent(blocking_agent);
		
		uint32_t length_before = swarmer_paths[i]->getLength();
		delete swarmer_paths[i];

		if(swarmers_attack)
			swarmer_paths[i]=swarmer_agents[i]->findShortestPathTo(temporary_context,agent->getPosition());
		else
			swarmer_paths[i]=swarmer_agents[i]->findPathAway(temporary_context,agent->getPosition(),400);

		uint32_t length_after=swarmer_paths[i]->getLength();

		if(length_after<length_before+40)
		{
			collisioninfo=
				swarmer_agents[i]->advanceAlongPath(swarmer_paths[i],5.0f,context);
			delete collisioninfo;
		}
		else
		{
			delete swarmer_paths[i];
			swarmer_paths[i]=0;
		}

		temporary_context->removeAgent(blocking_agent);
	}
}

If the agent is blocked from advancing along their path then we obtain a pointer to the blocking agent from the iCollisionInfo object returned by iAgent::advanceAlongPath().

The blocking agent is added to a temporary context and a new path generated taking that agent into account.

Note that we don't actually need to determine whether the agents are mutually blocking.
We prevent agents from taking long detours by checking the increase in length for the new path.

Spreading the load

To spread the load, only one swarmer is allowed to pathfind each frame.
This is implemented with the 'next_swarmer' variable that is incremented each frame.

Jams

The code is pretty robust (given its simplicity) but not 100 percent.
Agents will only ever move towards their goal, but in some situations it's necessary to move away from the goal in order to clear a jam.

It's possible to get the swarmers agents in this application to jam. (Have a go!)
The problem occurs where there are narrow sections of the mesh (in relation to the size of the queuing agents).

Other group movement examples

Some more discussion about implementing group movement behaviours within PathEngine, and other group movement examples, can be found here.


Documentation for PathEngine release 6.00 - Copyright © 2002-2016 PathEnginenext: 'PathStress'