Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html>
  2. <html>
  3.   <head>
  4.     <!--
  5.      
  6.       HeartRate, frame rate monitor and sketch.
  7.       Author: Corban Brook @corban
  8.      
  9.       Daniel Shiffman's flocking example ported from processing to javascript using HTML5 canvas.
  10.      
  11.       Using Vlad's mjs.js matrix and vector lib for speed
  12.    
  13.     -->
  14.    
  15.     <title>HTML5 Canvas - Flocking</title>
  16.     <script type="text/javascript" src="mjs.js"></script>
  17.     <script type="text/javascript" src="../heartrate.js"></script>
  18.    
  19.     <script type="text/javascript">
  20.  
  21.       var cvs,
  22.           ctx,
  23.           width,
  24.           height,
  25.           mouseX = 0,
  26.           mouseY = 0,
  27.           FPS = 50;
  28.  
  29.       document.addEventListener("DOMContentLoaded", init, false);
  30.  
  31.       var requestFrame = function() {};
  32.  
  33.       /* The init function creates a 2d context, runs setup and starts draw loop */
  34.       function init() {
  35.         cvs = document.getElementById("flocking");
  36.         ctx = cvs.getContext("2d");
  37.    
  38.         width = cvs.width, height = cvs.height;
  39.        
  40.         // Event Listeners for mouse
  41.         cvs.addEventListener('mouseup', mouseClicked, false);
  42.         cvs.addEventListener('mousemove', function(event) {
  43.           mouseX = event.clientX, mouseY = event.clientY;
  44.         }, false);
  45.  
  46.         window.heartRate = new HeartRate({ context: ctx, maxFPS: FPS, path: "../" });
  47.  
  48.         setup();
  49.        
  50.         function redraw() {
  51.           draw();
  52.           requestFrame();
  53.         }
  54.  
  55.         if (typeof window.mozRequestAnimationFrame === "function") {
  56.           (requestFrame = function() { window.mozRequestAnimationFrame(redraw); })();
  57.         } else if (typeof window.webkitRequestAnimationFrame === "function") {
  58.           (requestFrame = function() { window.webkitRequestAnimationFrame(redraw); })();
  59.         } else {
  60.           window.setInterval(redraw, 1000 / FPS);
  61.         }
  62.       }
  63.  
  64.      
  65.       function line(x1, y1, x2, y2) {
  66.         ctx.beginPath();
  67.         ctx.moveTo(x1, y1);
  68.         ctx.lineTo(x2, y2);
  69.         ctx.stroke();
  70.         ctx.closePath();
  71.       }
  72.  
  73.       function stroke(r, g, b, a) {
  74.         var prefix = a === undefined ? 'rgb(' : 'rgba(';
  75.         ctx.strokeStyle = prefix + Array.prototype.slice.call(arguments).join(",") + ')';
  76.       }
  77.  
  78.       function fill(r, g, b, a) {
  79.         var prefix = a === undefined ? 'rgb(' : 'rgba(';
  80.         ctx.fillStyle = prefix + Array.prototype.slice.call(arguments).join(",") + ')';
  81.       }
  82.      
  83.       //---------------------------------------------------------------------------
  84.  
  85.       var BIRD_TOTAL = 100;
  86.  
  87.       var flock;
  88.       var skip = 1;
  89.  
  90.       function setup() {
  91.         flock = new Flock();
  92.    
  93.         // Add initial flock of birds into the system
  94.         for (var i = 0; i < BIRD_TOTAL; i++) {
  95.           flock.addBird(new Bird(V3.$(width/2, height/2, 0), 2, 0.05));
  96.         }
  97.       }
  98.  
  99.       function draw() {
  100.         // Clear background
  101.         fill(240, 240, 240, 0.5);
  102.         ctx.fillRect(0, 0, cvs.width, cvs.height);
  103.        
  104.         flock.run();
  105.        
  106.         heartRate.monitor(2, 2);
  107.  
  108.         fill(40, 40, 40);
  109.         ctx.fillText(flock.birds.length + " particles", 730, 14);
  110.       }
  111.  
  112.       function mouseClicked() {
  113.         // Add 50 more birds under your mouse
  114.         for (var i = 0; i < BIRD_TOTAL; i++) {
  115.           flock.addBird(new Bird(V3.$(mouseX, mouseY, 0), 2, 0.05));
  116.         }
  117.       }
  118.  
  119.       function Flock() {
  120.         this.birds = [];
  121.       }
  122.  
  123.       Flock.prototype.run = function() {    
  124.         for (var i = 0; i < this.birds.length; i++) {
  125.           this.birds[i].run(this.birds); // Passing entire list of birds to each bird
  126.         }
  127.       };
  128.  
  129.       Flock.prototype.addBird = function(bird) {
  130.         this.birds.push(bird);
  131.       };
  132.  
  133.       function Bird(loc, maxSpeed, maxForce) {
  134.         this.loc      = V3.clone(loc);
  135.         this.vel      = V3.$(Math.random() * 2 - 1, Math.random() * 2 - 1, 0);
  136.         this.acc      = V3.$(0, 0, 0);
  137.    
  138.         this.r        = 5;
  139.         this.maxSpeed = maxSpeed;
  140.         this.maxForce = maxForce;
  141.       }
  142.  
  143.       Bird.prototype.run = function(birds) {
  144.         this.flock(birds);
  145.         this.update();
  146.         this.borders();
  147.         this.render();
  148.       };
  149.      
  150.       // if these 3 vars are defined here a strange flocking behavior occures
  151.       // whereas all birds fly to 0, 0 (top left corner)
  152.       var sep = V3.$(0, 0, 0);
  153.       var ali = V3.$(0, 0, 0);
  154.       var coh = V3.$(0, 0, 0);
  155.      
  156.       var diff = V3.$();
  157.      
  158.       var neighborDistance = 2500; // 50 squared
  159.       var desiredSeparation = 625; // 25 squared
  160.  
  161.       Bird.prototype.flock = function(birds) {
  162.         // if these 3 vectors are defined here each time flock is called, it works fine.
  163.         //var separation = V3.$(0, 0, 0);
  164.         //var alignment = V3.$(0, 0, 0);
  165.         //var cohesion = V3.$(0, 0, 0);
  166.        
  167.         var separation = sep;
  168.         var alignment = ali;
  169.         var cohesion = coh;
  170.        
  171.         V3.set(separation, 0, 0, 0);
  172.         V3.set(alignment, 0, 0, 0);
  173.         V3.set(cohesion, 0, 0, 0);
  174.        
  175.  
  176.        
  177.        
  178.         // and yes the set function does work. these vectors are all 0, 0, 0
  179.        
  180.         var sCount = 0, count = 0;
  181.  
  182.         for(var i = 0, len = birds.length; i < len; i ++) {
  183.           var d = V3.distanceSquared(this.loc, birds[i].loc);
  184.           if (d > 0) {
  185.             if (d < desiredSeparation) {
  186.               V3.sub(this.loc, birds[i].loc, diff);
  187.               V3.normalize(diff, diff);
  188.               V3.scale(diff, 1/Math.sqrt(d), diff);
  189.               V3.add(separation, diff, separation);
  190.               sCount++;
  191.             }
  192.          
  193.             if (d < neighborDistance) {
  194.               V3.add(alignment, birds[i].vel, alignment);
  195.            
  196.               V3.add(cohesion, birds[i].loc, cohesion);
  197.               count++;
  198.             }
  199.           }
  200.         }
  201.        
  202.         if (sCount > 0) {
  203.           V3.scale(separation, 1/sCount, separation);
  204.           V3.scale(separation, 2.0, separation); // weight separation
  205.          
  206.           V3.add(this.acc, separation, this.acc);
  207.         }
  208.        
  209.         if (count > 0) {
  210.           V3.scale(alignment, 1/count, alignment);
  211.           V3.limit(alignment, this.maxForce, alignment);
  212.          
  213.           V3.scale(cohesion, 1/count, cohesion);
  214.           cohesion = this.steer(cohesion, false);
  215.          
  216.           V3.add(this.acc, alignment, this.acc);
  217.           V3.add(this.acc, cohesion, this.acc);
  218.         }
  219.       };
  220.  
  221.       Bird.prototype.update = function() {
  222.         // Update velocity
  223.         V3.add(this.vel, this.acc, this.vel);
  224.    
  225.         // Limit speed
  226.         V3.limit(this.vel, this.maxSpeed, this.vel);
  227.         V3.add(this.loc, this.vel, this.loc);
  228.        
  229.         // Reset acceleration to zero
  230.         V3.set(this.acc, 0, 0, 0);
  231.       };
  232.  
  233.       Bird.prototype.seek = function(target) {
  234.         V3.add(this.acc, this.steer(target, false), this.acc);
  235.       };
  236.  
  237.       Bird.prototype.arrive = function(target) {
  238.         V3.add(this.acc, this.steer(target, true), this.acc);
  239.       };
  240.  
  241.       var desired = V3.$();
  242.       var steer = V3.$();
  243.  
  244.       Bird.prototype.steer = function(target, slowDown) {
  245.         //var steer = V3.$(0, 0, 0);
  246.         //var desired = V3.sub(target, this.loc);
  247.         V3.set(steer, 0, 0, 0);
  248.         V3.sub(target, this.loc, desired);
  249.         var d = V3.length(desired);
  250.        
  251.         if (d > 0) {
  252.           V3.normalize(desired, desired);
  253.        
  254.           if (slowDown && d < 100) {
  255.             V3.scale(desired, this.maxSpeed*(d/100), desired);
  256.           } else {
  257.             V3.scale(desired, this.maxSpeed, desired);
  258.           }
  259.          
  260.           V3.sub(desired, this.vel, steer);
  261.           V3.limit(steer, this.maxForce, steer);
  262.         }
  263.        
  264.         return steer;
  265.       };
  266.  
  267.       Bird.prototype.borders = function() {
  268.         var r = this.r, loc = this.loc;
  269.  
  270.         if (loc[0] < -r)         { loc[0] = width + r; }
  271.         if (loc[1] < -r)         { loc[1] = height + r; }
  272.         if (loc[0] > width + r)  { loc[0] = -r; }
  273.         if (loc[1] > height + r) { loc[1] = -r; }
  274.       };
  275.  
  276.       Bird.prototype.render = function() {
  277.         var theta = V3.heading2D(this.vel) + Math.PI/2;
  278.         ctx.save(); // push matrix
  279.           ctx.translate(this.loc[0], this.loc[1]);
  280.           ctx.rotate(theta);
  281.           line(0, this.r, 0, 0);
  282.         ctx.restore(); // pop matrix
  283.       };
  284.     </script>
  285.   </head>
  286.   <body>
  287.     <canvas id="flocking" width="800" height="600"></canvas>
  288.     <p>Click to add more particles. Push your browser to the limit. -- @corban</p>
  289.   </body>
  290. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement