Boids

by ElijahCirioli

HTML

<canvas id="myCanvas" width="1000" height="700"></canvas>
<div id=controls>
	<button id="resetButton">RESET</button>
	<button id="createButton" class="switchButton">CREATE</button><button id="scatterButton" class="switchButton">SCATTER</button>
	<button id="debugButton"></button><p id=debugLabel>SHOW DEBUG</p>
	<input type="range" min="2" max="100" value="40" class="slider" id="speedSlider">
	<input type="range" min="0" max="100" value="50" class="slider" id="inertiaSlider">
	<canvas id="triCanvas" width="160" height="160"></canvas>
	<p id=controlLabels>Mouse mode &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; Speed &emsp; &emsp; &emsp; &nbsp; &emsp; &emsp; Inertia</p>
</div>

CSS

body {
	-webkit-user-select: none; /* Safari */        
	-moz-user-select: none; /* Firefox */
	-ms-user-select: none; /* IE10+/Edge */
	user-select: none; /* Standard */
}
#myCanvas {
  border: 5px solid #3A5032;
  display: block;
}
#controls {
  display: block;
  margin-top: 10px;
}
#resetButton {
  background-color: #506E45;
  color: white;
  border: none;
  /* font-family: "Montserrat",serif; */
  text-align: center;
  line-height: 30px;
  font-size: 18px;
  padding: 5px 20px 5px 20px;
  cursor: pointer;
  outline: none;
}
.switchButton {
  margin: 0 auto;
  /* font-family: "Montserrat",serif; */
  text-align: center;
  padding: 5px 0 5px 0;
  line-height: 30px;
  font-size: 18px;
  cursor: pointer;
  border: none;
  width: 100px;
  outline: none;
}
#createButton {
  background-color: #506E45;
  margin-left: 25px;
  color: white;
}
#scatterButton {
  background-color: #c9c9c9;
}
#debugButton {
  background-color: #c9c9c9;
  width: 25px;
  height: 25px;
  border: none;
  outline: none;
  margin: 0 0 0 25px;
  vertical-align: middle;
  cursor: pointer;
}
#debugLabel {
  display: inline;
  line-height: 25px;
  font-size: 12px;
  margin-left: 7px;
  vertical-align: middle;
  font-family: Arial, Helvetica, sans-serif;
}
.slider {
  -webkit-appearance: none;
  appearance: none;
  background: #c9c9c9;
  outline: none;
  height: 25px;
  margin: -5px 0 0 25px;
  vertical-align: middle;
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 25px;
  background: #506E45;
  cursor: pointer;
}
.slider::-moz-range-thumb {
  width: 12px;
  height: 25px;
  background: #506E45;
  cursor: pointer;
}
#controlLabels {
  display: block;
  color: #383838;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 16px;
  margin: 5px 0 0 179px;
}
#triCanvas {
	position: absolute;
	margin-left: 40px;
	cursor: pointer;
}

JavaScript

//setup canvas
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");

//initialize variables
var boids = []; //all the boids
var distance = 100; //the radius of the boid's neighborhood (px)
var viewAngle = 5 * Math.PI / 3; //the viewing angle of the boid's neighborhood (radians)
var boidCount = 70; //how many boids to create
var speed = 4.0; //how fast the boids move
var showDebug = false; //show view angle and rays for one boid
var mouseMode = 0; //0 = draw boids, 1 = scatter
var mouseDown = false; //is the mouse being pressed down
var pred = new Predator(0, 0, 0); //the predator to scatter the boids away from

//define weights for the three rules
var separationWeight = 1;
var alignmentWeight = 1;
var cohesionWeight = 1;
//how much the rules affect the current velocity
var inertia = 0.5;

//define a boid
function Boid(x, y, velX, velY) {
  this.x = x;
  this.y = y;
  this.direction = 0;
  this.velX = velX;
  this.velY = velY;
  this.neighborhood = [];
}

//define a predator
function Predator(x, y, life) {
  this.x = x;
  this.y = y;
  this.life = life;
}

//game cycle
function update() {
  moveBoids();
  draw();
}

//update the velocity vectors of all boids and move
function moveBoids() {
  for (var i = 0; i < boids.length; i++) {
    var b = boids[i];
    b.neighborhood = getNeighborhood(b); //get all boids within Distance radius and viewAngle

    //gather the vectors from the three rules
    var vec1 = b.separation();
    var vec2 = b.alignment();
    var vec3 = b.cohesion();
    var vec4 = b.guidance();

    //add the vectors together and multiply weights
    b.velX += inertia * ((vec1[0] * separationWeight) + (vec2[0] * alignmentWeight) + (vec3[0] * cohesionWeight) + vec4[0]);
    b.velY += inertia * ((vec1[1] * separationWeight) + (vec2[1] * alignmentWeight) + (vec3[1] * cohesionWeight) + vec4[1]);

    //normalize the speed to what it should be
    var nomalizedVector = normalize([b.velX, b.velY], speed);
    b.velX =...