Add Labyrinth
[Hacks.git] / hacks / Labyrinth / Labyrinth.js
1 /* Copyright 2011 The Dominion of Awesome
2  * See COPYING for licensing information */
3 enyo.kind({
4         name: "Labyrinth",
5         kind: "Hack",
6         style: "background-color: blue",
7         preferences: [
8                 {name: "speed", label: "Speed", kind: "Slider", maximum: 20, minimum: 1, snap: 1},
9                 {name: "handedness", label: "Left/Right Bias", kind: "Slider", maximum: 1, minimum: 0, snap: 0.01},
10                 {name: "foregroundColor", label: "Foreground Color", kind: "ListSelector", items: colorList},
11                 {name: "backgroundColor", label: "Background Color", kind: "ListSelector", items: colorList}
12         ],
13         speed: 5,
14         handedness: 0.5,
15         foregroundColor: 'white',
16         backgroundColor: 'blue',
17         grid: null,
18         boundary: null,
19         count: 0,
20         rest: 0,
21         components: [
22                 {name: "viewport", nodeTag: "canvas"}
23         ],
24         rendered: function() {
25                 this.viewport = this.$.viewport.hasNode();
26                 this.ctx = this.viewport.getContext('2d');
27                 this.init();
28         },
29         start: function() {
30                 if (!this.timer)
31                         this.timer = setInterval(this.draw.bind(this), 50);
32         },
33         stop: function() {
34                 clearInterval(this.timer);
35                 this.timer = null;
36         },
37         resize: function(w, h) {
38                 this.viewport.width = this.w = w;
39                 this.viewport.height = this.h = h;
40
41                 this.ctx.fillStyle = this.backgroundColor;
42                 this.ctx.strokeStyle = this.foregroundColor;
43
44                 this.ctx.fillRect(0, 0, w, h);
45
46                 this.gw = Math.ceil(w / 8);
47                 this.gh = Math.ceil(h / 8);
48                 this.grid = new Array(this.gw);
49                 for (var i = 0; i < this.gw; i++) {
50                         this.grid[i] = new Array(this.gh);
51                 }
52
53                 var x = Math.floor(Math.random() * this.gw);
54                 var y = Math.floor(Math.random() * this.gh);
55                 this.grid[x][y] = Math.random() > this.handedness ? false : true;
56                 this.boundary = [{x: x, y: y}];
57                 this.count = 1;
58                 this.render(x, y);
59         },
60         preferencesChanged: function() {
61                 this.init();
62         },
63         init: function() {
64                 this.resize(window.innerWidth, window.innerHeight);
65         },
66         pick: function() {
67                 var c = this.boundary[Math.floor(Math.random() * this.boundary.length)];
68                 var possibilities = [];
69                 for (var x = -1; x <= 1; x++) {
70                         for (var y = -1; y <= 1; y++) {
71                                 if (y == 0 && x == 0)
72                                         continue;
73                                 if (c.x + x < 0 || c.x + x >= this.gw || c.y + y < 0 || c.y + y >= this.gh)
74                                         continue;
75                                 if (typeof(this.grid[c.x + x][c.y + y]) == 'undefined') {
76                                         possibilities.push({x: c.x + x, y: c.y + y});
77                                 }
78                         }
79                 }
80                 if (possibilities.length == 0) {
81                         for (var i = 0; i < this.boundary.length; i++) {
82                                 if (this.boundary[i].x == c.x && this.boundary[i].y == c.y) {
83                                         this.boundary.splice(i, 1);
84                                         break;
85                                 }
86                         }
87                         return this.pick();
88                 }
89
90                 var nc = possibilities[Math.floor(Math.random() * possibilities.length)];
91                 this.grid[nc.x][nc.y] = Math.random() > this.handedness ? false : true;
92                 this.boundary.push(nc);
93                 return nc;
94         },
95         render: function(x, y) {
96                 this.ctx.beginPath();
97                 if (this.grid[x][y] === true) {
98                         this.ctx.moveTo(x * 8 + 8, y * 8);
99                         this.ctx.lineTo(x * 8, y * 8 + 8);
100                 } else if (this.grid[x][y] === false) {
101                         this.ctx.moveTo(x * 8, y * 8);
102                         this.ctx.lineTo(x * 8 + 8, y * 8 + 8);
103                 }
104                 this.ctx.stroke();
105         },
106         draw: function() {
107                 if (this.rest > 0) {
108                         if (this.rest == 1)
109                                 this.init();
110                         this.rest--;
111                         return;
112                 }
113
114                 for (var i = 0; i < this.speed; i++) {
115                         var c = this.pick();
116                         this.render(c.x, c.y);
117                         this.count++;
118                         if (this.count == this.gw * this.gh) {
119                                 this.rest = 60;
120                                 return;
121                         }
122                 }
123         }
124 });