├── .DS_Store ├── .project ├── README.md ├── css ├── .DS_Store ├── img │ ├── circles.png │ └── cubes.jpg └── jamboree.css ├── jamboree.html └── js ├── .DS_Store ├── app.js ├── commonUtils ├── .DS_Store ├── commonUtils.js ├── kcolor.js ├── map.js ├── range.js ├── rect.js ├── time.js ├── timespan.js ├── transform.js ├── tree.js ├── ui.js ├── utilities.js └── vector.js ├── jamboreeUI.js ├── libs ├── dancer.js ├── inheritance.js ├── jquery-1.10.1.js ├── jquery-1.10.2.min.js ├── jquery-1.6.2.js ├── jquery-migrate-1.2.1.js ├── jquery-ui.js ├── jquery.mousewheel.min.js ├── jsxTransformer.js ├── poly2tri.js ├── processing-1.4.1.js ├── react.js ├── require.js ├── simplex_noise.js ├── three.js └── underscore.js ├── main.js ├── settings.js └── tutorials ├── boids.js ├── flowers.js ├── gameOfLife.js ├── lTrees.js ├── terrain.js └── tutorials.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxykate/PCGTutorials/92a51d3769259dfaee0dfa695830f897915c011a/.DS_Store -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Jamboree 4 | 5 | 6 | 7 | 8 | 9 | com.aptana.ide.core.unifiedBuilder 10 | 11 | 12 | 13 | 14 | 15 | com.aptana.projects.webnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PCGTutorials 2 | ============ 3 | 4 | PCGTutorials 5 | A set of procedural generation tutorials by GalaxyKate 6 | -------------------------------------------------------------------------------- /css/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxykate/PCGTutorials/92a51d3769259dfaee0dfa695830f897915c011a/css/.DS_Store -------------------------------------------------------------------------------- /css/img/circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxykate/PCGTutorials/92a51d3769259dfaee0dfa695830f897915c011a/css/img/circles.png -------------------------------------------------------------------------------- /css/img/cubes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxykate/PCGTutorials/92a51d3769259dfaee0dfa695830f897915c011a/css/img/cubes.jpg -------------------------------------------------------------------------------- /css/jamboree.css: -------------------------------------------------------------------------------- 1 | .noSelect { 2 | -webkit-user-select:none; 3 | -khtml-user-select:none; 4 | -moz-user-select:none; 5 | -o-user-select:none; 6 | outline:none; 7 | user-select:none; 8 | } 9 | body { 10 | background-image:url('img/circles.png'); 11 | /*background-image: url('img/carved2.jpeg');*/ 12 | background-repeat:repeat; 13 | font-family:"Trebuchet MS",Helvetica,sans-serif; 14 | } 15 | #app { 16 | position:relative; 17 | box-shadow:0px 0px 20px 3px rgba(255, 205, 255, .4); 18 | margin:10px auto; 19 | border-radius:30px; 20 | /*border:5px solid rgba(255, 255, 255, .4);*/ 21 | } 22 | .appSize { 23 | width:800px; 24 | height:480px; 25 | overflow:show; 26 | } 27 | #processingHolder { 28 | border-radius:30px; 29 | overflow:hidden; 30 | } 31 | #viewProcessing { 32 | border-radius:30px; 33 | width:100%; 34 | height:100%; 35 | } 36 | #controlBar { 37 | position:relative; 38 | top:-30px; 39 | width:600px; 40 | height:40px; 41 | background-color:rgba(20, 20, 20, .9); 42 | box-shadow:0px 2px 10px rgba(255, 144, 255, .4); 43 | margin:10px auto; 44 | border-radius:30px; 45 | } 46 | #controlBar button { 47 | font-size:17px; 48 | position:absolute; 49 | top:5px; 50 | background-color:rgba(20, 20, 20, .9); 51 | box-shadow:0px 2px 3px rgba(255, 144, 255, .4); 52 | border-radius:30px; 53 | color:white; 54 | width:30px; 55 | height:30px; 56 | } 57 | #backButton { 58 | left:10px; 59 | } 60 | #forwardButton { 61 | right:10px; 62 | } 63 | #title { 64 | position:relative; 65 | width:180px; 66 | margin:0 auto; 67 | text-align:center; 68 | font-size:17px; 69 | top:5px; 70 | color:white; 71 | } 72 | -------------------------------------------------------------------------------- /jamboree.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Verba docent, exempla trahunt 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 | 21 | 25 | 28 |
29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /js/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxykate/PCGTutorials/92a51d3769259dfaee0dfa695830f897915c011a/js/.DS_Store -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | var app = {}; 6 | 7 | define(["./jamboreeUI", "./settings", "./tutorials/tutorials"], function(UI, _settings, tutorials) {'use strict'; 8 | 9 | // Active tutorials 10 | var tutorialNames = ["GameOfLife", "Flowers", "LTrees", "Terrain", "Boids"]; 11 | // Starting 12 | var tutorialIndex = null; 13 | 14 | app.init = function() { 15 | console.log("Init Jamboree App"); 16 | app.time = { 17 | total : 0, 18 | framecount : 0, 19 | elapsed : .1, 20 | }; 21 | 22 | app.elapsed = .001; 23 | app.ui = UI; 24 | app.ui.init(); 25 | 26 | var appContainer = $("#app"); 27 | app.w = appContainer.width(); 28 | app.h = appContainer.height(); 29 | 30 | app.startTime = new Date().getTime(); 31 | 32 | var startIndex = localStorage.getItem("lastTutorial"); 33 | if (startIndex === null) 34 | startIndex = 0; 35 | 36 | app.loadTutorial(startIndex); 37 | 38 | }; 39 | 40 | app.loadTutorial = function(index) { 41 | console.log("Load " + index); 42 | tutorialIndex = index; 43 | var type = tutorialNames[index]; 44 | app.tutorial = new tutorials[type](); 45 | $("#title").html(app.tutorial.title); 46 | 47 | localStorage.setItem("lastTutorial", index); 48 | 49 | }; 50 | 51 | app.nextTutorial = function() { 52 | tutorialIndex = (tutorialIndex + 1) % tutorialNames.length; 53 | app.loadTutorial(tutorialIndex); 54 | }; 55 | 56 | app.previousTutorial = function() { 57 | tutorialIndex = (tutorialNames.length + tutorialIndex - 1) % tutorialNames.length; 58 | app.loadTutorial(tutorialIndex); 59 | }; 60 | 61 | app.setTime = function() { 62 | app.time.framecount++; 63 | 64 | var last = app.time.total; 65 | app.time.total = (new Date().getTime() - app.startTime) * .001; 66 | app.time.elapsed = app.time.total - last; 67 | 68 | }; 69 | 70 | app.update = function() { 71 | app.setTime(); 72 | app.ui.update(app.time); 73 | 74 | }; 75 | }); 76 | -------------------------------------------------------------------------------- /js/commonUtils/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/galaxykate/PCGTutorials/92a51d3769259dfaee0dfa695830f897915c011a/js/commonUtils/.DS_Store -------------------------------------------------------------------------------- /js/commonUtils/commonUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | var utilities = {}; 6 | var prefix = "commonUtils/"; 7 | define(["inheritance", "noise", prefix + "transform", prefix + "vector", prefix + "rect", prefix + "kcolor", prefix + "utilities", prefix + "ui", "jQueryUI", "underscore"], function(Inheritance, _Noise, _Transform, _Vector, _Rect, _KColor, _utilities, uiUtils, JQUERY, _) { 8 | var common = { 9 | Vector : _Vector, 10 | KColor : _KColor, 11 | Rect : _Rect, 12 | 13 | Transform : _Transform, 14 | 15 | }; 16 | console.log(uiUtils); 17 | $.extend(utilities, _utilities); 18 | $.extend(utilities, common); 19 | $.extend(utilities, uiUtils); 20 | //============================================================= 21 | //============================================================= 22 | //============================================================= 23 | // Add watching 24 | /* 25 | * object.watch polyfill 26 | * 27 | * 2012-04-03 28 | * 29 | * By Eli Grey, http://eligrey.com 30 | * Public Domain. 31 | * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 32 | */ 33 | 34 | // object.watch 35 | if (!Object.prototype.watch) { 36 | Object.defineProperty(Object.prototype, "watch", { 37 | enumerable : false, 38 | configurable : true, 39 | writable : false, 40 | value : function(prop, handler) { 41 | var oldval = this[prop], newval = oldval, getter = function() { 42 | return newval; 43 | }, setter = function(val) { 44 | oldval = newval; 45 | return newval = handler.call(this, prop, oldval, val); 46 | }; 47 | 48 | if ( 49 | delete this[prop]) {// can't watch constants 50 | Object.defineProperty(this, prop, { 51 | get : getter, 52 | set : setter, 53 | enumerable : true, 54 | configurable : true 55 | }); 56 | } 57 | } 58 | }); 59 | } 60 | 61 | // object.unwatch 62 | if (!Object.prototype.unwatch) { 63 | Object.defineProperty(Object.prototype, "unwatch", { 64 | enumerable : false, 65 | configurable : true, 66 | writable : false, 67 | value : function(prop) { 68 | var val = this[prop]; 69 | delete this[prop]; 70 | // remove accessors 71 | this[prop] = val; 72 | } 73 | }); 74 | } 75 | 76 | //============================================================= 77 | //============================================================= 78 | //============================================================= 79 | 80 | utilities.noiseObj = new _Noise(); 81 | utilities.noise = function() { 82 | // use the correct number of args 83 | switch(arguments.length) { 84 | case 1: 85 | return utilities.noiseObj.noise2D(arguments[0], 1000); 86 | break; 87 | case 2: 88 | return utilities.noiseObj.noise2D(arguments[0], arguments[1]); 89 | break; 90 | case 3: 91 | return utilities.noiseObj.noise3D(arguments[0], arguments[1], arguments[2]); 92 | break; 93 | case 4: 94 | return utilities.noiseObj.noise4D(arguments[0], arguments[1], arguments[2], arguments[3]); 95 | break; 96 | default: 97 | console.log("Attempting to use Noise with " + arguments.length + " arguments: not supported!"); 98 | return 0; 99 | break; 100 | } 101 | }; 102 | 103 | // renormalized to between [0, 1] 104 | utilities.unitNoise = function() { 105 | return utilities.noise.apply(undefined, arguments) * .5 + .5; 106 | }; 107 | 108 | //================================================== 109 | return utilities; 110 | }); 111 | -------------------------------------------------------------------------------- /js/commonUtils/kcolor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | // Color utility class 6 | // Create KColors (stored as HSBA [0, 1], so that (.45, .3, 1, .5) would be a half-transparent sky-blue) 7 | 8 | define([], function() { 9 | 10 | function toRGB(h, s, v) { 11 | var r, g, b; 12 | h *= 6; 13 | h = h % 6; 14 | 15 | var i = Math.floor(h); 16 | var f = h - i; 17 | var p = v * (1 - s); 18 | var q = v * (1 - (s * f)); 19 | var t = v * (1 - (s * (1 - f))); 20 | if (i == 0) { 21 | r = v; 22 | g = t; 23 | b = p; 24 | } else if (i == 1) { 25 | r = q; 26 | g = v; 27 | b = p; 28 | } else if (i == 2) { 29 | r = p; 30 | g = v; 31 | b = t; 32 | } else if (i == 3) { 33 | r = p; 34 | g = q; 35 | b = v; 36 | } else if (i == 4) { 37 | r = t; 38 | g = p; 39 | b = v; 40 | } else if (i == 5) { 41 | r = v; 42 | g = p; 43 | b = q; 44 | } 45 | r = Math.floor(r * 255); 46 | g = Math.floor(g * 255); 47 | b = Math.floor(b * 255); 48 | return [r, g, b]; 49 | }; 50 | 51 | return (function() { 52 | 53 | // Private functions 54 | 55 | // Make the Vector class 56 | function KColor(h, s, b, a) { 57 | this.h = h; 58 | this.s = s; 59 | this.b = b; 60 | if (a !== undefined) 61 | this.a = a; 62 | else 63 | this.a = 1; 64 | }; 65 | 66 | // Add lots of utilty, modification, lerping, etc functions to deal with colors 67 | 68 | KColor.prototype.toString = function() { 69 | return "hsb: " + this.h.toFixed(2) + " " + this.s.toFixed(2) + " " + this.b.toFixed(2) + " " + this.a.toFixed(2); 70 | 71 | }; 72 | 73 | KColor.prototype.clone = function() { 74 | return new KColor(this.h, this.s, this.b, this.a); 75 | }; 76 | 77 | KColor.prototype.constrainToUnit = function(v) { 78 | return Math.min(Math.max(v, 0), 1); 79 | }; 80 | 81 | KColor.prototype.cloneShade = function(shade, fade) { 82 | var clone; 83 | 84 | this.use(function(h, s, b, a) { 85 | clone = new KColor(h, s, b, a); 86 | }, shade, fade); 87 | 88 | return clone; 89 | }; 90 | 91 | KColor.prototype.creatMutant = function() { 92 | var clone; 93 | 94 | var hMutation = .2 * (Math.random() - .5); 95 | var sMutation = .2 * (Math.random() - .5); 96 | var bMutation = .2 * (Math.random() - .5); 97 | 98 | return new KColor(this.h + hMutation, this.s + sMutation, this.b + bMutation, this.a); 99 | 100 | }; 101 | 102 | // shade goes from -1 to 1, as does fade. 103 | KColor.prototype.fill = function(g, shade, fade) { 104 | return this.use(g.fill, shade, fade); 105 | }; 106 | 107 | KColor.prototype.stroke = function(g, shade, fade) { 108 | return this.use(g.stroke, shade, fade); 109 | }; 110 | 111 | KColor.prototype.background = function(g, shade, fade) { 112 | return this.use(g.background, shade, fade); 113 | }; 114 | 115 | KColor.prototype.use = function(gFunc, shade, fade) { 116 | 117 | var s1 = this.s; 118 | var h1 = this.h; 119 | var b1 = this.b; 120 | var a1 = this.a; 121 | 122 | if (shade !== undefined) { 123 | if (shade > 0) { 124 | s1 = this.constrainToUnit(s1 - shade * (s1)); 125 | b1 = this.constrainToUnit(b1 + shade * (1 - b1)); 126 | } else { 127 | s1 = this.constrainToUnit(s1 - shade * (1 - s1)); 128 | b1 = this.constrainToUnit(b1 + shade * (b1)); 129 | } 130 | 131 | h1 = (h1 + -.06 * shade + 1) % 1; 132 | } 133 | 134 | // Increase (or decrease) the alpha for this 135 | if (fade !== undefined) { 136 | if (fade < 0) { 137 | a1 = this.constrainToUnit(a1 * (1 + fade)); 138 | } else { 139 | a1 = this.constrainToUnit((1 - a1) * fade + a1); 140 | } 141 | } 142 | 143 | gFunc(h1, s1, b1, a1); 144 | }; 145 | 146 | //================================================================= 147 | //================================================================= 148 | //================================================================= 149 | 150 | KColor.prototype.toCSS = function(shade, fade) { 151 | 152 | if (shade !== undefined) { 153 | var css; 154 | this.use(function(h, s, b, a) { 155 | var rgb = toRGB(h, s, b, a); 156 | var vals = ""; 157 | $.each(rgb, function(index, val) { 158 | vals += Math.round(val) + ", "; 159 | }); 160 | vals += a; 161 | css = "rgba(" + vals + ")"; 162 | }, shade, fade); 163 | 164 | return css; 165 | } 166 | 167 | var rgb = toRGB(this.h, this.s, this.b, this.a); 168 | var vals = ""; 169 | $.each(rgb, function(index, val) { 170 | vals += Math.round(val) + ", "; 171 | }); 172 | vals += this.a; 173 | return "rgba(" + vals + ")"; 174 | }; 175 | 176 | // From the internet 177 | KColor.prototype.toRGB = function() { 178 | return toRGB(this.h, this.s, this.b, this.a); 179 | }; 180 | 181 | var toHexString = function(v) { 182 | var v2 = v.toString(16); 183 | if (v2.length == 0) 184 | v2 = "0" + v2; 185 | if (v2.length == 1) 186 | v2 = "0" + v2; 187 | return v2; 188 | }; 189 | 190 | KColor.prototype.toHex = function() { 191 | var rgb = this.toRGB(); 192 | 193 | var hex = rgb[0] << 16 | rgb[1] << 8 | rgb[2]; 194 | hex = toHexString(rgb[0]) + toHexString(rgb[1]) + toHexString(rgb[2]); 195 | return hex; 196 | }; 197 | 198 | KColor.makeIDColor = function(idNumber) { 199 | return new KColor((idNumber * .31299 + .42) % 1, 1, 1); 200 | }; 201 | 202 | //================================================================= 203 | //================================================================= 204 | //================================================================= 205 | 206 | return KColor; 207 | })(); 208 | 209 | }); 210 | -------------------------------------------------------------------------------- /js/commonUtils/map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | // Reusable Vector class 6 | 7 | define(["./vector"], function(Vector) { 8 | var Map = Class.extend({ 9 | init : function() { 10 | this.values = []; 11 | }, 12 | 13 | setDimensions : function(width, height, spacing) { 14 | this.columns = Math.round(width / spacing); 15 | this.rows = Math.round(height / spacing); 16 | this.xSpacing = width / this.columns; 17 | this.ySpacing = height / this.rows; 18 | 19 | for (var i = 0; i < this.columns; i++) { 20 | this.values[i] = []; 21 | for (var j = 0; j < this.rows; j++) { 22 | this.values[i][j] = .5 * (j / this.rows) + .5 * Math.random(); 23 | } 24 | } 25 | }, 26 | 27 | setFill : function(g, value) { 28 | g.fill((value * 1.5) % 1, .3 + .7 * value, 1 - value); 29 | }, 30 | 31 | sampleAt : function(p) { 32 | var x = p.x / this.xSpacing; 33 | var y = p.y / this.ySpacing; 34 | var column = Math.floor(x); 35 | var row = Math.floor(y); 36 | column = utilities.constrain(column, 0, this.columns - 1); 37 | row = utilities.constrain(row, 0, this.rows - 1); 38 | return this.values[column][row]; 39 | }, 40 | 41 | draw : function(g, t) { 42 | if (app.options.debugDrawLightmap) { 43 | for (var i = 0; i < this.columns; i++) { 44 | for (var j = 0; j < this.rows; j++) { 45 | var v = this.values[i][j]; 46 | this.setFill(g, v); 47 | g.rect(i * this.xSpacing, j * this.ySpacing, this.xSpacing, this.ySpacing); 48 | } 49 | } 50 | } 51 | } 52 | }) 53 | return Map; 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /js/commonUtils/range.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | define(["inheritance"], function(Inheritance) { 5 | var Range = Class.extend({ 6 | init : function(context) { 7 | 8 | // default values 9 | this.min = 0; 10 | this.max = 1; 11 | this.defaultValue = .5; 12 | 13 | // Translate all the context into this 14 | $.extend(this, context); 15 | this.value = this.defaultValue; 16 | }, 17 | 18 | setToMax : function() { 19 | this.setTo(this.max); 20 | }, 21 | 22 | setToMin : function() { 23 | this.setTo(this.min); 24 | }, 25 | 26 | setToPct : function(pct) { 27 | this.setTo((this.max - this.min) * pct + this.min); 28 | }, 29 | 30 | add : function(val) { 31 | this.setTo(val + this.value); 32 | }, 33 | 34 | setTo : function(val) { 35 | this.value = Math.min(this.max, Math.max(this.min, val)); 36 | }, 37 | 38 | getValue : function() { 39 | return this.value; 40 | }, 41 | 42 | getPct : function(v) { 43 | return (v - this.min) / (this.max - this.min); 44 | }, 45 | 46 | toString : function() { 47 | return "[" + this.min.toFixed(2) + "-" + this.max.toFixed(2) + "]"; 48 | }, 49 | }); 50 | return Range; 51 | }); 52 | -------------------------------------------------------------------------------- /js/commonUtils/rect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | // Reusable Vector class 6 | 7 | define(["./vector"], function(Vector) { 8 | var Rect = Class.extend({ 9 | 10 | // use as init(x, y, w, h) or init(position:Vector, dimensions:Vector) 11 | init : function() { 12 | if (arguments.length == 4) { 13 | this.x = arguments[0]; 14 | this.y = arguments[1]; 15 | this.w = arguments[2]; 16 | this.h = arguments[3]; 17 | 18 | } else if (arguments.length === 2) { 19 | this.x = arguments[0].x; 20 | this.y = arguments[0].y; 21 | this.w = arguments[1].x; 22 | this.h = arguments[1].y; 23 | } else { 24 | this.w = 0; 25 | this.h = 0; 26 | } 27 | 28 | }, 29 | 30 | clone : function() { 31 | return new Rect(this.x, this.y, this.w, this.h); 32 | }, 33 | 34 | setPosition : function(p) { 35 | if (arguments.length == 2) { 36 | this.x = arguments[0]; 37 | this.y = arguments[1]; 38 | } else { 39 | this.x = p.x; 40 | this.y = p.y; 41 | } 42 | }, 43 | 44 | setDimensions : function(p) { 45 | if (arguments.length == 2) { 46 | this.w = arguments[0]; 47 | this.h = arguments[1]; 48 | } else { 49 | this.w = p.x; 50 | this.h = p.y; 51 | } 52 | }, 53 | 54 | // return the Vectors of the corners 55 | getCorners : function(ccw) { 56 | var x0 = this.x + this.w; 57 | var x1 = this.x; 58 | var y0 = this.y; 59 | var y1 = this.y + this.h; 60 | 61 | if (ccw) 62 | return [new Vector(x0, y0), new Vector(x1, y0), new Vector(x1, y1), new Vector(x0, y1)]; 63 | return [new Vector(x0, y0), new Vector(x0, y1), new Vector(x1, y1), new Vector(x1, y0)]; 64 | }, 65 | 66 | reset : function() { 67 | this.x = undefined; 68 | this.y = undefined; 69 | this.w = 0; 70 | this.h = 0; 71 | }, 72 | 73 | stretchToContainBox : function(b) { 74 | var box = this; 75 | var c = b.getCorners(); 76 | $.each(c, function(index, corner) { 77 | box.stretchToContainPoint(corner); 78 | }); 79 | }, 80 | 81 | stretchToContainPoint : function(pt) { 82 | if (this.x === undefined) 83 | this.x = pt.x; 84 | if (this.y === undefined) 85 | this.y = pt.y; 86 | 87 | if (pt.x < this.x) { 88 | this.w += this.x - pt.x; 89 | this.x = pt.x; 90 | } 91 | if (pt.y < this.y) { 92 | this.h += this.y - pt.y; 93 | this.y = pt.y; 94 | } 95 | 96 | this.w = Math.max(this.w, pt.x - this.x); 97 | this.h = Math.max(this.h, pt.y - this.y); 98 | 99 | }, 100 | 101 | stretchToContainPoints : function(pts) { 102 | for (var i = 0; i < pts.length; i++) { 103 | this.stretchToContainPoint(pts[i]); 104 | } 105 | }, 106 | 107 | getRandomPosition : function(border) { 108 | var x = this.x + border + Math.random() * (this.w - border * 2); 109 | var y = this.y + border + Math.random() * (this.h - border * 2); 110 | 111 | return new Vector(x, y); 112 | }, 113 | 114 | getSidePosition : function(side, sidePos, outset) { 115 | var x = sidePos; 116 | 117 | if (side === "left") { 118 | x = outset; 119 | } 120 | if (side === "right") { 121 | x = this.w - outset; 122 | } 123 | 124 | var y = sidePos; 125 | 126 | if (side === "top") { 127 | y = outset; 128 | } 129 | if (side === "bottom") { 130 | y = this.h - outset; 131 | } 132 | 133 | var p = new Vector(x + this.x, y + this.y); 134 | return p; 135 | }, 136 | 137 | centerTransform : function(g) { 138 | g.translate(-this.x + -this.w / 2, -this.y + -this.h / 2); 139 | }, 140 | 141 | getCenter : function() { 142 | return new Vector(this.x + this.w / 2, this.y + this.h / 2); 143 | }, 144 | 145 | draw : function(g) { 146 | g.rect(this.x, this.y, this.w, this.h); 147 | }, 148 | 149 | toCSS : function() { 150 | return { 151 | width : this.w + "px", 152 | height : this.h + "px", 153 | top : this.y + "px", 154 | left : this.x + "px", 155 | 156 | }; 157 | }, 158 | toString : function() { 159 | return "[(" + this.x.toFixed(2) + "," + this.y.toFixed(2) + "), " + this.w.toFixed(2) + "x" + this.h.toFixed(2) + "]"; 160 | } 161 | }); 162 | 163 | return Rect; 164 | 165 | }); 166 | -------------------------------------------------------------------------------- /js/commonUtils/time.js: -------------------------------------------------------------------------------- 1 | define(["inheritance", "./timespan"], function(Inheritance, TimeSpan) { 2 | var Time = Class.extend({ 3 | init : function(name) { 4 | this.name = name; 5 | this.ellapsed = 0; 6 | this.frameCount = 0; 7 | this.total = 0; 8 | this.timespans = new TimeSpan.Manager(); 9 | 10 | }, 11 | 12 | addTimeSpan : function(timespan) { 13 | this.timespans.add(timespan); 14 | }, 15 | 16 | addEllapsed : function(t) { 17 | this.ellapsed = t; 18 | this.total += t; 19 | }, 20 | 21 | updateTime : function(t) { 22 | if (isNaN(t)) { 23 | throw ("Update time " + this.name + " with bad total value " + t); 24 | } 25 | 26 | this.ellapsed = t - this.total; 27 | 28 | if (isNaN(this.ellapsed) || this.ellapsed < .001 || this.ellapsed > 1) { 29 | // throw ("Update time " + this.name + " with bad ellapsed value " + this.ellapsed); 30 | 31 | } 32 | if (this.ellapsed < .01) 33 | this.ellapsed = .01; 34 | if (this.ellapsed > .5) 35 | this.ellapsed = .5; 36 | if (isNaN(this.ellapsed)) 37 | this.ellapsed = .05; 38 | 39 | this.total = t; 40 | this.timespans.update(this.ellapsed); 41 | }, 42 | toString : function() { 43 | return this.name + ": " + this.total.toFixed(2) + "(" + this.ellapsed.toFixed(3) + ")"; 44 | } 45 | }); 46 | 47 | return Time; 48 | }); 49 | -------------------------------------------------------------------------------- /js/commonUtils/timespan.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | define(["inheritance"], function(Inheritance) { 5 | 6 | var TimeSpan = Class.extend({ 7 | 8 | // context options: 9 | // onStart, onChange, onFinish, lifespan 10 | init : function(context) { 11 | 12 | // default values 13 | this.lifespan = 1; 14 | this.total = 0; 15 | // Translate all the context into this 16 | $.extend(this, context); 17 | }, 18 | 19 | start : function(startTime) { 20 | this.startTime = startTime; 21 | this.total = 0; 22 | 23 | if (this.onStart) 24 | this.onStart(startTime); 25 | }, 26 | 27 | increment : function(ellapsed) { 28 | this.total += ellapsed; 29 | if (this.onChange) 30 | this.onChange(this.total, this.getPct()); 31 | 32 | if (this.total > this.lifespan) 33 | this.finish(); 34 | }, 35 | 36 | finish : function() { 37 | this.completed = true; 38 | 39 | if (this.onFinish) 40 | this.onFinish(); 41 | 42 | }, 43 | 44 | getPct : function() { 45 | return (this.total) / this.lifespan; 46 | }, 47 | 48 | drawClock : function(g, center, radius) { 49 | var pct = this.getPct(); 50 | g.fill(0); 51 | g.ellipse(center.x, center.y, radius, radius); 52 | g.fill(1); 53 | g.arc(center.x, center.y, radius - 1, radius - 1, 0, 2 * pct * Math.PI); 54 | g.fill(0); 55 | g.ellipse(center.x, center.y, radius * .2, radius * .2); 56 | 57 | }, 58 | 59 | toString : function() { 60 | return this.total + "/" + this.lifespan + " = " + this.getPct(); 61 | }, 62 | }); 63 | 64 | var TimeSpanManager = Class.extend({ 65 | init : function() { 66 | this.timespans = []; 67 | }, 68 | 69 | add : function(timespan) { 70 | this.timespans.push(timespan); 71 | }, 72 | 73 | update : function(ellapsed) { 74 | $.each(this.timespans, function(index, t) { 75 | t.increment(ellapsed); 76 | }); 77 | 78 | // cleanup 79 | this.timespans = _.filter(this.timespans, function(t) { 80 | return !t.completed; 81 | }); 82 | } 83 | }); 84 | 85 | var PowerUpDown = TimeSpan.extend({ 86 | init : function(context) { 87 | this._super(context); 88 | this.ended = false; 89 | this.started = false; 90 | this.total = 0; 91 | 92 | }, 93 | 94 | end : function() { 95 | this.ended = true; 96 | this.total = 0; 97 | 98 | }, 99 | 100 | getPct : function() { 101 | if (!this.started) { 102 | // Powering up 103 | return utilities.constrain(this.total / this.powerUpLength, 0, 1); 104 | 105 | } else { 106 | if (!this.ended) { 107 | // Cycling 108 | return 1; 109 | } else { 110 | return utilities.constrain(1 - this.total / this.powerDownLength, 0, 1); 111 | 112 | } 113 | } 114 | }, 115 | 116 | startMiddle : function() { 117 | this.started = true; 118 | if (this.onMiddle) 119 | this.onMiddle(this.total); 120 | 121 | }, 122 | 123 | increment : function(ellapsed) { 124 | this.total += ellapsed; 125 | if (!this.started) { 126 | // Check for start 127 | if (this.total > this.powerUpLength) 128 | this.startMiddle(); 129 | } else { 130 | if (this.ended) { 131 | // Check for end 132 | if (this.total > this.powerDownLength) { 133 | this.finish(); 134 | } 135 | 136 | } 137 | } 138 | 139 | } 140 | }); 141 | 142 | TimeSpan.Manager = TimeSpanManager; 143 | TimeSpan.PowerUpDown = PowerUpDown; 144 | return TimeSpan; 145 | }); 146 | -------------------------------------------------------------------------------- /js/commonUtils/transform.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | // Reusable Vector class 5 | 6 | define(["./vector"], function(Vector) { 7 | var Transform = Vector.extend({ 8 | init : function(arg0, arg1, arg2) { 9 | this._super(arg0, arg1, arg2); 10 | this.rotation = 0; 11 | this.scale = 1; 12 | 13 | }, 14 | 15 | cloneFrom : function(t) { 16 | this.rotation = t.rotation; 17 | this.scale = t.scale; 18 | this.setTo(t); 19 | }, 20 | 21 | reset : function() { 22 | this.rotation = 0; 23 | this.scale = 1; 24 | this.setTo(0, 0, 0); 25 | }, 26 | 27 | applyTransform : function(g) { 28 | this.translateTo(g); 29 | g.rotate(this.rotation); 30 | g.scale(this.scale); 31 | }, 32 | 33 | toWorld : function(localPos, worldPos) { 34 | worldPos.setTo(localPos); 35 | worldPos.rotate(this.rotation); 36 | worldPos.add(this); 37 | 38 | worldPos.mult(this.scale); 39 | if (localPos.rotation !== undefined) 40 | worldPos.rotation += this.rotation; 41 | }, 42 | 43 | toLocal : function(worldPos, localPos) { 44 | localPos.setTo(worldPos); 45 | localPos.div(this.scale); 46 | localPos.sub(this); 47 | localPos.rotate(-this.rotation); 48 | 49 | if (worldPos.rotation !== undefined) 50 | localPos.rotation -= this.rotation; 51 | }, 52 | 53 | toString : function() { 54 | return "[" + this._super() + " " + this.rotation.toFixed(2) + "rad " + this.scale + "X]"; 55 | } 56 | }); 57 | 58 | return Transform; 59 | 60 | }); 61 | -------------------------------------------------------------------------------- /js/commonUtils/tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | define(["common"], function(common) { 6 | var nodeCount = 0; 7 | 8 | var Tree = Class.extend({ 9 | init : function() { 10 | // Set the depth if there's a parent 11 | this.depth = 0; 12 | 13 | this.idNumber = nodeCount; 14 | this.children = []; 15 | nodeCount++; 16 | }, 17 | 18 | compileNodes : function(list, query) { 19 | 20 | if (query(this)) 21 | list.push(this); 22 | if (this.children) { 23 | $.each(this.children, function(index, child) { 24 | child.compileNodes(list, query); 25 | }); 26 | } 27 | }, 28 | 29 | removeChildren : function() { 30 | $.each(this.children, function(index, child) { 31 | child.removeParent(); 32 | }); 33 | this.children = []; 34 | }, 35 | 36 | removeParent : function() { 37 | this.parent = undefined; 38 | this.depth = 0; 39 | }, 40 | 41 | setParent : function(parent) { 42 | 43 | this.parent = parent; 44 | this.depth = this.parent !== undefined ? this.parent.depth + 1 : 0; 45 | 46 | // this NEEDS TO HAVE CHILDREN DEFINED 47 | if (this.parent) { 48 | if (this.parent.children === undefined) 49 | this.parent.children = []; 50 | 51 | this.parent.children.push(this); 52 | } 53 | }, 54 | 55 | getChildren : function() { 56 | return this.children; 57 | }, 58 | 59 | debugPrint : function() { 60 | var spacer = ""; 61 | for (var i = 0; i < this.depth; i++) { 62 | spacer += " "; 63 | } 64 | console.log(spacer + this); 65 | 66 | var children = this.getChildren(); 67 | if (children !== undefined) { 68 | $.each(children, function(index, node) { 69 | node.debugPrint(); 70 | }); 71 | } 72 | }, 73 | 74 | reduceDown : function(f, base) { 75 | console.log(this.depth + " Reduce down " + this); 76 | base = f(base, this); 77 | 78 | if (this.children !== undefined) { 79 | $.each(this.children, function(index, node) { 80 | base = node.reduceDown(f, base); 81 | }); 82 | } 83 | 84 | return base; 85 | }, 86 | 87 | toString : function() { 88 | return "Node" + this.idNumber; 89 | }, 90 | 91 | generateTree : function(initNode) { 92 | initNode(this); 93 | var children = this.getChildren(); 94 | $.each(children, function(index, node) { 95 | node.generateTree(initNode); 96 | }); 97 | } 98 | }); 99 | 100 | return Tree; 101 | 102 | }); 103 | -------------------------------------------------------------------------------- /js/commonUtils/ui.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kate Compton 3 | */ 4 | 5 | define([], function() { 6 | return { 7 | addSlider : function(parent, key, defaultValue, minValue, maxValue, onChange) { 8 | 9 | // Create an empty slider div 10 | var optionDiv = $("
", { 11 | }); 12 | optionDiv.css({ 13 | "pointer-events" : "auto" 14 | }); 15 | parent.append(optionDiv); 16 | 17 | var slider = $('
', { 18 | id : 'slider_' + key, 19 | class : "tuning_slider", 20 | value : key 21 | }); 22 | 23 | var step = maxValue - minValue; 24 | if (step < 10) 25 | step = .1; 26 | else 27 | step = 1; 28 | 29 | slider.appendTo(optionDiv); 30 | slider.slider({ 31 | range : "min", 32 | value : defaultValue, 33 | min : minValue, 34 | max : maxValue, 35 | step : step, 36 | slide : function(event, ui) { 37 | $("#" + key + "amt").text(ui.value); 38 | console.log("Slide " + ui.value); 39 | if (onChange !== undefined) { 40 | onChange(key, ui.value); 41 | } 42 | } 43 | }); 44 | 45 | // Create a lable 46 | $('