This paper will use front-end technology to simulate 2D and 3D flocks of birds. I choose Canvas element to draw, and of course, CSS3 or SVG can also be used.

  • Making github.com/dwqdaiwenqi… Remember to hit star

The whole implementation demo

I used Threejs for 3d rendering

For 2d rendering engine, I choose CAX. Cax is a rendering engine THAT I like very much. It supports small programs, small games and Web browser rendering. It can be used to develop both mini games and charts (see wechart), highly recommended!

2 d birds

2d demo

These birds aren’t just flying around aimlessly, they all seem to have developed intelligence, forming groups and producing complex group movements

This seemingly complex behavior is a composite behavior, usually broken down into the following types

Separation

Cohesion

Alignment

These three properties separate, converge, and queue together to produce a motor-flying flock (swarm)

Given the complex behavior of the flock, we don’t have to know the overall wisdom of the flock. Each bird just needs to apply those three characteristics to the other birds in its range, and naturally form a colony. Take a look at the following code, the code is not much optimization, will do:

Create birds and add them to the scene

var birds = Array.from({length:60},(v,i)=>{
  var bird = new Bird()
  stage.add(bird)

  Object.assign(bird,{
    po: new Vector(stage.width*rd(),stage.height*rd())
    ,ve: new Vector(rd() * 20 - 10, rd() * 20 - 10),ac: new Vector()
  }) 
  return bird
})

this.tick = cax.tick((a)= >{
  stage.update()
  birds.forEach(b= >b.update(stage,birds))
})
Copy the code

Key Update methods

update(birds){
 // Ignore yourself
 birds = birds.filter(o= >this! =o)// separation
 for(let bird of birds){
   // Too close
   if(this.po.distanceTo(bird.po) < Bird.sDist){
     // Subtract the steering force to achieve separation
     this.ac.sub(
       bird.po.clone()
       .sub(this.po).normalize()
       .multiplyScalar(Bird.MAX_SPEED)
       .sub(this.ve)
     )
   } 
 }

 // cohesion
 let cohesion =  birds.reduce((param, b) = >{
   if(this.po.distanceTo(b.po) < Bird.cDist){
     param.sum.add(b.po)
     param.count++
   }
   return param
 },{sum:new Vector(),count:0.force:new Vector()})

 if(cohesion.count>0) {// Find the average position first, use the average position to find the desired target speed, and then add the calculated steering force to the acceleration
   this.ac.add(
     cohesion.sum.divideScalar(cohesion.count)
     .sub(this.po).normalize()
     .multiplyScalar(Bird.MAX_SPEED)
     .sub(this.ve)
   )
 }


 // alignment
 let alignment =  birds.reduce((param, b) = >{
   if(this.po.distanceTo(b.po) < Bird.aDist){
     param.sum.add(b.ve)
     param.count++
   }
   return param
 },{sum:new Vector(),count:0.force:new Vector()})

 if(alignment.count>0) {// First calculate the average speed, then calculate the desired target speed using the average speed, and then add the calculated steering force to the acceleration
   this.ac.add(
     alignment.sum.divideScalar(alignment.count).normalize()
     .multiplyScalar(Bird.MAX_SPEED)
     .sub(this.ve) 
   )
 }
 // Do not exceed maximum steering force and speed
 if(this.ac.length > Bird.MAX_FORCE) this.ac.normalize().multiplyScalar(Bird.MAX_FORCE)
 if(this.ve.length > Bird.MAX_SPEED) this.ve.normalize().multiplyScalar(Bird.MAX_SPEED)
 
 // Slow down the heavy birds
 this.ve.add(this.ac.divideScalar(this.mass))
 this.po.add(this.ve) 
 
 // ...
  
}
 
Copy the code

Ignore yourself first, and if you search for birds that are too close, add the calculated steering force to the acceleration. It should be noted that there is an additional condition for judging too close, that is, in the field of view. (this.ve. Dot (this.po.clone().sub(bird.po))) < 0); Will form a different community effect.

We can also overlay layers of information to produce more complex simulations. The birds are all of the same type, you can add an eagle object, if the distance between the bird and the eagle exceeds a certain threshold the bird will immediately run away. To simulate this, just add an escape behavior to the system, which also causes the bird’s overall steering force, speed, to increase.

3 d the flock

3d demo

The implementation of 3D and 2D are similar in principle, the only thing to pay attention to is that the object needs to turn to the target direction, which is usually handled by quaternion, the key to the code is

 this.rot.setFromQuaternion(
      new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0.1.0), new THREE.Vector3(this.ve.x, this.ve.y, this.ve.z).normalize())
    )
    
 this.rotation.copy(new THREE.Euler(this.rot.x,this.rot.y,this.rot.z))
Copy the code

reference

  • www.red3d.com/cwr/boids/