Initial commit, v1.0.0
[Hacks.git] / hacks / Swarm / Swarm.js
1 /* Copyright 2011 The Dominion of Awesome
2  * See COPYING for licensing information */
3 enyo.kind({
4         name: "Pixel",
5         constructor: function(canvas) {
6                 this.x = Math.random() * canvas.width;
7                 this.y = Math.random() * canvas.height;
8                 this.vx = Math.random() * 20.0 - 10.0;
9                 this.vy = Math.random() * 20.0 - 10.0;
10                 this.lastupdate = (new Date()).getTime();
11         },
12         accel: function(x, y) {
13                 this.vx += x;
14                 if (this.vx > 200.0)
15                         this.vx = 200.0;
16                 else if (this.vx < -200.0)
17                         this.vx = -200.0;
18                 this.vy += y;
19                 if (this.vy > 200.0)
20                         this.vy = 200.0;
21                 else if (this.vy < -200.0)
22                         this.vy = -200.0;
23         },
24         update: function() {
25                 var now = (new Date()).getTime();
26                 var dt = (now - this.lastupdate) / 75.0;
27                 this.x += this.vx * dt;
28                 this.y += this.vy * dt;
29                 this.lastupdate = now;
30         },
31         draw: function(ctx) {   
32                 ctx.beginPath();
33                 ctx.moveTo(this.x,this.y);
34                 ctx.lineTo(this.x - this.vx / 4.0, this.y - this.vy / 4.0);
35                 ctx.stroke();
36                 ctx.closePath();
37         }       
38 });
39
40 enyo.kind({
41         name: "Swarm",
42         kind: "Hack",
43         align: "stretch",
44         pack: "stretch",
45         components: [
46                 {name: "canvas", nodeTag: "canvas", style: "background-color: gray",
47                  onmousemove: "mouseMove", onmousedown: "mouseDown"}
48         ],
49         npixels: 100,
50         pixels: [],
51         rendered: function() {
52                 this.canvas = this.$.canvas.hasNode();
53                 this.resize();
54                 this.mx = this.canvas.width / 2;
55                 this.my = this.canvas.width / 2;
56                 for (var x = 0; x < this.npixels; x++)
57                         this.pixels.push(new Pixel(this.canvas));
58                 //this.stopTime = (new Date()).getTime();
59                 this.engine();
60         },
61         start: function() {
62                 if (this.stopTime) {
63                         var delta = (new Date()).getTime() - this.stopTime;
64                         for (var i = 0; i < this.npixels; i++)
65                                 this.pixels[i].lastupdate += delta;
66                         this.stopTime = null;
67                 }
68                 if (!this.timer)
69                         this.timer = setInterval(this.engine.bind(this), 20);
70         },
71         stop: function() {
72                 this.stopTime = (new Date()).getTime();
73                 clearInterval(this.timer);
74                 this.timer = null;
75         },
76         resize: function(w, h) {
77                 this.canvas.width = w;
78                 this.canvas.height = h;
79                 //this.canvas.style.width = w + 'px';
80                 //this.canvas.style.height = h + 'px';
81                 this.context = this.canvas.getContext('2d');
82                 this.context.strokeStyle = '#000000';
83                 this.context.lineCap = 'round';
84                 this.context.lineWidth = 1.5;
85         },
86         mouseMove: function(inSender, inEvent) {
87                 this.mx = inEvent.clientX;
88                 this.my = inEvent.clientY;
89         },
90         mouseDown: function(inSender, inEvent) {
91                 this.mouseMove(inSender, inEvent);
92                 // Apply force to each pixel outwards from the mouse
93                 for (var i = 0; i < this.npixels; i++) {
94                         // Get the direction
95                         var dx = this.pixels[i].x - inEvent.clientX;
96                         var dy = this.pixels[i].y - inEvent.clientY;
97                         var mag = Math.sqrt(dx*dx + dy*dy);
98                         dx /= mag;
99                         dy /= mag;
100
101                         // Apply force.
102                         this.pixels[i].accel(dx * 40.0, dy * 40.0);
103                 }
104         },
105         engine: function() {
106                 // Clear the canvas
107                 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
108                 // Update all pixel objects
109                 for (var i = 0; i < this.npixels; i++) {
110                         // Get distance
111                         var dx = this.mx - this.pixels[i].x;
112                         var dy = this.my - this.pixels[i].y;
113                         var d = Math.sqrt(dx*dx + dy*dy);
114
115                         // Apply acceleration to pixels towards the mouse cursor
116                         var ax = dx / 50.0;
117                         var ay = dy / 50.0;
118
119                         // Apply a drag proportional to the distance from the cursor
120                         if (d > 100.0) {
121                                 ax += -this.pixels[i].vx * (d - 100.0) / 2000.0;
122                                 ay += -this.pixels[i].vy * (d - 100.0) / 2000.0;
123                         }
124
125                         // And a "chaotic" acceleration inversely proportional
126                         // to the distance from the cursor
127                         ax += (Math.random() * 160.0 - 80.0) / d;
128                         ay += (Math.random() * 160.0 - 80.0) / d;
129
130                         this.pixels[i].accel(ax,ay);
131                         this.pixels[i].update();
132                         this.pixels[i].draw(this.context);
133                 }
134
135                 this.context.strokeRect(this.mx - 10, this.my - 10, 20, 20);
136         }
137 });