Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <!--
- HeartRate, frame rate monitor and sketch.
- Author: Corban Brook @corban
- Daniel Shiffman's flocking example ported from processing to javascript using HTML5 canvas.
- Using Vlad's mjs.js matrix and vector lib for speed
- -->
- <title>HTML5 Canvas - Flocking</title>
- <script type="text/javascript" src="mjs.js"></script>
- <script type="text/javascript" src="../heartrate.js"></script>
- <script type="text/javascript">
- var cvs,
- ctx,
- width,
- height,
- mouseX = 0,
- mouseY = 0,
- FPS = 50;
- document.addEventListener("DOMContentLoaded", init, false);
- var requestFrame = function() {};
- /* The init function creates a 2d context, runs setup and starts draw loop */
- function init() {
- cvs = document.getElementById("flocking");
- ctx = cvs.getContext("2d");
- width = cvs.width, height = cvs.height;
- // Event Listeners for mouse
- cvs.addEventListener('mouseup', mouseClicked, false);
- cvs.addEventListener('mousemove', function(event) {
- mouseX = event.clientX, mouseY = event.clientY;
- }, false);
- window.heartRate = new HeartRate({ context: ctx, maxFPS: FPS, path: "../" });
- setup();
- function redraw() {
- draw();
- requestFrame();
- }
- if (typeof window.mozRequestAnimationFrame === "function") {
- (requestFrame = function() { window.mozRequestAnimationFrame(redraw); })();
- } else if (typeof window.webkitRequestAnimationFrame === "function") {
- (requestFrame = function() { window.webkitRequestAnimationFrame(redraw); })();
- } else {
- window.setInterval(redraw, 1000 / FPS);
- }
- }
- function line(x1, y1, x2, y2) {
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.stroke();
- ctx.closePath();
- }
- function stroke(r, g, b, a) {
- var prefix = a === undefined ? 'rgb(' : 'rgba(';
- ctx.strokeStyle = prefix + Array.prototype.slice.call(arguments).join(",") + ')';
- }
- function fill(r, g, b, a) {
- var prefix = a === undefined ? 'rgb(' : 'rgba(';
- ctx.fillStyle = prefix + Array.prototype.slice.call(arguments).join(",") + ')';
- }
- //---------------------------------------------------------------------------
- var BIRD_TOTAL = 100;
- var flock;
- var skip = 1;
- function setup() {
- flock = new Flock();
- // Add initial flock of birds into the system
- for (var i = 0; i < BIRD_TOTAL; i++) {
- flock.addBird(new Bird(V3.$(width/2, height/2, 0), 2, 0.05));
- }
- }
- function draw() {
- // Clear background
- fill(240, 240, 240, 0.5);
- ctx.fillRect(0, 0, cvs.width, cvs.height);
- flock.run();
- heartRate.monitor(2, 2);
- fill(40, 40, 40);
- ctx.fillText(flock.birds.length + " particles", 730, 14);
- }
- function mouseClicked() {
- // Add 50 more birds under your mouse
- for (var i = 0; i < BIRD_TOTAL; i++) {
- flock.addBird(new Bird(V3.$(mouseX, mouseY, 0), 2, 0.05));
- }
- }
- function Flock() {
- this.birds = [];
- }
- Flock.prototype.run = function() {
- for (var i = 0; i < this.birds.length; i++) {
- this.birds[i].run(this.birds); // Passing entire list of birds to each bird
- }
- };
- Flock.prototype.addBird = function(bird) {
- this.birds.push(bird);
- };
- function Bird(loc, maxSpeed, maxForce) {
- this.loc = V3.clone(loc);
- this.vel = V3.$(Math.random() * 2 - 1, Math.random() * 2 - 1, 0);
- this.acc = V3.$(0, 0, 0);
- this.r = 5;
- this.maxSpeed = maxSpeed;
- this.maxForce = maxForce;
- }
- Bird.prototype.run = function(birds) {
- this.flock(birds);
- this.update();
- this.borders();
- this.render();
- };
- // if these 3 vars are defined here a strange flocking behavior occures
- // whereas all birds fly to 0, 0 (top left corner)
- var separation = V3.$(0, 0, 0);
- var alignment = V3.$(0, 0, 0);
- var cohesion = V3.$(0, 0, 0);
- var diff = V3.$();
- var neighborDistance = 2500; // 50 squared
- var desiredSeparation = 625; // 25 squared
- Bird.prototype.flock = function(birds) {
- // if these 3 vectors are defined here each time flock is called, it works fine.
- //var separation = V3.$(0, 0, 0);
- //var alignment = V3.$(0, 0, 0);
- //var cohesion = V3.$(0, 0, 0);
- V3.set(separation, 0, 0, 0);
- V3.set(alignment, 0, 0, 0);
- V3.set(cohesion, 0, 0, 0);
- // and yes the set function does work. these vectors are all 0, 0, 0
- var sCount = 0, count = 0;
- for(var i = 0, len = birds.length; i < len; i ++) {
- var d = V3.distanceSquared(this.loc, birds[i].loc);
- if (d > 0) {
- if (d < desiredSeparation) {
- V3.sub(this.loc, birds[i].loc, diff);
- V3.normalize(diff, diff);
- V3.scale(diff, 1/(d/10), diff);
- V3.add(separation, diff, separation);
- sCount++;
- }
- if (d < neighborDistance) {
- V3.add(alignment, birds[i].vel, alignment);
- V3.add(cohesion, birds[i].loc, cohesion);
- count++;
- }
- }
- }
- if (sCount > 0) {
- V3.scale(separation, 1/sCount, separation);
- V3.scale(separation, 2.0, separation); // weight separation
- V3.add(this.acc, separation, this.acc);
- }
- if (count > 0) {
- V3.scale(alignment, 1/count, alignment);
- V3.limit(alignment, this.maxForce, alignment);
- V3.scale(cohesion, 1/count, cohesion);
- cohesion = this.steer(cohesion, false);
- V3.add(this.acc, alignment, this.acc);
- V3.add(this.acc, cohesion, this.acc);
- }
- };
- Bird.prototype.update = function() {
- // Update velocity
- V3.add(this.vel, this.acc, this.vel);
- // Limit speed
- V3.limit(this.vel, this.maxSpeed, this.vel);
- V3.add(this.loc, this.vel, this.loc);
- // Reset acceleration to zero
- V3.set(this.acc, 0, 0, 0);
- };
- Bird.prototype.seek = function(target) {
- V3.add(this.acc, this.steer(target, false), this.acc);
- };
- Bird.prototype.arrive = function(target) {
- V3.add(this.acc, this.steer(target, true), this.acc);
- };
- var desired = V3.$();
- var steer = V3.$();
- Bird.prototype.steer = function(target, slowDown) {
- //var steer = V3.$(0, 0, 0);
- //var desired = V3.sub(target, this.loc);
- V3.set(steer, 0, 0, 0);
- V3.sub(target, this.loc, desired);
- var d = V3.length(desired);
- if (d > 0) {
- V3.normalize(desired, desired);
- if (slowDown && d < 100) {
- V3.scale(desired, this.maxSpeed*(d/100), desired);
- } else {
- V3.scale(desired, this.maxSpeed, desired);
- }
- V3.sub(desired, this.vel, steer);
- V3.limit(steer, this.maxForce, steer);
- }
- return steer;
- };
- Bird.prototype.borders = function() {
- var r = this.r, loc = this.loc;
- if (loc[0] < -r) { loc[0] = width + r; }
- if (loc[1] < -r) { loc[1] = height + r; }
- if (loc[0] > width + r) { loc[0] = -r; }
- if (loc[1] > height + r) { loc[1] = -r; }
- };
- Bird.prototype.render = function() {
- var theta = V3.heading2D(this.vel) + Math.PI/2;
- ctx.save(); // push matrix
- ctx.translate(this.loc[0], this.loc[1]);
- ctx.rotate(theta);
- line(0, this.r, 0, 0);
- ctx.restore(); // pop matrix
- };
- </script>
- </head>
- <body>
- <canvas id="flocking" width="800" height="600"></canvas>
- <p>Click to add more particles. Push your browser to the limit. -- @corban</p>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement