src/boid.js
function avoid(obstacles) {
        for (let i = 0; i < obstacles.length; i++) {
            const obstacle = obstacles[i];
            const heading = velocity.clone().normalize();

            // vec between obstacle and boid
            const difference = obstacle.position.clone().subtract(position);
            const dotProd = difference.dotProduct(heading);

            // if obstacle in front of boid
            if (dotProd > 0) {
                // vec to represent 'feeler' arm
                const feeler = heading.clone().scaleBy(avoidDistance);
                // project difference onto feeler
                const projection = heading.clone().scaleBy(dotProd);
                // distance from obstacle to feeler
                const vecDistance = projection.subtract(difference);
                const distance = vecDistance.length;
                // if feeler intersects obstacle (plus buffer), and projection
                // less than feeler length, will collide
                if (distance < (obstacle.radius || 0) + avoidBuffer && projection.length < feeler.length) {
                    // calc a force +/- 90 deg from vec to circ
                    const force = heading.clone().scaleBy(maxSpeed);
                    force.angle += difference.sign(velocity) * PI_D2;
                    // scale force by distance (further = smaller force)
                    const dist = projection.length / feeler.length;
                    force.scaleBy(1 - dist);
                    // add to steering force
                    steeringForce.add(force);
                    // braking force - slows boid down so it has time to turn (closer = harder)
                    velocity.scaleBy(dist);

                    force.dispose();
                }
                feeler.dispose();
                projection.dispose();
                vecDistance.dispose();
            }
            heading.dispose();
            difference.dispose();
        }
        return boid;
    }
function avoid(obstacles) {
        for (let i = 0; i < obstacles.length; i++) {
            const obstacle = obstacles[i];
            const heading = velocity.clone().normalize();

            // vec between obstacle and boid
            const difference = obstacle.position.clone().subtract(position);
            const dotProd = difference.dotProduct(heading);

            // if obstacle in front of boid
            if (dotProd > 0) {
                // vec to represent 'feeler' arm
                const feeler = heading.clone().scaleBy(avoidDistance);
                // project difference onto feeler
                const projection = heading.clone().scaleBy(dotProd);
                // distance from obstacle to feeler
                const vecDistance = projection.subtract(difference);
                const distance = vecDistance.length;
                // if feeler intersects obstacle (plus buffer), and projection
                // less than feeler length, will collide
                if (distance < (obstacle.radius || 0) + avoidBuffer && projection.length < feeler.length) {
                    // calc a force +/- 90 deg from vec to circ
                    const force = heading.clone().scaleBy(maxSpeed);
                    force.angle += difference.sign(velocity) * PI_D2;
                    // scale force by distance (further = smaller force)
                    const dist = projection.length / feeler.length;
                    force.scaleBy(1 - dist);
                    // add to steering force
                    steeringForce.add(force);
                    // braking force - slows boid down so it has time to turn (closer = harder)
                    velocity.scaleBy(dist);

                    force.dispose();
                }
                feeler.dispose();
                projection.dispose();
                vecDistance.dispose();
            }
            heading.dispose();
            difference.dispose();
        }
        return boid;
    }
function avoid ( obstacles ) { for ( let i = 0 ; i < obstacles . length ; i ++ ) { const obstacle = obstacles [ i ] ; const heading = velocity . clone ( ) . normalize ( ) ; // vec between obstacle and boid const difference = obstacle . position . clone ( ) . subtract ( position ) ; const dotProd = difference . dotProduct ( heading ) ; // if obstacle in front of boid if ( dotProd > 0 ) { // vec to represent 'feeler' arm const feeler = heading . clone ( ) . scaleBy ( avoidDistance ) ; // project difference onto feeler const projection = heading . clone ( ) . scaleBy ( dotProd ) ; // distance from obstacle to feeler const vecDistance = projection . subtract ( difference ) ; const distance = vecDistance . length ; // if feeler intersects obstacle (plus buffer), and projection // less than feeler length, will collide if ( distance < ( obstacle . radius || 0 ) + avoidBuffer && projection . length < feeler . length ) { // calc a force +/- 90 deg from vec to circ const force = heading . clone ( ) . scaleBy ( maxSpeed ) ; force . angle += difference . sign ( velocity ) * PI_D2 ; // scale force by distance (further = smaller force) const dist = projection . length / feeler . length ; force . scaleBy ( 1 - dist ) ; // add to steering force steeringForce . add ( force ) ; // braking force - slows boid down so it has time to turn (closer = harder) velocity . scaleBy ( dist ) ; force . dispose ( ) ; } feeler . dispose ( ) ; projection . dispose ( ) ; vecDistance . dispose ( ) ; } heading . dispose ( ) ; difference . dispose ( ) ; } return boid ; }
gets a bit rough used in combination with seeking as the boid attempts to seek straight through an object while simultaneously trying to avoid it
gets a bit rough used in combination with seeking as the boid attempts to seek straight through an object while simultaneously trying to avoid it