🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

flocking sim help

Started by
4 comments, last by Nypyren 9 years ago

Hey everyone :).

i'm trying to create a flocking simulation but i'm having some problems.

iv been trying to use the programming game AI by example to create it but atm all the boids just end up going to the centre (and shake around on the spot) where im more looking for a result like this

when what I get is the image attached.

I have tried to debug it but i cant see where the error is. ill post the code below and any help you can provide will be very helpful.

constructor for each boid


 flockobj::flockobj(modelloader *temp)
 {

   radiousep = 4.0f;

   radiuscohu = 10.0f;

   radiusaligh = 10.0f;

  speed = 4.0f;

  neighbors = 0;


  aligvec = glm::vec3(0.0f);
  conhesionvec = glm::vec3(0.0f);
  sperationvec = glm::vec3(0.0f);

   x = rand() % 8 - 4;
   y = rand() % 8 - 4;

 
  velocity = glm::vec3(x,y,0.0f);

  inside = false;


 }

update function


void flockobj::Update(float deltaTs )
 {
   velocity += sperationvec + aligvec + conhesionvec;

   glm::vec3 move = velocity * deltaTs; 

   _position += move;
}

alignment function


void flockobj::Alignmentcal(std::vector<flockobj*> others) //this is the behaviour that effects the alignment of your objects
{

  neighbors = 0;
  aligvec = glm::vec3(0,0,0);

  
  for(int i = 0; i < others.size(); i++)
  {
    float len =  glm::length(others[i]->returnposition() - _position);

    if(others[i] != this && len < radiusaligh)
    {

      if(glm::length(others[i]->returnvelocity()) != 0)
      {
        aligvec += glm::normalize(others[i]->returnvelocity());

        if(!_finite(aligvec.x))
        {
          float a = glm::length(others[i]->returnvelocity());
        }
      }

   

      neighbors++;
    }

  }

  if(neighbors > 0)
  {
    aligvec /= neighbors;

      if(glm::length(velocity) != 0)
      {
       aligvec -= glm::normalize(velocity);
      }
     if(glm::length(aligvec) > speed)
    {
      aligvec = glm::normalize(aligvec) * speed;
    }
     
  }
      
    


}

Cohesion function


void flockobj::Cohesioncal(std::vector<flockobj*> others) //cohesion is making sure that our objects gravitate to the center of the flock
{
  neighbors = 0;
  conhesionvec = glm::vec3(0,0,0);

  
  for(int i = 0; i < others.size(); i++)
  {
    float len =  glm::length(others[i]->returnposition() - _position);

    if(others[i] != this && len < radiusaligh)
    {
      conhesionvec += others[i]->returnposition();
      neighbors++;

       if(!_finite(conhesionvec.x))
       {
         int g = 10;
       }


    }

  }

  if(neighbors > 0)
  {
    conhesionvec /= neighbors;
    glm::vec3 temp = (conhesionvec - _position);
    temp = glm::normalize(temp) * speed;
    conhesionvec = temp - velocity;
    if(glm::length(conhesionvec) > speed)
    {
      conhesionvec = glm::normalize(conhesionvec) * speed;
    }

  }


}

Separation function


void flockobj::Separationcal(std::vector<flockobj*> others)  //seperation makes sure that our objects dont just all move the the center of mass
{
  
  sperationvec = glm::vec3(0,0,0);

  for(int i = 0; i < others.size(); i++)
  {
    float len =  glm::length(others[i]->returnposition() - _position);


    if(others[i] != this && len < radiousep)
    {
      glm::vec3 dist = _position - others[i]->returnposition();

      if(glm::length(dist) != 0)
      {
        sperationvec += glm::normalize(dist)/glm::length(dist);
      }

    }

  }
  
  if(glm::length(sperationvec) > speed)
    {
      sperationvec = glm::normalize(sperationvec) * speed;
    }


  //sperationvec = glm::normalize(sperationvec);

}

thanks in advance.

Advertisement
Your cohesion function is using the alignment radius for its check instead of the cohesion radius, but that shouldn't necessarily cause major problems.

My guess is that your existing boid velocity are just being modified too quickly by the flocking velocities.

Try multiplying the flocking velocities by small fractions such as 0.05f or so. I would personally put cohesion as the weakest force, separation slightly stronger than cohesion, and keep alignment fairly strong.

Try multiplying the flocking velocities by small fractions such as 0.05f or so. I would personally put cohesion as the weakest force, separation slightly stronger than cohesion, and keep alignment fairly strong.

do u mean times the sperationvec, aligvec and the conhesionvec by different weights?


Yeah. Something like this...play with the numbers to see how they modify the flocking:


velocity += sperationvec * 0.05f + aligvec * 0.2f + conhesionvec * 0.02f;

Yeah. Something like this...play with the numbers to see how they modify the flocking:


velocity += sperationvec * 0.05f + aligvec * 0.2f + conhesionvec * 0.02f;

thanks that helped with the boids shaking on the spot so much

the only other thing i need to ask is that at the start i give each boid a starting velocity but they still end up stationery in the middle of the screen (like the screenshot). do i have to keep adding a force impulse to make they move in a direction?

in the example website all i could see was a starting velocity and after that they went in wat i guess would be the most common direction velocity (averaged). this is wat i thought alignment was in charge off. though i would also guess that it would be separation and cohesion that would be screwing up the alignment

In some boid simulators I've seen, there is an additional check to find out whether a boid is facing another boid or not. In these sims, boids can only "see in front of themselves" and only try to flock with boids they can see. I *think* this is what allows the flock to keep its momentum in one main direction, because if any of the boids in the flock can't see anyone else, he will keep moving in a straight line, and everyone who CAN see him will follow. Another side effect is that the flock might occasionally split into separate flocks or merge back together.

You can use (DotProduct(boid.velocity, otherboid.position - boid.position) > 0) to determine whether a boid is "in front" of another or not. You can normalize the vectors and compare to a non-zero cosine value if you want to adjust the "angle" of vision. (I think I got the math right, but someone is sure to correct me if not...)


I can't tell if you're doing a vision-cone check or not. You *could* do it before you pass the 'others' parameter to the functions you posted.

Another thing you can do is add a small amount of completely random velocity change during each update, so that boids which can't see anyone else don't fly in exact straight lines.

This topic is closed to new replies.

Advertisement