├── media
└── particle.png
├── excludes
├── .gitignore
├── lib
├── game
│ ├── main.js
│ ├── entities
│ │ ├── particle.js
│ │ └── particle-fast.js
│ ├── particles.js
│ └── particles-fast.js
└── plugins
│ └── fill-browser.js
├── package.json
├── impact.html
├── impact-fast.html
├── Gruntfile.js
├── README.md
├── pixi.html
├── canvas.html
├── dom.html
├── fpsmeter.min.js
├── webgl.v2.html
├── index.html
├── webgl.v3.html
├── webgl.html
├── dat.gui.min.js
└── particles.min.js
/media/particle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quidmonkey/particle_test/HEAD/media/particle.png
--------------------------------------------------------------------------------
/excludes:
--------------------------------------------------------------------------------
1 | Gruntfile.js
2 | Makefile
3 | package.json
4 | tools
5 | lib
6 | node_modules
7 | .git
8 | .gitignore
9 | README.md
10 | excludes
11 | .DS_Store
12 | debug-webgl.js
13 | deploy.json
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | lib/impact
3 | lib/impact/*
4 | lib/weltmeister
5 | lib/weltmeister/*
6 | tools
7 | tools/*
8 | Makefile
9 | node_modules
10 | node_modules/*
11 | webgl-debug.js
12 | deploy.json
13 | particles.min.js
14 |
--------------------------------------------------------------------------------
/lib/game/main.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'game.main'
3 | )
4 | .requires(
5 | 'plugins.fill-browser',
6 |
7 | 'game.particles',
8 | 'game.particles-fast'
9 | )
10 | .defines(function(){ "use strict";
11 |
12 | /* Empty module to require all debug panels */
13 |
14 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "particles",
3 | "htmlFiles": [
4 | "impact.html",
5 | "impact-fast.html"
6 | ],
7 | "version": "0.1.0",
8 | "devDependencies": {
9 | "grunt": "~0.4.1",
10 | "grunt-contrib-uglify": "~0.2.0",
11 | "grunt-shell": "~0.2.2",
12 | "shelljs": "~0.1.3"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/game/entities/particle.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'game.entities.particle'
3 | )
4 | .requires(
5 | 'impact.entity'
6 | )
7 | .defines(function () {
8 |
9 | EntityParticle = ig.Entity.extend({
10 |
11 | animSheet: new ig.AnimationSheet('media/particle.png', 13, 13),
12 | vel: { x: 200, y: 200 },
13 |
14 | init: function (x, y, settings) {
15 | this.parent(x, y, settings);
16 |
17 | this.addAnim('idle', 1, [0]);
18 |
19 | this.vel.x = this.vel.x * Math.random() - this.vel.x / 2;
20 | this.vel.y = this.vel.y * Math.random() - this.vel.y / 2;
21 | },
22 |
23 | update: function () {
24 | this.parent();
25 |
26 | if (this.pos.x < 0 || this.pos.x + this.size.x > ig.system.width) {
27 | this.vel.x = -this.vel.x;
28 | }
29 | if (this.pos.y < 0 || this.pos.y + this.size.y > ig.system.height) {
30 | this.vel.y = -this.vel.y;
31 | }
32 | }
33 |
34 | });
35 |
36 | });
37 |
--------------------------------------------------------------------------------
/impact.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Impact Game
5 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/impact-fast.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Impact Game
5 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/lib/game/entities/particle-fast.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'game.entities.particle-fast'
3 | )
4 | .requires(
5 | 'impact.entity'
6 | )
7 | .defines(function () {
8 |
9 | // constructor
10 | // does not inherit from ig.Class which instantiates
11 | // classes slowly due to ig.copy
12 | EntityParticleFast = function (x, y) {
13 | this.pos = {
14 | x: x,
15 | y: y
16 | };
17 |
18 | this.vel = {
19 | x: this.vel.x * Math.random() - this.vel.x / 2,
20 | y: this.vel.y * Math.random() - this.vel.y / 2
21 | }
22 | };
23 |
24 | // class
25 | // only define necessary attributes
26 | EntityParticleFast.prototype = {
27 |
28 | image: new ig.Image('media/particle.png', 13, 13),
29 | size: { x: 13, y: 13 },
30 | vel: { x: 200, y: 200 },
31 |
32 | // skip the crawl through ig.Animation and ig.Image
33 | // make the drawImage call directly
34 | draw: function () {
35 | ig.system.context.drawImage(this.image.data, ~~this.pos.x, ~~this.pos.y);
36 | },
37 |
38 | // remove gravity, collision map trace and animation update
39 | update: function () {
40 | // simplified euler integration
41 | // in-lined to remove the overhead of a function call
42 | this.pos.x += this.vel.x * ig.system.tick;
43 | this.pos.y += this.vel.y * ig.system.tick;
44 |
45 | if (this.pos.x < 0 || this.pos.x + this.size.x > ig.system.width) {
46 | this.vel.x = -this.vel.x;
47 | }
48 | if (this.pos.y < 0 || this.pos.y + this.size.y > ig.system.height) {
49 | this.vel.y = -this.vel.y;
50 | }
51 | }
52 | };
53 |
54 | });
55 |
--------------------------------------------------------------------------------
/lib/game/particles.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'game.particles'
3 | )
4 | .requires(
5 | 'impact.game',
6 | 'game.entities.particle'
7 | )
8 | .defines(function () {
9 |
10 | ParticleTest = ig.Game.extend({
11 |
12 | clearColor: '#FFFFFF',
13 | fps: null,
14 | gui: null,
15 | TOTAL_PARTICLES: 200,
16 |
17 | init: function () {
18 | this.fps = new FPSMeter(document.body, { theme: 'dark', heat: 1, graph: 1 });
19 |
20 | this.gui = new dat.GUI();
21 | this.gui.add(this, 'TOTAL_PARTICLES', 0, 15000);
22 |
23 | this.spawnParticles(this.TOTAL_PARTICLES);
24 | },
25 |
26 | checkParticleCount: function (count) {
27 | if (this.entities.length < count) {
28 | this.spawnParticles(count - this.entities.length);
29 | } else if (this.entities.length > count) {
30 | this.entities.length = count;
31 | }
32 | },
33 |
34 | spawnParticles: function (count) {
35 | var particleWidth = EntityParticle.prototype.size.x;
36 | var particleHeight = EntityParticle.prototype.size.y;
37 |
38 | for (var i = 0; i < count; i++) {
39 | this.spawnEntity(
40 | EntityParticle,
41 | Math.random() * (ig.system.width - particleWidth),
42 | Math.random() * (ig.system.height - particleHeight)
43 | );
44 | }
45 | },
46 |
47 | update: function () {
48 | this.checkParticleCount(~~this.TOTAL_PARTICLES);
49 | this.parent();
50 | this.fps.tick();
51 | }
52 |
53 | });
54 |
55 | // ig.main('#canvas', ParticleTest, 60, 500, 500, 1);
56 |
57 | });
58 |
--------------------------------------------------------------------------------
/lib/game/particles-fast.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'game.particles-fast'
3 | )
4 | .requires(
5 | 'impact.game',
6 | 'game.entities.particle-fast'
7 | )
8 | .defines(function () {
9 |
10 | // remove all this.parent calls
11 | // which invoke closures that are
12 | // expensive computationally
13 | ParticleTestFast = ig.Game.extend({
14 |
15 | fps: null,
16 | gui: null,
17 | TOTAL_PARTICLES: 500,
18 |
19 | init: function () {
20 | this.fpsDiv = document.getElementById('fps');
21 |
22 | this.fps = new FPSMeter(document.body, { theme: 'dark', heat: 1, graph: 1 });
23 |
24 | this.gui = new dat.GUI();
25 | this.gui.add(this, 'TOTAL_PARTICLES', 0, 20000);
26 |
27 | this.spawnParticles(this.TOTAL_PARTICLES);
28 | },
29 |
30 | checkParticleCount: function (count) {
31 | if (this.entities.length < count) {
32 | this.spawnParticles(count - this.entities.length);
33 | } else if (this.entities.length > count) {
34 | this.entities.length = count;
35 | }
36 | },
37 |
38 | // skip over spawnEntity since it does
39 | // more than we need
40 | spawnParticles: function (count) {
41 | var particleWidth = EntityParticleFast.prototype.size.x;
42 | var particleHeight = EntityParticleFast.prototype.size.y;
43 |
44 | for (var i = 0; i < count; i++) {
45 | this.entities.push(
46 | new EntityParticleFast(
47 | Math.random() * (ig.system.width - particleWidth),
48 | Math.random() * (ig.system.height - particleHeight)
49 | )
50 | );
51 | }
52 | },
53 |
54 | // ig.Game.run calls update and draw separately
55 | // let's override that and call them both in one loop
56 | // let's remove collision detection/resolution, background maps
57 | // and entities array management
58 | run: function () {
59 | this.checkParticleCount(~~this.TOTAL_PARTICLES);
60 |
61 | // in-line clear canvas call to remove
62 | // overhead of function call
63 | // use clearRect vs fillRect
64 | ig.system.context.clearRect(0, 0, ig.system.realWidth, ig.system.realHeight);
65 |
66 | // update and draw in one go!
67 | for (var i = 0, len = this.entities.length; i < len; i++) {
68 | var ent = this.entities[i];
69 | ent.update();
70 | ent.draw();
71 | }
72 |
73 | this.fps.tick();
74 | }
75 |
76 | });
77 |
78 | // ig.main('#canvas', ParticleTestFast, 60, 500, 500, 1);
79 |
80 | });
81 |
--------------------------------------------------------------------------------
/lib/plugins/fill-browser.js:
--------------------------------------------------------------------------------
1 | ig.module(
2 | 'plugins.fill-browser'
3 | )
4 | .requires(
5 | 'impact.system'
6 | )
7 | .defines(function () {
8 |
9 | // disable if on mobile
10 | if (ig.ua.mobile) { return; }
11 |
12 | // set to true to retain canvas's aspect ratio
13 | // set to false to fill entire window
14 | ig.System.keepAspectRatio = true;
15 |
16 | ig.System.initialDebugInject = true;
17 | ig.System.initialDebugPanelOffset = 28;
18 |
19 | ig.System.fillBrowser = function () {
20 | var canvas = document.getElementsByTagName('canvas')[0];
21 |
22 | if (typeof canvas === 'undefined') { return; }
23 |
24 | var windowHeight = window.innerHeight;
25 | var newWidth, newHeight;
26 |
27 | if (ig.Debug) {
28 | var debugPanel = document.getElementsByClassName('ig_debug')[0];
29 | windowHeight -= debugPanel.clientHeight;
30 | canvas.style.top = -debugPanel.clientHeight + 'px';
31 |
32 | if (ig.System.initialDebugInject) {
33 | // since this is the initial call
34 | // the debug stylesheet isn't loaded yet
35 | // so let's hardcode the value
36 | // for a quick and dirty fix
37 | windowHeight = window.innerHeight - ig.System.initialDebugPanelOffset;
38 | canvas.style.top = -ig.System.initialDebugPanelOffset + 'px';
39 |
40 | ig.Debug.inject({
41 | togglePanel: function (panel) {
42 | this.parent(panel);
43 | ig.System.fillBrowser();
44 | }
45 | });
46 | ig.System.canDebugInject = false;
47 | }
48 | }
49 |
50 | if (ig.System.keepAspectRatio) {
51 | var dWidth = window.innerWidth / canvas.width;
52 | var dHeight = windowHeight / canvas.height;
53 |
54 | if (dWidth < dHeight) {
55 | newWidth = dWidth * canvas.width;
56 | newHeight = dWidth * canvas.height;
57 | } else {
58 | newWidth = dHeight * canvas.width;
59 | newHeight = dHeight * canvas.height;
60 | }
61 | } else {
62 | newWidth = window.innerWidth;
63 | newHeight = windowHeight;
64 | }
65 |
66 | canvas.style.width = ~~newWidth + 'px';
67 | canvas.style.height = ~~newHeight + 'px';
68 | }
69 |
70 | ig.System.inject({
71 |
72 | init: function (canvasId, fps, width, height, scale) {
73 | ig.System.scaleMode = ig.System.SCALE.CRISP;
74 | this.parent(canvasId, fps, width, height, scale);
75 | },
76 |
77 | resize: function (width, height, scale) {
78 | this.parent(width, height, scale);
79 | ig.System.fillBrowser();
80 | }
81 |
82 | });
83 |
84 | window.onresize = ig.System.fillBrowser;
85 |
86 | });
87 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | var pkg = grunt.file.readJSON('package.json');
4 | var shell = require('shelljs');
5 |
6 | grunt.initConfig({
7 | dpy: grunt.file.readJSON('deploy.json'),
8 | pkg: grunt.file.readJSON('package.json'),
9 | shell: {
10 | // bake impact game
11 | bake: {
12 | command: 'cd tools/ && ./bake.sh && cd .. && mv game.min.js <%= pkg.name %>.min.js'
13 | },
14 | // deploy to an android running cocoonjs
15 | cocoon: {
16 | command: 'zip <%= pkg.name %>.zip -r * -x "*.DS_Store" && adb push <%= pkg.name %>.zip /sdcard/<%= pkg.name %>.zip',
17 | options: {
18 | stdout: true
19 | }
20 | },
21 | // deploy to a remote server
22 | deploy: {
23 | command: 'rsync -avz --exclude-from "<%= dpy.excludesFile %>" $PWD <%= dpy.deployUser %>@<%= dpy.deployServer %>:<%= dpy.deployDir %>',
24 | options: {
25 | stdout: true
26 | }
27 | },
28 | // expose ig globally for compilation purposes
29 | expose: {
30 | command: 'sed -i s/^ig./window.ig./g <%= pkg.name %>.min.js'
31 | }
32 | },
33 | uglify: {
34 | options: {
35 | banner: '/*! <%= pkg.name %>.min.js <%= grunt.template.today("dd-mm-yyyy") %> */\n'
36 | },
37 | build: {
38 | src: '<%= pkg.name %>.min.js',
39 | dest: '<%= pkg.name %>.min.js'
40 | }
41 | }
42 | });
43 |
44 | // load dependencies
45 | grunt.loadNpmTasks('grunt-contrib-uglify');
46 | grunt.loadNpmTasks('grunt-shell');
47 |
48 | // tasks
49 | grunt.registerTask('default', ['shell:bake', 'uglify']);
50 | grunt.registerTask('bake', ['shell:bake']);
51 | grunt.registerTask('build', ['shell:bake', 'uglify']);
52 | grunt.registerTask('cocoon', ['shell:cocoon']);
53 | grunt.registerTask('deploy', ['shell:deploy']);
54 | grunt.registerTask('expose', ['shell:expose']);
55 |
56 | // tasks built from other tasks
57 | grunt.registerTask('prepare', 'bake and inject minified script', function () {
58 | grunt.task.run(['shell:bake', 'uglify', 'inject']);
59 | });
60 | grunt.registerTask('publish', 'bake and deploy', function () {
61 | grunt.task.run(['shell:bake', 'uglify', 'inject', 'shell:deploy', 'revert']);
62 | });
63 |
64 | // custom tasks
65 | // remove impact scripts and inject minified script
66 | grunt.registerTask('inject', 'inject minified script', function () {
67 | pkg.htmlFiles.forEach(function (fileName) {
68 | shell.exec('sed -i \
69 | -e s#lib/impact/impact.js#' + pkg.name + '.min.js#g \
70 | -e s#lib/game/main.js##g \
71 | ' + fileName
72 | );
73 | });
74 | });
75 |
76 | // remove minified script and inject impact scripts
77 | grunt.registerTask('revert', 'revert minified script', function () {
78 | pkg.htmlFiles.forEach(function (fileName) {
79 | shell.exec('sed -i \
80 | -e s#' + pkg.name + '.min.js#lib/impact/impact.js#g \
81 | -e \'s#\"\"#\"lib/game/main.js\"#g\' \
82 | ' + fileName
83 | );
84 | });
85 | });
86 |
87 | };
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Canvas vs. DOM vs. WebGL vs. ImpactJS vs. PixiJS Particle Test
2 |
3 | This is a particle-based performance test comparing the [ImpactJS](http://impactjs.com/) game engine, 2D Canvas, WebGL and [PixiJS](https://github.com/GoodBoyDigital/pixi.js).
4 |
5 | The test features 8 HTML files:
6 |
7 | - canvas.html - 2D Canvas Test
8 | - dom.html - DOM Test
9 | - impact.html - ImpactJS Test
10 | - impact-fast.html - ImpactJS Test Using a Faster Implementation
11 | - pixi.html - PixiJS Test
12 | - webgl.html - WebGL Test #1 (interleaved)
13 | - webgl.v2.html - WebGL Test #2 (gl.POINTS)
14 | - webgl.v3.html - WebGL Test #3 (GPU Parallelism) - [Live Example](http://quidmonkey.github.io/particle_test/)
15 |
16 | Both the ImpactJS tests require a copy of the ImpactJS game engine. The Canvas and WebGL tests are standalone files.
17 |
18 | It is recommended that you adjust the slider in the upper right-hand corner until you reach 30 FPS and compare particle counts among the tests.
19 |
20 | ## DOM
21 |
22 | A DOM test is included as a base for benchmarking. It should be clear that of all tests, this is the slowest. Recent developments in web technology have allowed canvas rendering to far outstrip the DOM, and any web application which requires more than a few hundred elements onscreen simultaneously should forgo the DOM in favor of Canvas. Unfortunately, it is hard to get a proper 1-to-1 comparison between DOM and Canvas due to the differences in styling: where scaling a canvas can be achieve by styling its width and height (and by extension, any image drawn within it), the DOM requires styling to be defined for each element; thus, the browser needs to interpolate each img tag vs. a single canvas tag to achieve the same effect.
23 |
24 | ## ImpactJS
25 |
26 | The ImpactJS and the 2D Canvas performance tests make of use the canvas element's 2d context, but where ImpactJS wraps rendering in the trappings of a game engine, the 2D Canvas test seeks to render to the canvas directly.
27 |
28 | One of the goals of this test was to highlight the performance of the current ImpactJS implementation. ImpactJS makes use of John Resig's [Classical Object-Oriented Implementation](http://ejohn.org/blog/simple-javascript-inheritance/), which involves the use of closures to simulate inheritance. Unfortunately, such an elegant solution is not without its tradeoffs. When combined with Impact's heavy function use, the result is a significant performance hit.
29 |
30 | It should be noted that comparing a game engine to an optimized particle renderer is like comparing apples and oranges. To that extent, a faster ImpactJS test is included. This implementation seeks to route around some of the more time-consuming aspects of ImpactJS (collision detection, background map logic, etc.) as well as offer up some examples on how to get more performance from the game engine.
31 |
32 | You are encouraged to compare the implementation of both the standard ImpactJS particle implementation and the optimized one; in particular, [particle.js](lib/game/entities/particle.js) vs. [particle-fast.js](lib/game/entities/particle-fast.js) and [particles.js](lib/game/particles.js) vs. [particles-fast.js](lib/game/particles-fast.js). Both the *-fast.js files are heavily commented to highlight their differences.
33 |
34 | Special thanks to [Amadeus Demarzi](https://github.com/amadeus) for his help with the impact-fast implementation. The optimizations are as much his as they are mine.
35 |
36 | ## PixiJS
37 |
38 | While PixiJS can't match a native WebGL implementation, it does quite well. Unfortunately, it appears PixiJS implements a great deal of pre-processing in order to properly batch GL calls. Be aware that manipulating the particle count will incur some downtime while Pixi preps for batching.
39 |
40 | ## WebGL
41 |
42 | Three native WebGL tests are included. The first uses an interleaving technique to pass data to WebGL via a vertex buffer object (VBO). Both vertex and fragment shader are passed, with each quad weighing in at a hefty 30 floats. The second test passes vertices as gl.POINTS vs. gl.TRIANGLES, and uses the pre-defined gl_PointSize and gl_PointCoord to interpolate fragment data. Overall, this results in ~4-5 fps or an 8% performance increase. The third and final test passes a gl.POINTS VBO during initialization and only passes a single float each frame (delta time), allowing the particles to run entirely on the GPU, unhindered by Javascript. This results in massive performance gains.
43 |
44 | ## Errata
45 |
46 | All tests make use of [Dat GUI](https://code.google.com/p/dat-gui/) for changing particle count on-the-fly and [FPS Meter](http://darsa.in/fpsmeter/) for tracking frames-per-second.
47 |
--------------------------------------------------------------------------------
/pixi.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
20 |
21 |
22 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/canvas.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/dom.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
29 |
30 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
--------------------------------------------------------------------------------
/fpsmeter.min.js:
--------------------------------------------------------------------------------
1 | /*! FPSMeter 0.3.0 - 24th Apr 2013 | https://github.com/Darsain/fpsmeter */
2 | (function(r,j){function s(a,e){for(var g in e)try{a.style[g]=e[g]}catch(j){}return a}function H(a){return Object.prototype.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase()}function R(a,e){if("array"!==H(e))return-1;if(e.indexOf)return e.indexOf(a);for(var g=0,j=e.length;gd.interval?(x=M(k),m()):(x=setTimeout(k,d.interval),P=M(m))}function G(a){a=a||window.event;a.preventDefault?(a.preventDefault(),a.stopPropagation()):(a.returnValue=!1,a.cancelBubble=!0);b.toggle()}function U(){d.toggleOn&&S(f.container,d.toggleOn,G,1);
6 | a.removeChild(f.container)}function V(){f.container&&U();h=D.theme[d.theme];y=h.compiledHeatmaps||[];if(!y.length&&h.heatmaps.length){for(p=0;p=m?m*(1+j):m+j-m*j;0===l?g="#000":(t=2*m-l,k=(l-t)/l,g*=6,n=Math.floor(g),v=g-n,v*=l*k,0===n||6===n?(n=l,k=t+v,l=t):1===n?(n=l-v,k=l,l=t):2===n?(n=t,k=l,l=t+
7 | v):3===n?(n=t,k=l-v):4===n?(n=t+v,k=t):(n=l,k=t,l-=v),g="#"+N(n)+N(k)+N(l));b[e]=g}}h.compiledHeatmaps=y}f.container=s(document.createElement("div"),h.container);f.count=f.container.appendChild(s(document.createElement("div"),h.count));f.legend=f.container.appendChild(s(document.createElement("div"),h.legend));f.graph=d.graph?f.container.appendChild(s(document.createElement("div"),h.graph)):0;w.length=0;for(var q in f)f[q]&&h[q].heatOn&&w.push({name:q,el:f[q]});u.length=0;if(f.graph){f.graph.style.width=
8 | d.history*h.column.width+(d.history-1)*h.column.spacing+"px";for(c=0;c
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
332 |
333 |
350 |
351 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
323 |
324 |
364 |
365 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
--------------------------------------------------------------------------------
/webgl.v3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
323 |
324 |
364 |
365 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
--------------------------------------------------------------------------------
/webgl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
376 |
377 |
395 |
396 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
--------------------------------------------------------------------------------
/dat.gui.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * dat-gui JavaScript Controller Library
3 | * http://code.google.com/p/dat-gui
4 | *
5 | * Copyright 2011 Data Arts Team, Google Creative Lab
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | */
13 | var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){var a=a||document,c=a.createElement("link");c.type="text/css";c.rel="stylesheet";c.href=e;a.getElementsByTagName("head")[0].appendChild(c)},inject:function(e,a){var a=a||document,c=document.createElement("style");c.type="text/css";c.innerHTML=e;a.getElementsByTagName("head")[0].appendChild(c)}}}();
14 | dat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(c[f]=a[f])},this);return c},defaults:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(c[f])&&(c[f]=a[f])},this);return c},compose:function(){var c=a.call(arguments);return function(){for(var d=a.call(arguments),f=c.length-1;f>=0;f--)d=[c[f].apply(this,d)];return d[0]}},
15 | each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var b=0,n=a.length;b-1?d.length-d.indexOf(".")-1:0};c.superclass=e;a.extend(c.prototype,e.prototype,{setValue:function(a){if(this.__min!==void 0&&athis.__max)a=this.__max;this.__step!==void 0&&a%this.__step!=0&&(a=Math.round(a/this.__step)*this.__step);return c.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return c}(dat.controllers.Controller,dat.utils.common);
29 | dat.controllers.NumberControllerBox=function(e,a,c){var d=function(f,b,e){function h(){var a=parseFloat(l.__input.value);c.isNaN(a)||l.setValue(a)}function j(a){var b=o-a.clientY;l.setValue(l.getValue()+b*l.__impliedStep);o=a.clientY}function m(){a.unbind(window,"mousemove",j);a.unbind(window,"mouseup",m)}this.__truncationSuspended=false;d.superclass.call(this,f,b,e);var l=this,o;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",h);
30 | a.bind(this.__input,"blur",function(){h();l.__onFinishChange&&l.__onFinishChange.call(l,l.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",j);a.bind(window,"mouseup",m);o=b.clientY});a.bind(this.__input,"keydown",function(a){if(a.keyCode===13)l.__truncationSuspended=true,this.blur(),l.__truncationSuspended=false});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input,
31 | b;if(this.__truncationSuspended)b=this.getValue();else{b=this.getValue();var c=Math.pow(10,this.__precision);b=Math.round(b*c)/c}a.value=b;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common);
32 | dat.controllers.NumberControllerSlider=function(e,a,c,d,f){var b=function(d,c,f,e,l){function o(b){b.preventDefault();var d=a.getOffset(g.__background),c=a.getWidth(g.__background);g.setValue(g.__min+(g.__max-g.__min)*((b.clientX-d.left)/(d.left+c-d.left)));return false}function y(){a.unbind(window,"mousemove",o);a.unbind(window,"mouseup",y);g.__onFinishChange&&g.__onFinishChange.call(g,g.getValue())}b.superclass.call(this,d,c,{min:f,max:e,step:l});var g=this;this.__background=document.createElement("div");
33 | this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",o);a.bind(window,"mouseup",y);o(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};b.superclass=e;b.useDefaultStyles=function(){c.inject(f)};d.extend(b.prototype,e.prototype,{updateDisplay:function(){this.__foreground.style.width=
34 | (this.getValue()-this.__min)/(this.__max-this.__min)*100+"%";return b.superclass.prototype.updateDisplay.call(this)}});return b}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,".slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}");
35 | dat.controllers.FunctionController=function(e,a,c){var d=function(c,b,e){d.superclass.call(this,c,b);var h=this;this.__button=document.createElement("div");this.__button.innerHTML=e===void 0?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();h.fire();return false});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;c.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this,
36 | this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);
37 | dat.controllers.BooleanController=function(e,a,c){var d=function(c,b){d.superclass.call(this,c,b);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},false);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&&
38 | this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){this.getValue()===true?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=true):this.__checkbox.checked=false;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);
39 | dat.color.toString=function(e){return function(a){if(a.a==1||e.isUndefined(a.a)){for(a=a.hex.toString(16);a.length<6;)a="0"+a;return"#"+a}else return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common);
40 | dat.color.interpret=function(e,a){var c,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
41 | return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return a.length!=
42 | 3?false:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return a.length!=4?false:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:false},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&&
43 | a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:false},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:false},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:false},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d=
44 | false;var b=arguments.length>1?a.toArray(arguments):arguments[0];a.each(f,function(e){if(e.litmus(b))return a.each(e.conversions,function(e,f){c=e.read(b);if(d===false&&c!==false)return d=c,c.conversionName=f,c.conversion=e,a.BREAK}),a.BREAK});return d}}(dat.color.toString,dat.utils.common);
45 | dat.GUI=dat.gui.GUI=function(e,a,c,d,f,b,n,h,j,m,l,o,y,g,i){function q(a,b,r,c){if(b[r]===void 0)throw Error("Object "+b+' has no property "'+r+'"');c.color?b=new l(b,r):(b=[b,r].concat(c.factoryArgs),b=d.apply(a,b));if(c.before instanceof f)c.before=c.before.__li;t(a,b);g.addClass(b.domElement,"c");r=document.createElement("span");g.addClass(r,"property-name");r.innerHTML=b.property;var e=document.createElement("div");e.appendChild(r);e.appendChild(b.domElement);c=s(a,e,c.before);g.addClass(c,k.CLASS_CONTROLLER_ROW);
46 | g.addClass(c,typeof b.getValue());p(a,c,b);a.__controllers.push(b);return b}function s(a,b,d){var c=document.createElement("li");b&&c.appendChild(b);d?a.__ul.insertBefore(c,params.before):a.__ul.appendChild(c);a.onResize();return c}function p(a,d,c){c.__li=d;c.__gui=a;i.extend(c,{options:function(b){if(arguments.length>1)return c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[i.toArray(arguments)]});if(i.isArray(b)||i.isObject(b))return c.remove(),q(a,c.object,c.property,
47 | {before:c.__li.nextElementSibling,factoryArgs:[b]})},name:function(a){c.__li.firstElementChild.firstElementChild.innerHTML=a;return c},listen:function(){c.__gui.listen(c);return c},remove:function(){c.__gui.remove(c);return c}});if(c instanceof j){var e=new h(c.object,c.property,{min:c.__min,max:c.__max,step:c.__step});i.each(["updateDisplay","onChange","onFinishChange"],function(a){var b=c[a],H=e[a];c[a]=e[a]=function(){var a=Array.prototype.slice.call(arguments);b.apply(c,a);return H.apply(e,a)}});
48 | g.addClass(d,"has-slider");c.domElement.insertBefore(e.domElement,c.domElement.firstElementChild)}else if(c instanceof h){var f=function(b){return i.isNumber(c.__min)&&i.isNumber(c.__max)?(c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[c.__min,c.__max,c.__step]})):b};c.min=i.compose(f,c.min);c.max=i.compose(f,c.max)}else if(c instanceof b)g.bind(d,"click",function(){g.fakeEvent(c.__checkbox,"click")}),g.bind(c.__checkbox,"click",function(a){a.stopPropagation()});
49 | else if(c instanceof n)g.bind(d,"click",function(){g.fakeEvent(c.__button,"click")}),g.bind(d,"mouseover",function(){g.addClass(c.__button,"hover")}),g.bind(d,"mouseout",function(){g.removeClass(c.__button,"hover")});else if(c instanceof l)g.addClass(d,"color"),c.updateDisplay=i.compose(function(a){d.style.borderLeftColor=c.__color.toString();return a},c.updateDisplay),c.updateDisplay();c.setValue=i.compose(function(b){a.getRoot().__preset_select&&c.isModified()&&B(a.getRoot(),true);return b},c.setValue)}
50 | function t(a,b){var c=a.getRoot(),d=c.__rememberedObjects.indexOf(b.object);if(d!=-1){var e=c.__rememberedObjectIndecesToControllers[d];e===void 0&&(e={},c.__rememberedObjectIndecesToControllers[d]=e);e[b.property]=b;if(c.load&&c.load.remembered){c=c.load.remembered;if(c[a.preset])c=c[a.preset];else if(c[w])c=c[w];else return;if(c[d]&&c[d][b.property]!==void 0)d=c[d][b.property],b.initialValue=d,b.setValue(d)}}}function I(a){var b=a.__save_row=document.createElement("li");g.addClass(a.domElement,
51 | "has-save");a.__ul.insertBefore(b,a.__ul.firstChild);g.addClass(b,"save-row");var c=document.createElement("span");c.innerHTML=" ";g.addClass(c,"button gears");var d=document.createElement("span");d.innerHTML="Save";g.addClass(d,"button");g.addClass(d,"save");var e=document.createElement("span");e.innerHTML="New";g.addClass(e,"button");g.addClass(e,"save-as");var f=document.createElement("span");f.innerHTML="Revert";g.addClass(f,"button");g.addClass(f,"revert");var m=a.__preset_select=document.createElement("select");
52 | a.load&&a.load.remembered?i.each(a.load.remembered,function(b,c){C(a,c,c==a.preset)}):C(a,w,false);g.bind(m,"change",function(){for(var b=0;b0){a.preset=this.preset;if(!a.remembered)a.remembered={};a.remembered[this.preset]=z(this)}a.folders={};i.each(this.__folders,function(b,
69 | c){a.folders[c]=b.getSaveObject()});return a},save:function(){if(!this.load.remembered)this.load.remembered={};this.load.remembered[this.preset]=z(this);B(this,false)},saveAs:function(a){if(!this.load.remembered)this.load.remembered={},this.load.remembered[w]=z(this,true);this.load.remembered[a]=z(this);this.preset=a;C(this,a,true)},revert:function(a){i.each(this.__controllers,function(b){this.getRoot().load.remembered?t(a||this.getRoot(),b):b.setValue(b.initialValue)},this);i.each(this.__folders,
70 | function(a){a.revert(a)});a||B(this.getRoot(),false)},listen:function(a){var b=this.__listening.length==0;this.__listening.push(a);b&&E(this.__listening)}});return k}(dat.utils.css,'\n\n Here\'s the new load parameter for your
GUI\'s constructor:\n\n
\n\n
\n\n
Automatically save\n values to
localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n
',
71 | ".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n",
72 | dat.controllers.factory=function(e,a,c,d,f,b,n){return function(h,j,m,l){var o=h[j];if(n.isArray(m)||n.isObject(m))return new e(h,j,m);if(n.isNumber(o))return n.isNumber(m)&&n.isNumber(l)?new c(h,j,m,l):new a(h,j,{min:m,max:l});if(n.isString(o))return new d(h,j);if(n.isFunction(o))return new f(h,j,"");if(n.isBoolean(o))return new b(h,j)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,c){var d=
73 | function(c,b){function e(){h.setValue(h.__input.value)}d.superclass.call(this,c,b);var h=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())});a.bind(this.__input,"keydown",function(a){a.keyCode===13&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,
74 | e.prototype,{updateDisplay:function(){if(!a.isActive(this.__input))this.__input.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController,
75 | dat.controllers.ColorController=function(e,a,c,d,f){function b(a,b,c,d){a.style.background="";f.each(j,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+c+" 0%, "+d+" 100%); "})}function n(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
76 | a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var h=function(e,l){function o(b){q(b);a.bind(window,"mousemove",q);a.bind(window,
77 | "mouseup",j)}function j(){a.unbind(window,"mousemove",q);a.unbind(window,"mouseup",j)}function g(){var a=d(this.value);a!==false?(p.__color.__state=a,p.setValue(p.__color.toOriginal())):this.value=p.__color.toString()}function i(){a.unbind(window,"mousemove",s);a.unbind(window,"mouseup",i)}function q(b){b.preventDefault();var c=a.getWidth(p.__saturation_field),d=a.getOffset(p.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c,b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=
78 | 1:b<0&&(b=0);e>1?e=1:e<0&&(e=0);p.__color.v=b;p.__color.s=e;p.setValue(p.__color.toOriginal());return false}function s(b){b.preventDefault();var c=a.getHeight(p.__hue_field),d=a.getOffset(p.__hue_field),b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=1:b<0&&(b=0);p.__color.h=b*360;p.setValue(p.__color.toOriginal());return false}h.superclass.call(this,e,l);this.__color=new c(this.getValue());this.__temp=new c(0);var p=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement,
79 | false);this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input=
80 | document.createElement("input");this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){a.keyCode===13&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(){a.addClass(this,"drag").bind(window,"mouseup",function(){a.removeClass(p.__selector,"drag")})});var t=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"});
81 | f.extend(this.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(this.__color.v<0.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(t.style,
82 | {width:"100%",height:"100%",background:"none"});b(t,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});n(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",o);a.bind(this.__field_knob,"mousedown",o);a.bind(this.__hue_field,"mousedown",
83 | function(b){s(b);a.bind(window,"mousemove",s);a.bind(window,"mouseup",i)});this.__saturation_field.appendChild(t);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};h.superclass=e;f.extend(h.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue());
84 | if(a!==false){var e=false;f.each(c.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=true,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var h=this.__color.v<0.5||this.__color.s>0.5?255:0,j=255-h;f.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toString(),border:this.__field_knob_border+
85 | "rgb("+h+","+h+","+h+")"});this.__hue_knob.style.marginTop=(1-this.__color.h/360)*100+"px";this.__temp.s=1;this.__temp.v=1;b(this.__saturation_field,"left","#fff",this.__temp.toString());f.extend(this.__input.style,{backgroundColor:this.__input.value=this.__color.toString(),color:"rgb("+h+","+h+","+h+")",textShadow:this.__input_textShadow+"rgba("+j+","+j+","+j+",.7)"})}});var j=["-moz-","-o-","-webkit-","-ms-",""];return h}(dat.controllers.Controller,dat.dom.dom,dat.color.Color=function(e,a,c,d){function f(a,
86 | b,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="RGB")return this.__state[b];n(this,b,c);return this.__state[b]},set:function(a){if(this.__state.space!=="RGB")n(this,b,c),this.__state.space="RGB";this.__state[b]=a}})}function b(a,b){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="HSV")return this.__state[b];h(this);return this.__state[b]},set:function(a){if(this.__state.space!=="HSV")h(this),this.__state.space="HSV";this.__state[b]=a}})}function n(b,c,e){if(b.__state.space===
87 | "HEX")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space==="HSV")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw"Corrupted color state";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw"Failed to interpret color arguments";this.__state.a=this.__state.a||
88 | 1};j.COMPONENTS="r,g,b,h,s,v,hex,a".split(",");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,"r",2);f(j.prototype,"g",1);f(j.prototype,"b",0);b(j.prototype,"h");b(j.prototype,"s");b(j.prototype,"v");Object.defineProperty(j.prototype,"a",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,"hex",{get:function(){if(!this.__state.space!=="HEX")this.__state.hex=
89 | a.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space="HEX";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0};
90 | a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255<e;e++)i[e]=ig.copy(t[e]);return i}var i={};for(var e in t)i[e]=ig.copy(t[e]);return i},merge:function(t,i){for(var e in i){var s=i[e];"object"!=typeof s||s instanceof HTMLElement||s instanceof ig.Class?t[e]=s:(t[e]&&"object"==typeof t[e]||(t[e]=s instanceof Array?[]:{}),ig.merge(t[e],s))}return t},ksort:function(t){if(!t||"object"!=typeof t)return[];var i=[],e=[];for(var s in t)i.push(s);i.sort();for(var s=0;i.length>s;s++)e.push(t[i[s]]);return e},setVendorAttribute:function(t,i,e){var s=i.charAt(0).toUpperCase()+i.substr(1);t[i]=t["ms"+s]=t["moz"+s]=t["webkit"+s]=t["o"+s]=e},getVendorAttribute:function(t,i){var e=i.charAt(0).toUpperCase()+i.substr(1);return t[i]||t["ms"+e]||t["moz"+e]||t["webkit"+e]||t["o"+e]},normalizeVendorAttribute:function(t,i){var e=ig.getVendorAttribute(t,i);!t[i]&&e&&(t[i]=e)},getImagePixels:function(t,i,e,s,n){var a=ig.$new("canvas");a.width=t.width,a.height=t.height;var o=a.getContext("2d");ig.System.SCALE.CRISP(a,o);var r=ig.getVendorAttribute(o,"backingStorePixelRatio")||1;ig.normalizeVendorAttribute(o,"getImageDataHD");var h=t.width/r,l=t.height/r;return a.width=Math.ceil(h),a.height=Math.ceil(l),o.drawImage(t,0,0,h,l),1===r?o.getImageData(i,e,s,n):o.getImageDataHD(i,e,s,n)},module:function(t){if(ig._current)throw"Module '"+ig._current.name+"' defines nothing";if(ig.modules[t]&&ig.modules[t].body)throw"Module '"+t+"' is already defined";return ig._current={name:t,requires:[],loaded:!1,body:null},ig.modules[t]=ig._current,ig._loadQueue.push(ig._current),ig},requires:function(){return ig._current.requires=Array.prototype.slice.call(arguments),ig},defines:function(t){ig._current.body=t,ig._current=null,ig._initDOMReady()},addResource:function(t){ig.resources.push(t)},setNocache:function(t){ig.nocache=t?"?"+Date.now():""},log:function(){},assert:function(){},show:function(){},mark:function(){},_loadScript:function(t,i){ig.modules[t]={name:t,requires:[],loaded:!1,body:null},ig._waitForOnload++;var e=ig.prefix+ig.lib+t.replace(/\./g,"/")+".js"+ig.nocache,s=ig.$new("script");s.type="text/javascript",s.src=e,s.onload=function(){ig._waitForOnload--,ig._execModules()},s.onerror=function(){throw"Failed to load module "+t+" at "+e+" "+"required from "+i},ig.$("head")[0].appendChild(s)},_execModules:function(){for(var t=!1,i=0;ig._loadQueue.length>i;i++){for(var e=ig._loadQueue[i],s=!0,n=0;e.requires.length>n;n++){var a=e.requires[n];ig.modules[a]?ig.modules[a].loaded||(s=!1):(s=!1,ig._loadScript(a,e.name))}s&&e.body&&(ig._loadQueue.splice(i,1),e.loaded=!0,e.body(),t=!0,i--)}if(t)ig._execModules();else if(!ig.baked&&0==ig._waitForOnload&&0!=ig._loadQueue.length){for(var o=[],i=0;ig._loadQueue.length>i;i++){for(var r=[],h=ig._loadQueue[i].requires,n=0;h.length>n;n++){var e=ig.modules[h[n]];e&&e.loaded||r.push(h[n])}o.push(ig._loadQueue[i].name+" (requires: "+r.join(", ")+")")}throw"Unresolved (circular?) dependencies. Most likely there's a name/path mismatch for one of the listed modules:\n"+o.join("\n")}},_DOMReady:function(){if(!ig.modules["dom.ready"].loaded){if(!document.body)return setTimeout(ig._DOMReady,13);ig.modules["dom.ready"].loaded=!0,ig._waitForOnload--,ig._execModules()}return 0},_boot:function(){document.location.href.match(/\?nocache/)&&ig.setNocache(!0),ig.ua.pixelRatio=t.devicePixelRatio||1,ig.ua.viewport={width:t.innerWidth,height:t.innerHeight},ig.ua.screen={width:t.screen.availWidth*ig.ua.pixelRatio,height:t.screen.availHeight*ig.ua.pixelRatio},ig.ua.iPhone=/iPhone/i.test(navigator.userAgent),ig.ua.iPhone4=ig.ua.iPhone&&2==ig.ua.pixelRatio,ig.ua.iPad=/iPad/i.test(navigator.userAgent),ig.ua.android=/android/i.test(navigator.userAgent),ig.ua.winPhone=/Windows Phone/i.test(navigator.userAgent),ig.ua.iOS=ig.ua.iPhone||ig.ua.iPad,ig.ua.mobile=ig.ua.iOS||ig.ua.android||ig.ua.winPhone,ig.ua.touchDevice="ontouchstart"in t||t.navigator.msMaxTouchPoints},_initDOMReady:function(){return ig.modules["dom.ready"]?(ig._execModules(),void 0):(ig._boot(),ig.modules["dom.ready"]={requires:[],loaded:!1,body:null},ig._waitForOnload++,"complete"===document.readyState?ig._DOMReady():(document.addEventListener("DOMContentLoaded",ig._DOMReady,!1),t.addEventListener("load",ig._DOMReady,!1)),void 0)}},ig.normalizeVendorAttribute(t,"requestAnimationFrame"),t.requestAnimationFrame){var i=1,e={};t.ig.setAnimation=function(s,n){var a=i++;e[a]=!0;var o=function(){e[a]&&(t.requestAnimationFrame(o,n),s())};return t.requestAnimationFrame(o,n),a},t.ig.clearAnimation=function(t){delete e[t]}}else t.ig.setAnimation=function(i){return t.setInterval(i,1e3/60)},t.ig.clearAnimation=function(i){t.clearInterval(i)};var s=!1,n=/xyz/.test(function(){})?/\bparent\b/:/.*/;t.ig.Class=function(){};var a=function(t){var i=this.prototype,e={};for(var s in t)"function"==typeof t[s]&&"function"==typeof i[s]&&n.test(t[s])?(e[s]=i[s],i[s]=function(t,i){return function(){var s=this.parent;this.parent=e[t];var n=i.apply(this,arguments);return this.parent=s,n}}(s,t[s])):i[s]=t[s]};t.ig.Class.extend=function(i){function e(){if(!s){if(this.staticInstantiate){var t=this.staticInstantiate.apply(this,arguments);if(t)return t}for(var i in this)"object"==typeof this[i]&&(this[i]=ig.copy(this[i]));this.init&&this.init.apply(this,arguments)}return this}var o=this.prototype;s=!0;var r=new this;s=!1;for(var h in i)r[h]="function"==typeof i[h]&&"function"==typeof o[h]&&n.test(i[h])?function(t,i){return function(){var e=this.parent;this.parent=o[t];var s=i.apply(this,arguments);return this.parent=e,s}}(h,i[h]):i[h];return e.prototype=r,e.prototype.constructor=e,e.extend=t.ig.Class.extend,e.inject=a,e},t.ImpactMixin&&ig.merge(ig,t.ImpactMixin)})(window),ig.baked=!0,ig.module("impact.image").defines(function(){"use strict";ig.Image=ig.Class.extend({data:null,width:0,height:0,loaded:!1,failed:!1,loadCallback:null,path:"",staticInstantiate:function(t){return ig.Image.cache[t]||null},init:function(t){this.path=t,this.load()},load:function(t){return this.loaded?(t&&t(this.path,!0),void 0):(!this.loaded&&ig.ready?(this.loadCallback=t||null,this.data=new Image,this.data.onload=this.onload.bind(this),this.data.onerror=this.onerror.bind(this),this.data.src=ig.prefix+this.path+ig.nocache):ig.addResource(this),ig.Image.cache[this.path]=this,void 0)},reload:function(){this.loaded=!1,this.data=new Image,this.data.onload=this.onload.bind(this),this.data.src=this.path+"?"+Date.now()},onload:function(){this.width=this.data.width,this.height=this.data.height,this.loaded=!0,1!=ig.system.scale&&this.resize(ig.system.scale),this.loadCallback&&this.loadCallback(this.path,!0)},onerror:function(){this.failed=!0,this.loadCallback&&this.loadCallback(this.path,!1)},resize:function(t){var i=ig.getImagePixels(this.data,0,0,this.width,this.height),e=this.width*t,s=this.height*t,n=ig.$new("canvas");n.width=e,n.height=s;for(var a=n.getContext("2d"),o=a.getImageData(0,0,e,s),r=0;s>r;r++)for(var h=0;e>h;h++){var l=4*(Math.floor(r/t)*this.width+Math.floor(h/t)),c=4*(r*e+h);o.data[c]=i.data[l],o.data[c+1]=i.data[l+1],o.data[c+2]=i.data[l+2],o.data[c+3]=i.data[l+3]}a.putImageData(o,0,0),this.data=n},draw:function(t,i,e,s,n,a){if(this.loaded){var o=ig.system.scale;e=e?e*o:0,s=s?s*o:0,n=(n?n:this.width)*o,a=(a?a:this.height)*o,ig.system.context.drawImage(this.data,e,s,n,a,ig.system.getDrawPos(t),ig.system.getDrawPos(i),n,a),ig.Image.drawCount++}},drawTile:function(t,i,e,s,n,a,o){if(n=n?n:s,!(!this.loaded||s>this.width||n>this.height)){var r=ig.system.scale,h=Math.floor(s*r),l=Math.floor(n*r),c=a?-1:1,u=o?-1:1;(a||o)&&(ig.system.context.save(),ig.system.context.scale(c,u)),ig.system.context.drawImage(this.data,Math.floor(e*s)%this.width*r,Math.floor(e*s/this.width)*n*r,h,l,ig.system.getDrawPos(t)*c-(a?h:0),ig.system.getDrawPos(i)*u-(o?l:0),h,l),(a||o)&&ig.system.context.restore(),ig.Image.drawCount++}}}),ig.Image.drawCount=0,ig.Image.cache={},ig.Image.reloadCache=function(){for(var t in ig.Image.cache)ig.Image.cache[t].reload()}}),ig.baked=!0,ig.module("impact.font").requires("impact.image").defines(function(){"use strict";ig.Font=ig.Image.extend({widthMap:[],indices:[],firstChar:32,alpha:1,letterSpacing:1,lineSpacing:0,onload:function(t){this._loadMetrics(this.data),this.parent(t)},widthForString:function(t){if(-1!==t.indexOf("\n")){for(var i=t.split("\n"),e=0,s=0;i.length>s;s++)e=Math.max(e,this._widthForLine(i[s]));return e}return this._widthForLine(t)},_widthForLine:function(t){for(var i=0,e=0;t.length>e;e++)i+=this.widthMap[t.charCodeAt(e)-this.firstChar]+this.letterSpacing;return i},heightForString:function(t){return t.split("\n").length*(this.height+this.lineSpacing)},draw:function(t,i,e,s){if("string"!=typeof t&&(t=""+t),-1===t.indexOf("\n")){if(s==ig.Font.ALIGN.RIGHT||s==ig.Font.ALIGN.CENTER){var n=this._widthForLine(t);i-=s==ig.Font.ALIGN.CENTER?n/2:n}1!==this.alpha&&(ig.system.context.globalAlpha=this.alpha);for(var a=0;t.length>a;a++){var o=t.charCodeAt(a);i+=this._drawChar(o-this.firstChar,i,e)}1!==this.alpha&&(ig.system.context.globalAlpha=1),ig.Image.drawCount+=t.length}else for(var r=t.split("\n"),h=this.height+this.lineSpacing,a=0;r.length>a;a++)this.draw(r[a],i,e+a*h,s)},_drawChar:function(t,i,e){if(!this.loaded||0>t||t>=this.indices.length)return 0;var s=ig.system.scale,n=this.indices[t]*s,a=0,o=this.widthMap[t]*s,r=(this.height-2)*s;return ig.system.context.drawImage(this.data,n,a,o,r,ig.system.getDrawPos(i),ig.system.getDrawPos(e),o,r),this.widthMap[t]+this.letterSpacing},_loadMetrics:function(t){this.height=t.height-1,this.widthMap=[],this.indices=[];for(var i=ig.getImagePixels(t,0,t.height-1,t.width,1),e=0,s=0,n=0;t.width>n;n++){var a=4*n+3;i.data[a]>127?s++:128>i.data[a]&&s&&(this.widthMap.push(s),this.indices.push(n-s),e++,s=0)}this.widthMap.push(s),this.indices.push(n-s)}}),ig.Font.ALIGN={LEFT:0,RIGHT:1,CENTER:2}}),ig.baked=!0,ig.module("impact.sound").defines(function(){"use strict";ig.SoundManager=ig.Class.extend({clips:{},volume:1,format:null,init:function(){if(!ig.Sound.enabled||!window.Audio)return ig.Sound.enabled=!1,void 0;for(var t=new Audio,i=0;ig.Sound.use.length>i;i++){var e=ig.Sound.use[i];if(t.canPlayType(e.mime)){this.format=e;break}}this.format||(ig.Sound.enabled=!1)},load:function(t,i,e){var s=ig.prefix+t.replace(/[^\.]+$/,this.format.ext)+ig.nocache;if(this.clips[t]){if(i&&this.clips[t].lengthn;n++){var a=new Audio(s);a.load(),this.clips[t].push(a)}return this.clips[t][0]}var o=new Audio(s);if(e&&(o.addEventListener("canplaythrough",function r(i){o.removeEventListener("canplaythrough",r,!1),e(t,!0,i)},!1),o.addEventListener("error",function(i){e(t,!1,i)},!1)),o.preload="auto",o.load(),this.clips[t]=[o],i)for(var n=1;ig.Sound.channels>n;n++){var a=new Audio(s);a.load(),this.clips[t].push(a)}return o},get:function(t){for(var i,e=this.clips[t],s=0;i=e[s++];)if(i.paused||i.ended)return i.ended&&(i.currentTime=0),i;return e[0].pause(),e[0].currentTime=0,e[0]}}),ig.Music=ig.Class.extend({tracks:[],namedTracks:{},currentTrack:null,currentIndex:0,random:!1,_volume:1,_loop:!1,_fadeInterval:0,_fadeTimer:null,_endedCallbackBound:null,init:function(){this._endedCallbackBound=this._endedCallback.bind(this),Object.defineProperty?(Object.defineProperty(this,"volume",{get:this.getVolume.bind(this),set:this.setVolume.bind(this)}),Object.defineProperty(this,"loop",{get:this.getLooping.bind(this),set:this.setLooping.bind(this)})):this.__defineGetter__&&(this.__defineGetter__("volume",this.getVolume.bind(this)),this.__defineSetter__("volume",this.setVolume.bind(this)),this.__defineGetter__("loop",this.getLooping.bind(this)),this.__defineSetter__("loop",this.setLooping.bind(this)))},add:function(t,i){if(ig.Sound.enabled){var e=t instanceof ig.Sound?t.path:t,s=ig.soundManager.load(e,!1);s.loop=this._loop,s.volume=this._volume,s.addEventListener("ended",this._endedCallbackBound,!1),this.tracks.push(s),i&&(this.namedTracks[i]=s),this.currentTrack||(this.currentTrack=s)}},next:function(){this.tracks.length&&(this.stop(),this.currentIndex=this.random?Math.floor(Math.random()*this.tracks.length):(this.currentIndex+1)%this.tracks.length,this.currentTrack=this.tracks[this.currentIndex],this.play())},pause:function(){this.currentTrack&&this.currentTrack.pause()},stop:function(){this.currentTrack&&(this.currentTrack.pause(),this.currentTrack.currentTime=0)},play:function(t){if(t&&this.namedTracks[t]){var i=this.namedTracks[t];i!=this.currentTrack&&(this.stop(),this.currentTrack=i)}else if(!this.currentTrack)return;this.currentTrack.play()},getLooping:function(){return this._loop},setLooping:function(t){this._loop=t;for(var i in this.tracks)this.tracks[i].loop=t},getVolume:function(){return this._volume},setVolume:function(t){this._volume=t.limit(0,1);for(var i in this.tracks)this.tracks[i].volume=this._volume},fadeOut:function(t){this.currentTrack&&(clearInterval(this._fadeInterval),this.fadeTimer=new ig.Timer(t),this._fadeInterval=setInterval(this._fadeStep.bind(this),50))},_fadeStep:function(){var t=this.fadeTimer.delta().map(-this.fadeTimer.target,0,1,0).limit(0,1)*this._volume;.01>=t?(this.stop(),this.currentTrack.volume=this._volume,clearInterval(this._fadeInterval)):this.currentTrack.volume=t},_endedCallback:function(){this._loop?this.play():this.next()}}),ig.Sound=ig.Class.extend({path:"",volume:1,currentClip:null,multiChannel:!0,init:function(t,i){this.path=t,this.multiChannel=i!==!1,this.load()},load:function(t){return ig.Sound.enabled?(ig.ready?ig.soundManager.load(this.path,this.multiChannel,t):ig.addResource(this),void 0):(t&&t(this.path,!0),void 0)},play:function(){ig.Sound.enabled&&(this.currentClip=ig.soundManager.get(this.path),this.currentClip.volume=ig.soundManager.volume*this.volume,this.currentClip.play())},stop:function(){this.currentClip&&(this.currentClip.pause(),this.currentClip.currentTime=0)}}),ig.Sound.FORMAT={MP3:{ext:"mp3",mime:"audio/mpeg"},M4A:{ext:"m4a",mime:"audio/mp4; codecs=mp4a"},OGG:{ext:"ogg",mime:"audio/ogg; codecs=vorbis"},WEBM:{ext:"webm",mime:"audio/webm; codecs=vorbis"},CAF:{ext:"caf",mime:"audio/x-caf"}},ig.Sound.use=[ig.Sound.FORMAT.OGG,ig.Sound.FORMAT.MP3],ig.Sound.channels=4,ig.Sound.enabled=!0}),ig.baked=!0,ig.module("impact.loader").requires("impact.image","impact.font","impact.sound").defines(function(){"use strict";ig.Loader=ig.Class.extend({resources:[],gameClass:null,status:0,done:!1,_unloaded:[],_drawStatus:0,_intervalId:0,_loadCallbackBound:null,init:function(t,i){this.gameClass=t,this.resources=i,this._loadCallbackBound=this._loadCallback.bind(this);for(var e=0;this.resources.length>e;e++)this._unloaded.push(this.resources[e].path)},load:function(){if(ig.system.clear("#000"),!this.resources.length)return this.end(),void 0;for(var t=0;this.resources.length>t;t++)this.loadResource(this.resources[t]);this._intervalId=setInterval(this.draw.bind(this),16)},loadResource:function(t){t.load(this._loadCallbackBound)},end:function(){this.done||(this.done=!0,clearInterval(this._intervalId),ig.system.setGame(this.gameClass))},draw:function(){this._drawStatus+=(this.status-this._drawStatus)/5;var t=ig.system.scale,i=.6*ig.system.width,e=.1*ig.system.height,s=.5*ig.system.width-i/2,n=.5*ig.system.height-e/2;ig.system.context.fillStyle="#000",ig.system.context.fillRect(0,0,480,320),ig.system.context.fillStyle="#fff",ig.system.context.fillRect(s*t,n*t,i*t,e*t),ig.system.context.fillStyle="#000",ig.system.context.fillRect(s*t+t,n*t+t,i*t-t-t,e*t-t-t),ig.system.context.fillStyle="#fff",ig.system.context.fillRect(s*t,n*t,i*t*this._drawStatus,e*t)},_loadCallback:function(t,i){if(!i)throw"Failed to load resource: "+t;this._unloaded.erase(t),this.status=1-this._unloaded.length/this.resources.length,0==this._unloaded.length&&setTimeout(this.end.bind(this),250)}})}),ig.baked=!0,ig.module("impact.timer").defines(function(){"use strict";ig.Timer=ig.Class.extend({target:0,base:0,last:0,pausedAt:0,init:function(t){this.base=ig.Timer.time,this.last=ig.Timer.time,this.target=t||0},set:function(t){this.target=t||0,this.base=ig.Timer.time,this.pausedAt=0},reset:function(){this.base=ig.Timer.time,this.pausedAt=0},tick:function(){var t=ig.Timer.time-this.last;return this.last=ig.Timer.time,this.pausedAt?0:t},delta:function(){return(this.pausedAt||ig.Timer.time)-this.base-this.target},pause:function(){this.pausedAt||(this.pausedAt=ig.Timer.time)},unpause:function(){this.pausedAt&&(this.base+=ig.Timer.time-this.pausedAt,this.pausedAt=0)}}),ig.Timer._last=0,ig.Timer.time=Number.MIN_VALUE,ig.Timer.timeScale=1,ig.Timer.maxStep=.05,ig.Timer.step=function(){var t=Date.now(),i=(t-ig.Timer._last)/1e3;ig.Timer.time+=Math.min(i,ig.Timer.maxStep)*ig.Timer.timeScale,ig.Timer._last=t}}),ig.baked=!0,ig.module("impact.system").requires("impact.timer","impact.image").defines(function(){"use strict";ig.System=ig.Class.extend({fps:30,width:320,height:240,realWidth:320,realHeight:240,scale:1,tick:0,animationId:0,newGameClass:null,running:!1,delegate:null,clock:null,canvas:null,context:null,init:function(t,i,e,s,n){this.fps=i,this.clock=new ig.Timer,this.canvas=ig.$(t),this.resize(e,s,n),this.context=this.canvas.getContext("2d"),this.getDrawPos=ig.System.drawMode,1!=this.scale&&(ig.System.scaleMode=ig.System.SCALE.CRISP),ig.System.scaleMode(this.canvas,this.context)},resize:function(t,i,e){this.width=t,this.height=i,this.scale=e||this.scale,this.realWidth=this.width*this.scale,this.realHeight=this.height*this.scale,this.canvas.width=this.realWidth,this.canvas.height=this.realHeight},setGame:function(t){this.running?this.newGameClass=t:this.setGameNow(t)},setGameNow:function(t){ig.game=new t,ig.system.setDelegate(ig.game)},setDelegate:function(t){if("function"!=typeof t.run)throw"System.setDelegate: No run() function in object";this.delegate=t,this.startRunLoop()},stopRunLoop:function(){ig.clearAnimation(this.animationId),this.running=!1},startRunLoop:function(){this.stopRunLoop(),this.animationId=ig.setAnimation(this.run.bind(this),this.canvas),this.running=!0},clear:function(t){this.context.fillStyle=t,this.context.fillRect(0,0,this.realWidth,this.realHeight)},run:function(){ig.Timer.step(),this.tick=this.clock.tick(),this.delegate.run(),ig.input.clearPressed(),this.newGameClass&&(this.setGameNow(this.newGameClass),this.newGameClass=null)},getDrawPos:null}),ig.System.DRAW={AUTHENTIC:function(t){return Math.round(t)*this.scale},SMOOTH:function(t){return Math.round(t*this.scale)},SUBPIXEL:function(t){return t*this.scale}},ig.System.drawMode=ig.System.DRAW.SMOOTH,ig.System.SCALE={CRISP:function(t,i){ig.setVendorAttribute(i,"imageSmoothingEnabled",!1),t.style.imageRendering="-moz-crisp-edges",t.style.imageRendering="-o-crisp-edges",t.style.imageRendering="-webkit-optimize-contrast",t.style.imageRendering="crisp-edges",t.style.msInterpolationMode="nearest-neighbor"},SMOOTH:function(t,i){ig.setVendorAttribute(i,"imageSmoothingEnabled",!0),t.style.imageRendering="",t.style.msInterpolationMode=""}},ig.System.scaleMode=ig.System.SCALE.SMOOTH}),ig.baked=!0,ig.module("impact.input").defines(function(){"use strict";ig.KEY={MOUSE1:-1,MOUSE2:-3,MWHEEL_UP:-4,MWHEEL_DOWN:-5,BACKSPACE:8,TAB:9,ENTER:13,PAUSE:19,CAPS:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT_ARROW:37,UP_ARROW:38,RIGHT_ARROW:39,DOWN_ARROW:40,INSERT:45,DELETE:46,_0:48,_1:49,_2:50,_3:51,_4:52,_5:53,_6:54,_7:55,_8:56,_9:57,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,NUMPAD_0:96,NUMPAD_1:97,NUMPAD_2:98,NUMPAD_3:99,NUMPAD_4:100,NUMPAD_5:101,NUMPAD_6:102,NUMPAD_7:103,NUMPAD_8:104,NUMPAD_9:105,MULTIPLY:106,ADD:107,SUBSTRACT:109,DECIMAL:110,DIVIDE:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,SHIFT:16,CTRL:17,ALT:18,PLUS:187,COMMA:188,MINUS:189,PERIOD:190},ig.Input=ig.Class.extend({bindings:{},actions:{},presses:{},locks:{},delayedKeyup:{},isUsingMouse:!1,isUsingKeyboard:!1,isUsingAccelerometer:!1,mouse:{x:0,y:0},accel:{x:0,y:0,z:0},initMouse:function(){if(!this.isUsingMouse){this.isUsingMouse=!0;var t=this.mousewheel.bind(this);ig.system.canvas.addEventListener("mousewheel",t,!1),ig.system.canvas.addEventListener("DOMMouseScroll",t,!1),ig.system.canvas.addEventListener("contextmenu",this.contextmenu.bind(this),!1),ig.system.canvas.addEventListener("mousedown",this.keydown.bind(this),!1),ig.system.canvas.addEventListener("mouseup",this.keyup.bind(this),!1),ig.system.canvas.addEventListener("mousemove",this.mousemove.bind(this),!1),ig.ua.touchDevice&&(ig.system.canvas.addEventListener("touchstart",this.keydown.bind(this),!1),ig.system.canvas.addEventListener("touchend",this.keyup.bind(this),!1),ig.system.canvas.addEventListener("touchmove",this.mousemove.bind(this),!1),ig.system.canvas.addEventListener("MSPointerDown",this.keydown.bind(this),!1),ig.system.canvas.addEventListener("MSPointerUp",this.keyup.bind(this),!1),ig.system.canvas.addEventListener("MSPointerMove",this.mousemove.bind(this),!1),ig.system.canvas.style.msTouchAction="none")}},initKeyboard:function(){this.isUsingKeyboard||(this.isUsingKeyboard=!0,window.addEventListener("keydown",this.keydown.bind(this),!1),window.addEventListener("keyup",this.keyup.bind(this),!1))},initAccelerometer:function(){this.isUsingAccelerometer||window.addEventListener("devicemotion",this.devicemotion.bind(this),!1)},mousewheel:function(t){var i=t.wheelDelta?t.wheelDelta:-1*t.detail,e=i>0?ig.KEY.MWHEEL_UP:ig.KEY.MWHEEL_DOWN,s=this.bindings[e];s&&(this.actions[s]=!0,this.presses[s]=!0,this.delayedKeyup[s]=!0,t.stopPropagation(),t.preventDefault())},mousemove:function(t){var i=parseInt(ig.system.canvas.offsetWidth)||ig.system.realWidth,e=ig.system.scale*(i/ig.system.realWidth),s={left:0,top:0};ig.system.canvas.getBoundingClientRect&&(s=ig.system.canvas.getBoundingClientRect());var n=t.touches?t.touches[0]:t;this.mouse.x=(n.clientX-s.left)/e,this.mouse.y=(n.clientY-s.top)/e},contextmenu:function(t){this.bindings[ig.KEY.MOUSE2]&&(t.stopPropagation(),t.preventDefault())},keydown:function(t){var i=t.target.tagName;if("INPUT"!=i&&"TEXTAREA"!=i){var e="keydown"==t.type?t.keyCode:2==t.button?ig.KEY.MOUSE2:ig.KEY.MOUSE1;("touchstart"==t.type||"mousedown"==t.type)&&this.mousemove(t);var s=this.bindings[e];s&&(this.actions[s]=!0,this.locks[s]||(this.presses[s]=!0,this.locks[s]=!0),t.stopPropagation(),t.preventDefault())}},keyup:function(t){var i=t.target.tagName;if("INPUT"!=i&&"TEXTAREA"!=i){var e="keyup"==t.type?t.keyCode:2==t.button?ig.KEY.MOUSE2:ig.KEY.MOUSE1,s=this.bindings[e];s&&(this.delayedKeyup[s]=!0,t.stopPropagation(),t.preventDefault())}},devicemotion:function(t){this.accel=t.accelerationIncludingGravity},bind:function(t,i){0>t?this.initMouse():t>0&&this.initKeyboard(),this.bindings[t]=i},bindTouch:function(t,i){var e=ig.$(t),s=this;e.addEventListener("touchstart",function(t){s.touchStart(t,i)},!1),e.addEventListener("touchend",function(t){s.touchEnd(t,i)},!1),e.addEventListener("MSPointerDown",function(t){s.touchStart(t,i)},!1),e.addEventListener("MSPointerUp",function(t){s.touchEnd(t,i)},!1)},unbind:function(t){var i=this.bindings[t];this.delayedKeyup[i]=!0,this.bindings[t]=null},unbindAll:function(){this.bindings={},this.actions={},this.presses={},this.locks={},this.delayedKeyup={}},state:function(t){return this.actions[t]},pressed:function(t){return this.presses[t]},released:function(t){return this.delayedKeyup[t]},clearPressed:function(){for(var t in this.delayedKeyup)this.actions[t]=!1,this.locks[t]=!1;this.delayedKeyup={},this.presses={}},touchStart:function(t,i){return this.actions[i]=!0,this.presses[i]=!0,t.stopPropagation(),t.preventDefault(),!1},touchEnd:function(t,i){return this.delayedKeyup[i]=!0,t.stopPropagation(),t.preventDefault(),!1}})}),ig.baked=!0,ig.module("impact.impact").requires("dom.ready","impact.loader","impact.system","impact.input","impact.sound").defines(function(){"use strict";ig.main=function(t,i,e,s,n,a,o){ig.system=new ig.System(t,e,s,n,a||1),ig.input=new ig.Input,ig.soundManager=new ig.SoundManager,ig.music=new ig.Music,ig.ready=!0;var r=new(o||ig.Loader)(i,ig.resources);r.load()}}),ig.baked=!0,ig.module("plugins.fill-browser").requires("impact.system").defines(function(){ig.ua.mobile||(ig.System.keepAspectRatio=!0,ig.System.initialDebugInject=!0,ig.System.initialDebugPanelOffset=28,ig.System.fillBrowser=function(){var t=document.getElementsByTagName("canvas")[0];if(void 0!==t){var i,e,s=window.innerHeight;if(ig.Debug){var n=document.getElementsByClassName("ig_debug")[0];s-=n.clientHeight,t.style.top=-n.clientHeight+"px",ig.System.initialDebugInject&&(s=window.innerHeight-ig.System.initialDebugPanelOffset,t.style.top=-ig.System.initialDebugPanelOffset+"px",ig.Debug.inject({togglePanel:function(t){this.parent(t),ig.System.fillBrowser()}}),ig.System.canDebugInject=!1)}if(ig.System.keepAspectRatio){var a=window.innerWidth/t.width,o=s/t.height;o>a?(i=a*t.width,e=a*t.height):(i=o*t.width,e=o*t.height)}else i=window.innerWidth,e=s;t.style.width=~~i+"px",t.style.height=~~e+"px"}},ig.System.inject({init:function(t,i,e,s,n){ig.System.scaleMode=ig.System.SCALE.CRISP,this.parent(t,i,e,s,n)},resize:function(t,i,e){this.parent(t,i,e),ig.System.fillBrowser()}}),window.onresize=ig.System.fillBrowser)}),ig.baked=!0,ig.module("impact.animation").requires("impact.timer","impact.image").defines(function(){"use strict";ig.AnimationSheet=ig.Class.extend({width:8,height:8,image:null,init:function(t,i,e){this.width=i,this.height=e,this.image=new ig.Image(t)}}),ig.Animation=ig.Class.extend({sheet:null,timer:null,sequence:[],flip:{x:!1,y:!1},pivot:{x:0,y:0},frame:0,tile:0,loopCount:0,alpha:1,angle:0,init:function(t,i,e,s){this.sheet=t,this.pivot={x:t.width/2,y:t.height/2},this.timer=new ig.Timer,this.frameTime=i,this.sequence=e,this.stop=!!s,this.tile=this.sequence[0]},rewind:function(){return this.timer.set(),this.loopCount=0,this.tile=this.sequence[0],this},gotoFrame:function(t){this.timer.set(this.frameTime*-t),this.update()},gotoRandomFrame:function(){this.gotoFrame(Math.floor(Math.random()*this.sequence.length))},update:function(){var t=Math.floor(this.timer.delta()/this.frameTime);this.loopCount=Math.floor(t/this.sequence.length),this.frame=this.stop&&this.loopCount>0?this.sequence.length-1:t%this.sequence.length,this.tile=this.sequence[this.frame]},draw:function(t,i){var e=Math.max(this.sheet.width,this.sheet.height);t>ig.system.width||i>ig.system.height||0>t+e||0>i+e||(1!=this.alpha&&(ig.system.context.globalAlpha=this.alpha),0==this.angle?this.sheet.image.drawTile(t,i,this.tile,this.sheet.width,this.sheet.height,this.flip.x,this.flip.y):(ig.system.context.save(),ig.system.context.translate(ig.system.getDrawPos(t+this.pivot.x),ig.system.getDrawPos(i+this.pivot.y)),ig.system.context.rotate(this.angle),this.sheet.image.drawTile(-this.pivot.x,-this.pivot.y,this.tile,this.sheet.width,this.sheet.height,this.flip.x,this.flip.y),ig.system.context.restore()),1!=this.alpha&&(ig.system.context.globalAlpha=1))}})}),ig.baked=!0,ig.module("impact.entity").requires("impact.animation","impact.impact").defines(function(){"use strict";ig.Entity=ig.Class.extend({id:0,settings:{},size:{x:16,y:16},offset:{x:0,y:0},pos:{x:0,y:0},last:{x:0,y:0},vel:{x:0,y:0},accel:{x:0,y:0},friction:{x:0,y:0},maxVel:{x:100,y:100},zIndex:0,gravityFactor:1,standing:!1,bounciness:0,minBounceVelocity:40,anims:{},animSheet:null,currentAnim:null,health:10,type:0,checkAgainst:0,collides:0,_killed:!1,slopeStanding:{min:44..toRad(),max:136..toRad()},init:function(t,i,e){this.id=++ig.Entity._lastId,this.pos.x=t,this.pos.y=i,ig.merge(this,e)},addAnim:function(t,i,e,s){if(!this.animSheet)throw"No animSheet to add the animation "+t+" to.";var n=new ig.Animation(this.animSheet,i,e,s);return this.anims[t]=n,this.currentAnim||(this.currentAnim=n),n},update:function(){this.last.x=this.pos.x,this.last.y=this.pos.y,this.vel.y+=ig.game.gravity*ig.system.tick*this.gravityFactor,this.vel.x=this.getNewVelocity(this.vel.x,this.accel.x,this.friction.x,this.maxVel.x),this.vel.y=this.getNewVelocity(this.vel.y,this.accel.y,this.friction.y,this.maxVel.y);var t=this.vel.x*ig.system.tick,i=this.vel.y*ig.system.tick,e=ig.game.collisionMap.trace(this.pos.x,this.pos.y,t,i,this.size.x,this.size.y);this.handleMovementTrace(e),this.currentAnim&&this.currentAnim.update()},getNewVelocity:function(t,i,e,s){if(i)return(t+i*ig.system.tick).limit(-s,s);if(e){var n=e*ig.system.tick;return t-n>0?t-n:0>t+n?t+n:0}return t.limit(-s,s)},handleMovementTrace:function(t){if(this.standing=!1,t.collision.y&&(this.bounciness>0&&Math.abs(this.vel.y)>this.minBounceVelocity?this.vel.y*=-this.bounciness:(this.vel.y>0&&(this.standing=!0),this.vel.y=0)),t.collision.x&&(this.bounciness>0&&Math.abs(this.vel.x)>this.minBounceVelocity?this.vel.x*=-this.bounciness:this.vel.x=0),t.collision.slope){var i=t.collision.slope;if(this.bounciness>0){var e=this.vel.x*i.nx+this.vel.y*i.ny;this.vel.x=(this.vel.x-2*i.nx*e)*this.bounciness,this.vel.y=(this.vel.y-2*i.ny*e)*this.bounciness}else{var s=i.x*i.x+i.y*i.y,n=(this.vel.x*i.x+this.vel.y*i.y)/s;this.vel.x=i.x*n,this.vel.y=i.y*n;var a=Math.atan2(i.x,i.y);a>this.slopeStanding.min&&this.slopeStanding.max>a&&(this.standing=!0)}}this.pos=t.pos},draw:function(){this.currentAnim&&this.currentAnim.draw(this.pos.x-this.offset.x-ig.game._rscreen.x,this.pos.y-this.offset.y-ig.game._rscreen.y)},kill:function(){ig.game.removeEntity(this)},receiveDamage:function(t){this.health-=t,0>=this.health&&this.kill()},touches:function(t){return!(this.pos.x>=t.pos.x+t.size.x||this.pos.x+this.size.x<=t.pos.x||this.pos.y>=t.pos.y+t.size.y||this.pos.y+this.size.y<=t.pos.y)},distanceTo:function(t){var i=this.pos.x+this.size.x/2-(t.pos.x+t.size.x/2),e=this.pos.y+this.size.y/2-(t.pos.y+t.size.y/2);return Math.sqrt(i*i+e*e)},angleTo:function(t){return Math.atan2(t.pos.y+t.size.y/2-(this.pos.y+this.size.y/2),t.pos.x+t.size.x/2-(this.pos.x+this.size.x/2))},check:function(){},collideWith:function(){},ready:function(){}}),ig.Entity._lastId=0,ig.Entity.COLLIDES={NEVER:0,LITE:1,PASSIVE:2,ACTIVE:4,FIXED:8},ig.Entity.TYPE={NONE:0,A:1,B:2,BOTH:3},ig.Entity.checkPair=function(t,i){t.checkAgainst&i.type&&t.check(i),i.checkAgainst&t.type&&i.check(t),t.collides&&i.collides&&t.collides+i.collides>ig.Entity.COLLIDES.ACTIVE&&ig.Entity.solveCollision(t,i)},ig.Entity.solveCollision=function(t,i){var e=null;t.collides==ig.Entity.COLLIDES.LITE||i.collides==ig.Entity.COLLIDES.FIXED?e=t:(i.collides==ig.Entity.COLLIDES.LITE||t.collides==ig.Entity.COLLIDES.FIXED)&&(e=i),t.last.x+t.size.x>i.last.x&&t.last.xi.last.y&&t.last.y0)){var r=ig.game.collisionMap.trace(t.pos.x,t.pos.y,0,-(t.pos.y+t.size.y-i.pos.y),t.size.x,t.size.y);t.pos.y=r.pos.y,t.bounciness>0&&t.vel.y>t.minBounceVelocity?t.vel.y*=-t.bounciness:(t.standing=!0,t.vel.y=0)}else{var h=(t.vel.y-i.vel.y)/2;t.vel.y=-h,i.vel.y=h;var a=i.vel.x*ig.system.tick,r=ig.game.collisionMap.trace(t.pos.x,t.pos.y,a,-s/2,t.size.x,t.size.y);t.pos.y=r.pos.y;var l=ig.game.collisionMap.trace(i.pos.x,i.pos.y,0,s/2,i.size.x,i.size.y);i.pos.y=l.pos.y}}}),ig.baked=!0,ig.module("impact.map").defines(function(){"use strict";ig.Map=ig.Class.extend({tilesize:8,width:1,height:1,data:[[]],name:null,init:function(t,i){this.tilesize=t,this.data=i,this.height=i.length,this.width=i[0].length},getTile:function(t,i){var e=Math.floor(t/this.tilesize),s=Math.floor(i/this.tilesize);return e>=0&&this.width>e&&s>=0&&this.height>s?this.data[s][e]:0},setTile:function(t,i,e){var s=Math.floor(t/this.tilesize),n=Math.floor(i/this.tilesize);s>=0&&this.width>s&&n>=0&&this.height>n&&(this.data[n][s]=e)}})}),ig.baked=!0,ig.module("impact.collision-map").requires("impact.map").defines(function(){"use strict";ig.CollisionMap=ig.Map.extend({lastSlope:1,tiledef:null,init:function(t,i,e){this.parent(t,i),this.tiledef=e||ig.CollisionMap.defaultTileDef;for(var s in this.tiledef)s|0>this.lastSlope&&(this.lastSlope=0|s)},trace:function(t,i,e,s,n,a){var o={collision:{x:!1,y:!1,slope:!1},pos:{x:t,y:i},tile:{x:0,y:0}},r=Math.ceil(Math.max(Math.abs(e),Math.abs(s))/this.tilesize);if(r>1)for(var h=e/r,l=s/r,c=0;r>c&&(h||l)&&(this._traceStep(o,t,i,h,l,n,a,e,s,c),t=o.pos.x,i=o.pos.y,o.collision.x&&(h=0,e=0),o.collision.y&&(l=0,s=0),!o.collision.slope);c++);else this._traceStep(o,t,i,e,s,n,a,e,s,0);return o},_traceStep:function(t,i,e,s,n,a,o,r,h,l){t.pos.x+=s,t.pos.y+=n;var c=0;if(s){var u=s>0?a:0,d=0>s?this.tilesize:0,g=Math.max(Math.floor(e/this.tilesize),0),m=Math.min(Math.ceil((e+o)/this.tilesize),this.height),p=Math.floor((t.pos.x+u)/this.tilesize),f=Math.floor((i+u)/this.tilesize);if((l>0||p==f||0>f||f>=this.width)&&(f=-1),p>=0&&this.width>p)for(var y=g;m>y&&!(-1!=f&&(c=this.data[y][f],c>1&&this.lastSlope>=c&&this._checkTileDef(t,c,i,e,r,h,a,o,f,y)));y++)if(c=this.data[y][p],1==c||c>this.lastSlope||c>1&&this._checkTileDef(t,c,i,e,r,h,a,o,p,y)){if(c>1&&this.lastSlope>=c&&t.collision.slope)break;t.collision.x=!0,t.tile.x=c,i=t.pos.x=p*this.tilesize-u+d,r=0;break}}if(n){var v=n>0?o:0,x=0>n?this.tilesize:0,w=Math.max(Math.floor(t.pos.x/this.tilesize),0),b=Math.min(Math.ceil((t.pos.x+a)/this.tilesize),this.width),y=Math.floor((t.pos.y+v)/this.tilesize),M=Math.floor((e+v)/this.tilesize);if((l>0||y==M||0>M||M>=this.height)&&(M=-1),y>=0&&this.height>y)for(var p=w;b>p&&!(-1!=M&&(c=this.data[M][p],c>1&&this.lastSlope>=c&&this._checkTileDef(t,c,i,e,r,h,a,o,p,M)));p++)if(c=this.data[y][p],1==c||c>this.lastSlope||c>1&&this._checkTileDef(t,c,i,e,r,h,a,o,p,y)){if(c>1&&this.lastSlope>=c&&t.collision.slope)break;t.collision.y=!0,t.tile.y=c,t.pos.y=y*this.tilesize-v+x;break}}},_checkTileDef:function(t,i,e,s,n,a,o,r,h,l){var c=this.tiledef[i];if(!c)return!1;var u=(h+c[0])*this.tilesize,d=(l+c[1])*this.tilesize,g=(c[2]-c[0])*this.tilesize,m=(c[3]-c[1])*this.tilesize,p=c[4],f=e+n+(0>m?o:0)-u,y=s+a+(g>0?r:0)-d;if(g*y-m*f>0){if(0>n*-m+a*g)return p;var v=Math.sqrt(g*g+m*m),x=m/v,w=-g/v,b=f*x+y*w,M=x*b,S=w*b;return M*M+S*S>=n*n+a*a?p||.5>g*(y-a)-m*(f-n):(t.pos.x=e+n-M,t.pos.y=s+a-S,t.collision.slope={x:g,y:m,nx:x,ny:w},!0)}return!1}});var t=.5,i=1/3,e=2/3,s=!0,n=!1;ig.CollisionMap.defaultTileDef={5:[0,1,1,e,s],6:[0,e,1,i,s],7:[0,i,1,0,s],3:[0,1,1,t,s],4:[0,t,1,0,s],2:[0,1,1,0,s],10:[t,1,1,0,s],21:[0,1,t,0,s],32:[e,1,1,0,s],43:[i,1,e,0,s],54:[0,1,i,0,s],27:[0,0,1,i,s],28:[0,i,1,e,s],29:[0,e,1,1,s],25:[0,0,1,t,s],26:[0,t,1,1,s],24:[0,0,1,1,s],11:[0,0,t,1,s],22:[t,0,1,1,s],33:[0,0,i,1,s],44:[i,0,e,1,s],55:[e,0,1,1,s],16:[1,i,0,0,s],17:[1,e,0,i,s],18:[1,1,0,e,s],14:[1,t,0,0,s],15:[1,1,0,t,s],13:[1,1,0,0,s],8:[t,1,0,0,s],19:[1,1,t,0,s],30:[i,1,0,0,s],41:[e,1,i,0,s],52:[1,1,e,0,s],38:[1,e,0,1,s],39:[1,i,0,e,s],40:[1,0,0,i,s],36:[1,t,0,1,s],37:[1,0,0,t,s],35:[1,0,0,1,s],9:[1,0,t,1,s],20:[t,0,0,1,s],31:[1,0,e,1,s],42:[e,0,i,1,s],53:[i,0,0,1,s],12:[0,0,1,0,n],23:[1,1,0,1,n],34:[1,0,1,1,n],45:[0,1,0,0,n]},ig.CollisionMap.staticNoCollision={trace:function(t,i,e,s){return{collision:{x:!1,y:!1,slope:!1},pos:{x:t+e,y:i+s},tile:{x:0,y:0}}}}}),ig.baked=!0,ig.module("impact.background-map").requires("impact.map","impact.image").defines(function(){"use strict";ig.BackgroundMap=ig.Map.extend({tiles:null,scroll:{x:0,y:0},distance:1,repeat:!1,tilesetName:"",foreground:!1,enabled:!0,preRender:!1,preRenderedChunks:null,chunkSize:512,debugChunks:!1,anims:{},init:function(t,i,e){this.parent(t,i),this.setTileset(e)},setTileset:function(t){this.tilesetName=t instanceof ig.Image?t.path:t,this.tiles=new ig.Image(this.tilesetName),this.preRenderedChunks=null},setScreenPos:function(t,i){this.scroll.x=t/this.distance,this.scroll.y=i/this.distance},preRenderMapToChunks:function(){var t=this.width*this.tilesize*ig.system.scale,i=this.height*this.tilesize*ig.system.scale;this.chunkSize=Math.min(Math.max(t,i),this.chunkSize);var e=Math.ceil(t/this.chunkSize),s=Math.ceil(i/this.chunkSize);this.preRenderedChunks=[];for(var n=0;s>n;n++){this.preRenderedChunks[n]=[];for(var a=0;e>a;a++){var o=a==e-1?t-a*this.chunkSize:this.chunkSize,r=n==s-1?i-n*this.chunkSize:this.chunkSize;this.preRenderedChunks[n][a]=this.preRenderChunk(a,n,o,r)}}},preRenderChunk:function(t,i,e,s){var n=e/this.tilesize/ig.system.scale+1,a=s/this.tilesize/ig.system.scale+1,o=t*this.chunkSize/ig.system.scale%this.tilesize,r=i*this.chunkSize/ig.system.scale%this.tilesize,h=Math.floor(t*this.chunkSize/this.tilesize/ig.system.scale),l=Math.floor(i*this.chunkSize/this.tilesize/ig.system.scale),c=ig.$new("canvas");c.width=e,c.height=s;var u=ig.system.context;ig.system.context=c.getContext("2d");for(var d=0;n>d;d++)for(var g=0;a>g;g++)if(this.width>d+h&&this.height>g+l){var m=this.data[g+l][d+h];m&&this.tiles.drawTile(d*this.tilesize-o,g*this.tilesize-r,m-1,this.tilesize)}return ig.system.context=u,c},draw:function(){this.tiles.loaded&&this.enabled&&(this.preRender?this.drawPreRendered():this.drawTiled())},drawPreRendered:function(){this.preRenderedChunks||this.preRenderMapToChunks();var t=ig.system.getDrawPos(this.scroll.x),i=ig.system.getDrawPos(this.scroll.y);if(this.repeat){var e=this.width*this.tilesize*ig.system.scale;t=(t%e+e)%e;var s=this.height*this.tilesize*ig.system.scale;i=(i%s+s)%s}var n=Math.max(Math.floor(t/this.chunkSize),0),a=Math.max(Math.floor(i/this.chunkSize),0),o=Math.ceil((t+ig.system.realWidth)/this.chunkSize),r=Math.ceil((i+ig.system.realHeight)/this.chunkSize),h=this.preRenderedChunks[0].length,l=this.preRenderedChunks.length;this.repeat||(o=Math.min(o,h),r=Math.min(r,l));for(var c=0,u=a;r>u;u++){for(var d=0,g=n;o>g;g++){var m=this.preRenderedChunks[u%l][g%h],p=-t+g*this.chunkSize-d,f=-i+u*this.chunkSize-c;ig.system.context.drawImage(m,p,f),ig.Image.drawCount++,this.debugChunks&&(ig.system.context.strokeStyle="#f0f",ig.system.context.strokeRect(p,f,this.chunkSize,this.chunkSize)),this.repeat&&m.widthu;c++,u+=this.tilesize){var d=c+s;if(d>=this.height||0>d){if(!this.repeat)continue;d=(d%this.height+this.height)%this.height}for(var g=-1,m=o;h>m;g++,m+=this.tilesize){var p=g+e;if(p>=this.width||0>p){if(!this.repeat)continue;p=(p%this.width+this.width)%this.width}(t=this.data[d][p])&&((i=this.anims[t-1])?i.draw(m,u):this.tiles.drawTile(m,u,t-1,this.tilesize))}}}})}),ig.baked=!0,ig.module("impact.game").requires("impact.impact","impact.entity","impact.collision-map","impact.background-map").defines(function(){"use strict";ig.Game=ig.Class.extend({clearColor:"#000000",gravity:0,screen:{x:0,y:0},_rscreen:{x:0,y:0},entities:[],namedEntities:{},collisionMap:ig.CollisionMap.staticNoCollision,backgroundMaps:[],backgroundAnims:{},autoSort:!1,sortBy:null,cellSize:64,_deferredKill:[],_levelToLoad:null,_doSortEntities:!1,staticInstantiate:function(){return this.sortBy=this.sortBy||ig.Game.SORT.Z_INDEX,ig.game=this,null},loadLevel:function(t){this.screen={x:0,y:0},this.entities=[],this.namedEntities={};for(var i=0;t.entities.length>i;i++){var e=t.entities[i];this.spawnEntity(e.type,e.x,e.y,e.settings)}this.sortEntities(),this.collisionMap=ig.CollisionMap.staticNoCollision,this.backgroundMaps=[];for(var i=0;t.layer.length>i;i++){var s=t.layer[i];if("collision"==s.name)this.collisionMap=new ig.CollisionMap(s.tilesize,s.data);else{var n=new ig.BackgroundMap(s.tilesize,s.data,s.tilesetName);n.anims=this.backgroundAnims[s.tilesetName]||{},n.repeat=s.repeat,n.distance=s.distance,n.foreground=!!s.foreground,n.preRender=!!s.preRender,n.name=s.name,this.backgroundMaps.push(n)}}for(var i=0;this.entities.length>i;i++)this.entities[i].ready()},loadLevelDeferred:function(t){this._levelToLoad=t},getMapByName:function(t){if("collision"==t)return this.collisionMap;for(var i=0;this.backgroundMaps.length>i;i++)if(this.backgroundMaps[i].name==t)return this.backgroundMaps[i];return null},getEntityByName:function(t){return this.namedEntities[t]},getEntitiesByType:function(t){for(var i="string"==typeof t?ig.global[t]:t,e=[],s=0;this.entities.length>s;s++){var n=this.entities[s];n instanceof i&&!n._killed&&e.push(n)}return e},spawnEntity:function(t,i,e,s){var n="string"==typeof t?ig.global[t]:t;if(!n)throw"Can't spawn entity of type "+t;var a=new n(i,e,s||{});return this.entities.push(a),a.name&&(this.namedEntities[a.name]=a),a},sortEntities:function(){this.entities.sort(this.sortBy)},sortEntitiesDeferred:function(){this._doSortEntities=!0},removeEntity:function(t){t.name&&delete this.namedEntities[t.name],t._killed=!0,t.type=ig.Entity.TYPE.NONE,t.checkAgainst=ig.Entity.TYPE.NONE,t.collides=ig.Entity.COLLIDES.NEVER,this._deferredKill.push(t)},run:function(){this.update(),this.draw()},update:function(){this._levelToLoad&&(this.loadLevel(this._levelToLoad),this._levelToLoad=null),(this._doSortEntities||this.autoSort)&&(this.sortEntities(),this._doSortEntities=!1),this.updateEntities(),this.checkEntities();for(var t=0;this._deferredKill.length>t;t++)this.entities.erase(this._deferredKill[t]);this._deferredKill=[];for(var i in this.backgroundAnims){var e=this.backgroundAnims[i];for(var s in e)e[s].update()}},updateEntities:function(){for(var t=0;this.entities.length>t;t++){var i=this.entities[t];i._killed||i.update()}},draw:function(){this.clearColor&&ig.system.clear(this.clearColor),this._rscreen.x=ig.system.getDrawPos(this.screen.x)/ig.system.scale,this._rscreen.y=ig.system.getDrawPos(this.screen.y)/ig.system.scale;var t;for(t=0;this.backgroundMaps.length>t;t++){var i=this.backgroundMaps[t];if(i.foreground)break;i.setScreenPos(this.screen.x,this.screen.y),i.draw()}for(this.drawEntities(),t;this.backgroundMaps.length>t;t++){var i=this.backgroundMaps[t];i.setScreenPos(this.screen.x,this.screen.y),i.draw()}},drawEntities:function(){for(var t=0;this.entities.length>t;t++)this.entities[t].draw()},checkEntities:function(){for(var t={},i=0;this.entities.length>i;i++){var e=this.entities[i];if(e.type!=ig.Entity.TYPE.NONE||e.checkAgainst!=ig.Entity.TYPE.NONE||e.collides!=ig.Entity.COLLIDES.NEVER)for(var s={},n=Math.floor(e.pos.x/this.cellSize),a=Math.floor(e.pos.y/this.cellSize),o=Math.floor((e.pos.x+e.size.x)/this.cellSize)+1,r=Math.floor((e.pos.y+e.size.y)/this.cellSize)+1,h=n;o>h;h++)for(var l=a;r>l;l++)if(t[h])if(t[h][l]){for(var c=t[h][l],u=0;c.length>u;u++)e.touches(c[u])&&!s[c[u].id]&&(s[c[u].id]=!0,ig.Entity.checkPair(e,c[u]));c.push(e)}else t[h][l]=[e];else t[h]={},t[h][l]=[e]}}}),ig.Game.SORT={Z_INDEX:function(t,i){return t.zIndex-i.zIndex},POS_X:function(t,i){return t.pos.x+t.size.x-(i.pos.x+i.size.x)},POS_Y:function(t,i){return t.pos.y+t.size.y-(i.pos.y+i.size.y)}}}),ig.baked=!0,ig.module("game.entities.particle").requires("impact.entity").defines(function(){EntityParticle=ig.Entity.extend({animSheet:new ig.AnimationSheet("media/particle.png",13,13),vel:{x:200,y:200},init:function(t,i,e){this.parent(t,i,e),this.addAnim("idle",1,[0]),this.vel.x=this.vel.x*Math.random()-this.vel.x/2,this.vel.y=this.vel.y*Math.random()-this.vel.y/2},update:function(){this.parent(),(0>this.pos.x||this.pos.x+this.size.x>ig.system.width)&&(this.vel.x=-this.vel.x),(0>this.pos.y||this.pos.y+this.size.y>ig.system.height)&&(this.vel.y=-this.vel.y)}})}),ig.baked=!0,ig.module("game.particles").requires("impact.game","game.entities.particle").defines(function(){ParticleTest=ig.Game.extend({clearColor:"#FFFFFF",fps:null,gui:null,TOTAL_PARTICLES:200,init:function(){this.fps=new FPSMeter(document.body,{theme:"dark",heat:1,graph:1}),this.gui=new dat.GUI,this.gui.add(this,"TOTAL_PARTICLES",0,15e3),this.spawnParticles(this.TOTAL_PARTICLES)},checkParticleCount:function(t){t>this.entities.length?this.spawnParticles(t-this.entities.length):this.entities.length>t&&(this.entities.length=t)},spawnParticles:function(t){for(var i=EntityParticle.prototype.size.x,e=EntityParticle.prototype.size.y,s=0;t>s;s++)this.spawnEntity(EntityParticle,Math.random()*(ig.system.width-i),Math.random()*(ig.system.height-e))},update:function(){this.checkParticleCount(~~this.TOTAL_PARTICLES),this.parent(),this.fps.tick()}})}),ig.baked=!0,ig.module("game.entities.particle-fast").requires("impact.entity").defines(function(){EntityParticleFast=function(t,i){this.pos={x:t,y:i},this.vel={x:this.vel.x*Math.random()-this.vel.x/2,y:this.vel.y*Math.random()-this.vel.y/2}},EntityParticleFast.prototype={image:new ig.Image("media/particle.png",13,13),size:{x:13,y:13},vel:{x:200,y:200},draw:function(){ig.system.context.drawImage(this.image.data,~~this.pos.x,~~this.pos.y)},update:function(){this.pos.x+=this.vel.x*ig.system.tick,this.pos.y+=this.vel.y*ig.system.tick,(0>this.pos.x||this.pos.x+this.size.x>ig.system.width)&&(this.vel.x=-this.vel.x),(0>this.pos.y||this.pos.y+this.size.y>ig.system.height)&&(this.vel.y=-this.vel.y)}}}),ig.baked=!0,ig.module("game.particles-fast").requires("impact.game","game.entities.particle-fast").defines(function(){ParticleTestFast=ig.Game.extend({fps:null,gui:null,TOTAL_PARTICLES:500,init:function(){this.fpsDiv=document.getElementById("fps"),this.fps=new FPSMeter(document.body,{theme:"dark",heat:1,graph:1}),this.gui=new dat.GUI,this.gui.add(this,"TOTAL_PARTICLES",0,2e4),this.spawnParticles(this.TOTAL_PARTICLES)},checkParticleCount:function(t){t>this.entities.length?this.spawnParticles(t-this.entities.length):this.entities.length>t&&(this.entities.length=t)},spawnParticles:function(t){for(var i=EntityParticleFast.prototype.size.x,e=EntityParticleFast.prototype.size.y,s=0;t>s;s++)this.entities.push(new EntityParticleFast(Math.random()*(ig.system.width-i),Math.random()*(ig.system.height-e)))},run:function(){this.checkParticleCount(~~this.TOTAL_PARTICLES),ig.system.context.fillStyle="#FFFFFF",ig.system.context.fillRect(0,0,ig.system.realWidth,ig.system.realHeight);for(var t=0,i=this.entities.length;i>t;t++){var e=this.entities[t];e.update(),e.draw()}this.fps.tick()}})}),ig.baked=!0,ig.module("game.main").requires("plugins.fill-browser","game.particles","game.particles-fast").defines(function(){"use strict"});
--------------------------------------------------------------------------------