示例#1
0
void PointBehavior::Apply(Boid& boid)
{
	ofVec2f displacement;
	int count = 0;
	
	GameEntityState& boidState = boid.CurrentState();
	
	for (RIterator it = GetRelevant(boid.Senses.EntitiesInRange); !it.End(); ++it)
	{
		count++;
		GameEntity* entity = it.Current();
		
		// use next state if it has already been calculated, otherwise use
		GameEntityState& entityState = entity->NextState().IsReady ?  entity->NextState() : entity->CurrentState();
		ofVec2f offset = entityState.Position - boidState.Position;
		
		if (offset.length() < Range)
		{ 
			float inverseDistance = Range - offset.length();
			offset.normalize();
			ofVec2f weight = offset * inverseDistance * (IsAttractive ? 1: -1);
			displacement += weight;
		}
	}
	
	if (count <1)
		return;
		
	boid.NextState().Velocity += displacement * this->Factor;
}
示例#2
0
void BoundsBehavior::Apply(Boid& boid)
{
	ofVec2f curPos = boid.CurrentState().Position;
	float fovSize = boid.GetBoidType()->ViewDistance;	
	
	ofVec2f left(0, curPos.y);
	ofVec2f right(ofGetWidth(), curPos.y);
	ofVec2f top(curPos.x, 0);
	ofVec2f bottom(curPos.x, ofGetHeight());
	
	ofVec2f borderPoints[] = {left, right, top, bottom};
	ofVec2f newDir;
	
	for (int i = 0; i < 4; i++)
	{
		ofVec2f orthVec = borderPoints[i]-curPos;

		// if can't see orthogonal, ignore it
		if (orthVec.length() > fovSize)
			continue;
		
		// TODO: add hypotanuse checking
		
		// if orthogonal is out of range, ignore it
		if (orthVec.length() > this->Range)
			continue;
		
		float inverseDistance = fovSize - orthVec.length();
		orthVec.normalize();

		newDir -= orthVec * inverseDistance;
	}
	
	
	// ROEE: how to make a parabole
	boid.NextState().Velocity += newDir*this->Factor;
	
}
示例#3
0
void MovingBehavior::Apply(Boid& boid)
{
	ofVec2f curDirection = boid.CurrentState().Velocity;
	ofVec2f curDirectionN = curDirection.getNormalized();
	boid.NextState().Velocity += curDirectionN*5;
	
	ofVec2f nextDirection = boid.NextState().Velocity;
	ofVec2f nextDirectionN = nextDirection.getNormalized();
	float curSpeed = curDirection.length();
	float nextSpeed = nextDirection.length();
	
	// .........................
	// Limit speed & accelaration
	
	/*
	if (nextSpeed < this->MinSpeed)
	{
		// Continue previous direction if nothing specified
		if (nextSpeed == 0)
			nextDirectionN = curDirectionN;
		
		nextSpeed = this->MinSpeed;
	}
	*/
	
	if (this->MaxSpeed > 0 && nextSpeed > this->MaxSpeed)
		nextSpeed = this->MaxSpeed;
	
	if (this->MaxAccelaration > 0)
	{
		if (nextSpeed > curSpeed+curSpeed*MaxAccelaration)
			nextSpeed = curSpeed+curSpeed*MaxAccelaration;
		if (nextSpeed < curSpeed-curSpeed*MaxAccelaration)
			nextSpeed = curSpeed-curSpeed*MaxAccelaration;
	}
	
	// .........................
	// Limit rotation
	
	if (this->MaxRotation > 0)
	{
		// Compare the before and after vectors to limit rotation
		float dotProduct = ofClamp(curDirectionN.dot(nextDirectionN), -1, 1);
		float angle = acos(dotProduct);
		
		if (angle > this->MaxRotation)
		{
			angle = this->MaxRotation;
			
			// cross product tells us if we need a left or right rotation
			ofVec3f A(nextDirectionN);
			ofVec3f B(curDirectionN);
			ofVec3f C = A.getCrossed(B);
			if (C.z > 0)
				angle *= -1;
			
			nextDirectionN.rotateRad(angle);
		}
	}
	
	boid.NextState().Velocity = nextDirectionN*nextSpeed;
	boid.NextState().Position = boid.CurrentState().Position + boid.NextState().Velocity;
}
示例#4
0
void FlockingBehavior::Apply(Boid& boid)
{
	float m1 = 1.0f;
	float m2 = 1.0f;
	
	// Modifiers for flocking
	if (this->AvoidOnly)
	{
		m2 = 0.0f;
		m1 = -0.1f;
	}
	
	// ====================================
	// GROUP start
	ofVec2f group;
	
	// AVOID start
	ofVec2f avoid;
	
	// ALIGN start
	ofVec2f align;
	
	int boidCount = 0;
	ofVec2f offset;
	
	GameEntityState& boidState = boid.CurrentState();
	
	// ====================================
	
	for (RIterator it = GetRelevant(boid.Senses.EntitiesInRange); !it.End(); ++it)
	{
		boidCount++;
		GameEntity* entity = it.Current();
		
		// use next state if it has already been calculated, otherwise use
		GameEntityState& entityState = entity->NextState().IsReady ?  entity->NextState() : entity->CurrentState();
		offset = entityState.Position - boidState.Position;
		
		// ...................
		// GROUP iter
		group += entityState.Position;
		
		// ...................
		// AVOID iter
		if (offset.length() < AvoidDistance)
		{ 
			float inverseDistance = AvoidDistance - offset.length();
			// The further in the more effect we want it to have on the final heading
			// Normalize vector to get the direction 
			offset.normalize();
			// Multiply it by the inverse distance to give it magnitude
			// This gives us the vector from the edge of the avoidance circle to the boid b
			// Thus the closer boid b is to this boid the more wieght it will have on the avoidance heading
			ofVec2f weightb = offset * inverseDistance;
			avoid -= weightb;
		}
		
		// ...................
		// ALIGN iter
		align += entityState.Velocity;
		
	}
	if (boidCount < 1)
		return;
	
	// ====================================
	
	// GROUP end
	group /= boidCount;
	group = (group - boidState.Position) * GroupFactor;
	
	// AVOID end
	avoid *= 0.1f;
	
	// ALIGN end
	align /= boidCount;
	align = (align - boidState.Velocity) * AlignFactor;
	
	
	// ====================================
	// RESULT
	
	ofVec2f adjustment = ((m1*group) + avoid + (m2*align));
	//if (adjustment.length() > boid.CurrentState().Direction.length())
	//	adjustment.normalize();// *= boid.CurrentState().Direction.length();
	
	boid.NextState().Velocity += adjustment;
}