pixie_dust 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README +16 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/game.js +9200 -0
  8. data/lib/corelib.js +3331 -0
  9. data/lib/pixie_dust/version.rb +3 -0
  10. data/lib/pixie_dust.rb +14 -0
  11. data/pixie.json +15 -0
  12. data/pixie_dust.gemspec +29 -0
  13. data/source/active_bounds.coffee +48 -0
  14. data/source/ageable.coffee +23 -0
  15. data/source/bounded.coffee +282 -0
  16. data/source/camera.coffee +138 -0
  17. data/source/camera.fade.coffee +69 -0
  18. data/source/camera.flash.coffee +69 -0
  19. data/source/camera.rotate.coffee +11 -0
  20. data/source/camera.shake.coffee +27 -0
  21. data/source/camera.zoom.coffee +25 -0
  22. data/source/camera.zsort.coffee +13 -0
  23. data/source/clampable.coffee +61 -0
  24. data/source/collidable.coffee +126 -0
  25. data/source/collision.coffee +272 -0
  26. data/source/collision_response.coffee +28 -0
  27. data/source/color.coffee +1113 -0
  28. data/source/color_table.coffee +2534 -0
  29. data/source/controllable.coffee +66 -0
  30. data/source/cooldown.coffee +82 -0
  31. data/source/debuggable.coffee +253 -0
  32. data/source/drawable.coffee +167 -0
  33. data/source/dust_emitter.coffee +36 -0
  34. data/source/easing.coffee +38 -0
  35. data/source/emitter.coffee +7 -0
  36. data/source/emitterable.coffee +68 -0
  37. data/source/engine.coffee +274 -0
  38. data/source/engine.collision.coffee +77 -0
  39. data/source/engine.data.coffee +23 -0
  40. data/source/engine.delay.coffee +41 -0
  41. data/source/engine.fps_counter.coffee +32 -0
  42. data/source/engine.game_state.coffee +86 -0
  43. data/source/engine.joysticks.coffee +47 -0
  44. data/source/engine.keyboard.coffee +17 -0
  45. data/source/engine.levels.coffee +69 -0
  46. data/source/engine.mouse.coffee +16 -0
  47. data/source/engine.selector.coffee +166 -0
  48. data/source/engine.stats.coffee +16 -0
  49. data/source/engine.tilemap.coffee +41 -0
  50. data/source/engine_background.coffee +32 -0
  51. data/source/expirable.coffee +47 -0
  52. data/source/flickerable.coffee +78 -0
  53. data/source/follow.coffee +65 -0
  54. data/source/framerate.coffee +42 -0
  55. data/source/game_object.coffee +181 -0
  56. data/source/game_object.effect.coffee +33 -0
  57. data/source/game_object.meter.coffee +191 -0
  58. data/source/game_over.coffee +40 -0
  59. data/source/game_state.coffee +67 -0
  60. data/source/game_state.save_state.coffee +76 -0
  61. data/source/game_state.single_camera.coffee +40 -0
  62. data/source/game_state_cameras.coffee +33 -0
  63. data/source/level_state.coffee +32 -0
  64. data/source/movable.coffee +57 -0
  65. data/source/oscillator.coffee +18 -0
  66. data/source/pixie_dust.coffee +2 -0
  67. data/source/resource_loader.coffee +35 -0
  68. data/source/rotatable.coffee +38 -0
  69. data/source/sprite.coffee +181 -0
  70. data/source/text_effect.coffee +74 -0
  71. data/source/text_effect.floating.coffee +22 -0
  72. data/source/text_screen.coffee +38 -0
  73. data/source/tilemap.coffee +56 -0
  74. data/source/timed_events.coffee +78 -0
  75. data/source/title_screen.coffee +38 -0
  76. data/source/tween.coffee +70 -0
  77. data/test/active_bounds.coffee +67 -0
  78. data/test/bounded.coffee +98 -0
  79. data/test/camera.coffee +29 -0
  80. data/test/clampable.coffee +18 -0
  81. data/test/collidable.coffee +51 -0
  82. data/test/collision.coffee +70 -0
  83. data/test/color.coffee +533 -0
  84. data/test/controllable.coffee +108 -0
  85. data/test/cooldown.coffee +116 -0
  86. data/test/debuggable.coffee +71 -0
  87. data/test/drawable.coffee +31 -0
  88. data/test/emitter.coffee +0 -0
  89. data/test/emitterable.coffee +15 -0
  90. data/test/engine.coffee +228 -0
  91. data/test/engine_data.coffee +12 -0
  92. data/test/engine_delay.coffee +14 -0
  93. data/test/engine_selector.coffee +100 -0
  94. data/test/expirable.coffee +35 -0
  95. data/test/flickerable.coffee +51 -0
  96. data/test/follow.coffee +34 -0
  97. data/test/game_object.coffee +78 -0
  98. data/test/game_object_effect.coffee +17 -0
  99. data/test/metered.coffee +33 -0
  100. data/test/movable.coffee +46 -0
  101. data/test/oscillator.coffee +28 -0
  102. data/test/resource_loader.coffee +7 -0
  103. data/test/rotatable.coffee +20 -0
  104. data/test/sprite.coffee +21 -0
  105. data/test/text.coffee +25 -0
  106. data/test/timed_events.coffee +23 -0
  107. data/test/tweening.coffee +18 -0
  108. metadata +233 -0
data/lib/corelib.js ADDED
@@ -0,0 +1,3331 @@
1
+
2
+
3
+ /**
4
+ Checks whether an object is an array.
5
+
6
+ Object.isArray([1, 2, 4])
7
+ # => true
8
+
9
+ Object.isArray({key: "value"})
10
+ # => false
11
+
12
+ @name isArray
13
+ @methodOf Object
14
+ @param {Object} object The object to check for array-ness.
15
+ @returns {Boolean} A boolean expressing whether the object is an instance of Array
16
+ */
17
+ var __slice = Array.prototype.slice;
18
+
19
+ Object.isArray = function(object) {
20
+ return Object.prototype.toString.call(object) === "[object Array]";
21
+ };
22
+
23
+ /**
24
+ Checks whether an object is a string.
25
+
26
+ Object.isString("a string")
27
+ # => true
28
+
29
+ Object.isString([1, 2, 4])
30
+ # => false
31
+
32
+ Object.isString({key: "value"})
33
+ # => false
34
+
35
+ @name isString
36
+ @methodOf Object
37
+ @param {Object} object The object to check for string-ness.
38
+ @returns {Boolean} A boolean expressing whether the object is an instance of String
39
+ */
40
+
41
+ Object.isString = function(object) {
42
+ return Object.prototype.toString.call(object) === "[object String]";
43
+ };
44
+
45
+ /**
46
+ Merges properties from objects into target without overiding.
47
+ First come, first served.
48
+
49
+ I =
50
+ a: 1
51
+ b: 2
52
+ c: 3
53
+
54
+ Object.reverseMerge I,
55
+ c: 6
56
+ d: 4
57
+
58
+ I # => {a: 1, b:2, c:3, d: 4}
59
+
60
+ @name reverseMerge
61
+ @methodOf Object
62
+ @param {Object} target The object to merge the properties into.
63
+ @returns {Object} target
64
+ */
65
+
66
+ Object.defaults = Object.reverseMerge = function() {
67
+ var name, object, objects, target, _i, _len;
68
+ target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
69
+ for (_i = 0, _len = objects.length; _i < _len; _i++) {
70
+ object = objects[_i];
71
+ for (name in object) {
72
+ if (!target.hasOwnProperty(name)) target[name] = object[name];
73
+ }
74
+ }
75
+ return target;
76
+ };
77
+
78
+ /**
79
+ Merges properties from sources into target with overiding.
80
+ Last in covers earlier properties.
81
+
82
+ I =
83
+ a: 1
84
+ b: 2
85
+ c: 3
86
+
87
+ Object.extend I,
88
+ c: 6
89
+ d: 4
90
+
91
+ I # => {a: 1, b:2, c:6, d: 4}
92
+
93
+ @name extend
94
+ @methodOf Object
95
+ @param {Object} target The object to merge the properties into.
96
+ @returns {Object} target
97
+ */
98
+
99
+ Object.extend = function() {
100
+ var name, source, sources, target, _i, _len;
101
+ target = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
102
+ for (_i = 0, _len = sources.length; _i < _len; _i++) {
103
+ source = sources[_i];
104
+ for (name in source) {
105
+ target[name] = source[name];
106
+ }
107
+ }
108
+ return target;
109
+ };
110
+
111
+ /**
112
+ Helper method that tells you if something is an object.
113
+
114
+ object = {a: 1}
115
+
116
+ Object.isObject(object)
117
+ # => true
118
+
119
+ @name isObject
120
+ @methodOf Object
121
+ @param {Object} object Maybe this guy is an object.
122
+ @returns {Boolean} true if this guy is an object.
123
+ */
124
+
125
+ Object.isObject = function(object) {
126
+ return Object.prototype.toString.call(object) === '[object Object]';
127
+ };
128
+
129
+ /**
130
+ Calculate the average value of an array. Returns undefined if some elements
131
+ are not numbers.
132
+
133
+ [1, 3, 5, 7].average()
134
+ # => 4
135
+
136
+ @name average
137
+ @methodOf Array#
138
+ @returns {Number} The average (arithmetic mean) of the list of numbers.
139
+ */
140
+ var _base,
141
+ __slice = Array.prototype.slice;
142
+
143
+ Array.prototype.average = function() {
144
+ return this.sum() / this.length;
145
+ };
146
+
147
+ /**
148
+ Returns a copy of the array without null and undefined values.
149
+
150
+ [null, undefined, 3, 3, undefined, 5].compact()
151
+ # => [3, 3, 5]
152
+
153
+ @name compact
154
+ @methodOf Array#
155
+ @returns {Array} A new array that contains only the non-null values.
156
+ */
157
+
158
+ Array.prototype.compact = function() {
159
+ return this.select(function(element) {
160
+ return element != null;
161
+ });
162
+ };
163
+
164
+ /**
165
+ Creates and returns a copy of the array. The copy contains
166
+ the same objects.
167
+
168
+ a = ["a", "b", "c"]
169
+ b = a.copy()
170
+
171
+ # their elements are equal
172
+ a[0] == b[0] && a[1] == b[1] && a[2] == b[2]
173
+ # => true
174
+
175
+ # but they aren't the same object in memory
176
+ a === b
177
+ # => false
178
+
179
+ @name copy
180
+ @methodOf Array#
181
+ @returns {Array} A new array that is a copy of the array
182
+ */
183
+
184
+ Array.prototype.copy = function() {
185
+ return this.concat();
186
+ };
187
+
188
+ /**
189
+ Empties the array of its contents. It is modified in place.
190
+
191
+ fullArray = [1, 2, 3]
192
+ fullArray.clear()
193
+ fullArray
194
+ # => []
195
+
196
+ @name clear
197
+ @methodOf Array#
198
+ @returns {Array} this, now emptied.
199
+ */
200
+
201
+ Array.prototype.clear = function() {
202
+ this.length = 0;
203
+ return this;
204
+ };
205
+
206
+ /**
207
+ Flatten out an array of arrays into a single array of elements.
208
+
209
+ [[1, 2], [3, 4], 5].flatten()
210
+ # => [1, 2, 3, 4, 5]
211
+
212
+ # won't flatten twice nested arrays. call
213
+ # flatten twice if that is what you want
214
+ [[1, 2], [3, [4, 5]], 6].flatten()
215
+ # => [1, 2, 3, [4, 5], 6]
216
+
217
+ @name flatten
218
+ @methodOf Array#
219
+ @returns {Array} A new array with all the sub-arrays flattened to the top.
220
+ */
221
+
222
+ Array.prototype.flatten = function() {
223
+ return this.inject([], function(a, b) {
224
+ return a.concat(b);
225
+ });
226
+ };
227
+
228
+ /**
229
+ Invoke the named method on each element in the array
230
+ and return a new array containing the results of the invocation.
231
+
232
+ [1.1, 2.2, 3.3, 4.4].invoke("floor")
233
+ # => [1, 2, 3, 4]
234
+
235
+ ['hello', 'world', 'cool!'].invoke('substring', 0, 3)
236
+ # => ['hel', 'wor', 'coo']
237
+
238
+ @param {String} method The name of the method to invoke.
239
+ @param [arg...] Optional arguments to pass to the method being invoked.
240
+ @name invoke
241
+ @methodOf Array#
242
+ @returns {Array} A new array containing the results of invoking the named method on each element.
243
+ */
244
+
245
+ Array.prototype.invoke = function() {
246
+ var args, method;
247
+ method = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
248
+ return this.map(function(element) {
249
+ return element[method].apply(element, args);
250
+ });
251
+ };
252
+
253
+ /**
254
+ Randomly select an element from the array.
255
+
256
+ [1, 2, 3].rand()
257
+ # => 2
258
+
259
+ @name rand
260
+ @methodOf Array#
261
+ @returns {Object} A random element from an array
262
+ */
263
+
264
+ Array.prototype.rand = function() {
265
+ return this[rand(this.length)];
266
+ };
267
+
268
+ /**
269
+ Remove the first occurrence of the given object from the array if it is
270
+ present. The array is modified in place.
271
+
272
+ a = [1, 1, "a", "b"]
273
+ a.remove(1)
274
+ # => 1
275
+
276
+ a
277
+ # => [1, "a", "b"]
278
+
279
+ @name remove
280
+ @methodOf Array#
281
+ @param {Object} object The object to remove from the array if present.
282
+ @returns {Object} The removed object if present otherwise undefined.
283
+ */
284
+
285
+ Array.prototype.remove = function(object) {
286
+ var index;
287
+ index = this.indexOf(object);
288
+ if (index >= 0) {
289
+ return this.splice(index, 1)[0];
290
+ } else {
291
+ return;
292
+ }
293
+ };
294
+
295
+ /**
296
+ Returns true if the element is present in the array.
297
+
298
+ ["a", "b", "c"].include("c")
299
+ # => true
300
+
301
+ [40, "a"].include(700)
302
+ # => false
303
+
304
+ @name include
305
+ @methodOf Array#
306
+ @param {Object} element The element to check if present.
307
+ @returns {Boolean} true if the element is in the array, false otherwise.
308
+ */
309
+
310
+ Array.prototype.include = function(element) {
311
+ return this.indexOf(element) !== -1;
312
+ };
313
+
314
+ /**
315
+ Call the given iterator once for each element in the array,
316
+ passing in the element as the first argument, the index of
317
+ the element as the second argument, and <code>this</code> array as the
318
+ third argument.
319
+
320
+ word = ""
321
+ indices = []
322
+ ["r", "a", "d"].each (letter, index) ->
323
+ word += letter
324
+ indices.push(index)
325
+
326
+ # => ["r", "a", "d"]
327
+
328
+ word
329
+ # => "rad"
330
+
331
+ indices
332
+ # => [0, 1, 2]
333
+
334
+ @name each
335
+ @methodOf Array#
336
+ @param {Function} iterator Function to be called once for each element in the array.
337
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
338
+ @returns {Array} this to enable method chaining.
339
+ */
340
+
341
+ Array.prototype.each = function(iterator, context) {
342
+ var element, i, _len;
343
+ if (this.forEach) {
344
+ this.forEach(iterator, context);
345
+ } else {
346
+ for (i = 0, _len = this.length; i < _len; i++) {
347
+ element = this[i];
348
+ iterator.call(context, element, i, this);
349
+ }
350
+ }
351
+ return this;
352
+ };
353
+
354
+ /**
355
+ Call the given iterator once for each element in the array,
356
+ passing in the element as the first argument, the index of
357
+ the element as the second argument, and `this` array as the
358
+ third argument.
359
+
360
+ [1, 2, 3].map (number) ->
361
+ number * number
362
+ # => [1, 4, 9]
363
+
364
+ @name map
365
+ @methodOf Array#
366
+ @param {Function} iterator Function to be called once for each element in the array.
367
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
368
+ @returns {Array} An array of the results of the iterator function being called on the original array elements.
369
+ */
370
+
371
+ (_base = Array.prototype).map || (_base.map = function(iterator, context) {
372
+ var element, i, results, _len;
373
+ results = [];
374
+ for (i = 0, _len = this.length; i < _len; i++) {
375
+ element = this[i];
376
+ results.push(iterator.call(context, element, i, this));
377
+ }
378
+ return results;
379
+ });
380
+
381
+ /**
382
+ Call the given iterator once for each pair of objects in the array.
383
+
384
+ [1, 2, 3, 4].eachPair (a, b) ->
385
+ # 1, 2
386
+ # 1, 3
387
+ # 1, 4
388
+ # 2, 3
389
+ # 2, 4
390
+ # 3, 4
391
+
392
+ @name eachPair
393
+ @methodOf Array#
394
+ @param {Function} iterator Function to be called once for each pair of elements in the array.
395
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
396
+ */
397
+
398
+ Array.prototype.eachPair = function(iterator, context) {
399
+ var a, b, i, j, length, _results;
400
+ length = this.length;
401
+ i = 0;
402
+ _results = [];
403
+ while (i < length) {
404
+ a = this[i];
405
+ j = i + 1;
406
+ i += 1;
407
+ _results.push((function() {
408
+ var _results2;
409
+ _results2 = [];
410
+ while (j < length) {
411
+ b = this[j];
412
+ j += 1;
413
+ _results2.push(iterator.call(context, a, b));
414
+ }
415
+ return _results2;
416
+ }).call(this));
417
+ }
418
+ return _results;
419
+ };
420
+
421
+ /**
422
+ Call the given iterator once for each element in the array,
423
+ passing in the element as the first argument and the given object
424
+ as the second argument. Additional arguments are passed similar to
425
+ <code>each</code>.
426
+
427
+ @see Array#each
428
+ @name eachWithObject
429
+ @methodOf Array#
430
+ @param {Object} object The object to pass to the iterator on each visit.
431
+ @param {Function} iterator Function to be called once for each element in the array.
432
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
433
+ @returns {Array} this
434
+ */
435
+
436
+ Array.prototype.eachWithObject = function(object, iterator, context) {
437
+ this.each(function(element, i, self) {
438
+ return iterator.call(context, element, object, i, self);
439
+ });
440
+ return object;
441
+ };
442
+
443
+ /**
444
+ Call the given iterator once for each group of elements in the array,
445
+ passing in the elements in groups of n. Additional argumens are
446
+ passed as in each.
447
+
448
+ results = []
449
+ [1, 2, 3, 4].eachSlice 2, (slice) ->
450
+ results.push(slice)
451
+ # => [1, 2, 3, 4]
452
+
453
+ results
454
+ # => [[1, 2], [3, 4]]
455
+
456
+ @see Array#each
457
+ @name eachSlice
458
+ @methodOf Array#
459
+ @param {Number} n The number of elements in each group.
460
+ @param {Function} iterator Function to be called once for each group of elements in the array.
461
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
462
+ @returns {Array} this
463
+ */
464
+
465
+ Array.prototype.eachSlice = function(n, iterator, context) {
466
+ var i, len;
467
+ if (n > 0) {
468
+ len = (this.length / n).floor();
469
+ i = -1;
470
+ while (++i < len) {
471
+ iterator.call(context, this.slice(i * n, (i + 1) * n), i * n, this);
472
+ }
473
+ }
474
+ return this;
475
+ };
476
+
477
+ /**
478
+ Pipe the input through each function in the array in turn. For example, if you have a
479
+ list of objects you can perform a series of selection, sorting, and other processing
480
+ methods and then receive the processed list. This array must contain functions that
481
+ accept a single input and return the processed input. The output of the first function
482
+ is fed to the input of the second and so on until the final processed output is returned.
483
+
484
+ @name pipeline
485
+ @methodOf Array#
486
+
487
+ @param {Object} input The initial input to pass to the first function in the pipeline.
488
+ @returns {Object} The result of processing the input by each function in the array.
489
+ */
490
+
491
+ Array.prototype.pipeline = function(input) {
492
+ var fn, _i, _len;
493
+ for (_i = 0, _len = this.length; _i < _len; _i++) {
494
+ fn = this[_i];
495
+ input = fn(input);
496
+ }
497
+ return input;
498
+ };
499
+
500
+ /**
501
+ Returns a new array with the elements all shuffled up.
502
+
503
+ a = [1, 2, 3]
504
+
505
+ a.shuffle()
506
+ # => [2, 3, 1]
507
+
508
+ a # => [1, 2, 3]
509
+
510
+ @name shuffle
511
+ @methodOf Array#
512
+ @returns {Array} A new array that is randomly shuffled.
513
+ */
514
+
515
+ Array.prototype.shuffle = function() {
516
+ var shuffledArray;
517
+ shuffledArray = [];
518
+ this.each(function(element) {
519
+ return shuffledArray.splice(rand(shuffledArray.length + 1), 0, element);
520
+ });
521
+ return shuffledArray;
522
+ };
523
+
524
+ /**
525
+ Returns the first element of the array, undefined if the array is empty.
526
+
527
+ ["first", "second", "third"].first()
528
+ # => "first"
529
+
530
+ @name first
531
+ @methodOf Array#
532
+ @returns {Object} The first element, or undefined if the array is empty.
533
+ */
534
+
535
+ Array.prototype.first = function() {
536
+ return this[0];
537
+ };
538
+
539
+ /**
540
+ Returns the last element of the array, undefined if the array is empty.
541
+
542
+ ["first", "second", "third"].last()
543
+ # => "third"
544
+
545
+ @name last
546
+ @methodOf Array#
547
+ @returns {Object} The last element, or undefined if the array is empty.
548
+ */
549
+
550
+ Array.prototype.last = function() {
551
+ return this[this.length - 1];
552
+ };
553
+
554
+ /**
555
+ Returns an object containing the extremes of this array.
556
+
557
+ [-1, 3, 0].extremes()
558
+ # => {min: -1, max: 3}
559
+
560
+ @name extremes
561
+ @methodOf Array#
562
+ @param {Function} [fn] An optional funtion used to evaluate each element to calculate its value for determining extremes.
563
+ @returns {Object} {min: minElement, max: maxElement}
564
+ */
565
+
566
+ Array.prototype.extremes = function(fn) {
567
+ var max, maxResult, min, minResult;
568
+ if (fn == null) fn = Function.identity;
569
+ min = max = void 0;
570
+ minResult = maxResult = void 0;
571
+ this.each(function(object) {
572
+ var result;
573
+ result = fn(object);
574
+ if (min != null) {
575
+ if (result < minResult) {
576
+ min = object;
577
+ minResult = result;
578
+ }
579
+ } else {
580
+ min = object;
581
+ minResult = result;
582
+ }
583
+ if (max != null) {
584
+ if (result > maxResult) {
585
+ max = object;
586
+ return maxResult = result;
587
+ }
588
+ } else {
589
+ max = object;
590
+ return maxResult = result;
591
+ }
592
+ });
593
+ return {
594
+ min: min,
595
+ max: max
596
+ };
597
+ };
598
+
599
+ Array.prototype.maxima = function(fn) {
600
+ if (fn == null) fn = Function.identity;
601
+ return this.inject([-Infinity, []], function(memo, item) {
602
+ var maxItems, maxValue, value;
603
+ value = fn(item);
604
+ maxValue = memo[0], maxItems = memo[1];
605
+ if (value > maxValue) {
606
+ return [value, [item]];
607
+ } else if (value === maxValue) {
608
+ return [value, maxItems.concat(item)];
609
+ } else {
610
+ return memo;
611
+ }
612
+ }).last();
613
+ };
614
+
615
+ Array.prototype.maximum = function(fn) {
616
+ return this.maxima().first();
617
+ };
618
+
619
+ Array.prototype.minima = function(fn) {
620
+ var inverseFn;
621
+ if (fn == null) fn = Function.identity;
622
+ inverseFn = function(x) {
623
+ return -x;
624
+ };
625
+ return this.maxima(inverseFn);
626
+ };
627
+
628
+ Array.prototype.minimum = function(fn) {
629
+ return this.minima().first();
630
+ };
631
+
632
+ /**
633
+ Pretend the array is a circle and grab a new array containing length elements.
634
+ If length is not given return the element at start, again assuming the array
635
+ is a circle.
636
+
637
+ [1, 2, 3].wrap(-1)
638
+ # => 3
639
+
640
+ [1, 2, 3].wrap(6)
641
+ # => 1
642
+
643
+ ["l", "o", "o", "p"].wrap(0, 16)
644
+ # => ["l", "o", "o", "p", "l", "o", "o", "p", "l", "o", "o", "p", "l", "o", "o", "p"]
645
+
646
+ @name wrap
647
+ @methodOf Array#
648
+ @param {Number} start The index to start wrapping at, or the index of the sole element to return if no length is given.
649
+ @param {Number} [length] Optional length determines how long result array should be.
650
+ @returns {Object} or {Array} The element at start mod array.length, or an array of length elements, starting from start and wrapping.
651
+ */
652
+
653
+ Array.prototype.wrap = function(start, length) {
654
+ var end, i, result;
655
+ if (length != null) {
656
+ end = start + length;
657
+ i = start;
658
+ result = [];
659
+ while (i < end) {
660
+ result.push(this[i.mod(this.length)]);
661
+ i += 1;
662
+ }
663
+ return result;
664
+ } else {
665
+ return this[start.mod(this.length)];
666
+ }
667
+ };
668
+
669
+ /**
670
+ Partitions the elements into two groups: those for which the iterator returns
671
+ true, and those for which it returns false.
672
+
673
+ [evens, odds] = [1, 2, 3, 4].partition (n) ->
674
+ n.even()
675
+
676
+ evens
677
+ # => [2, 4]
678
+
679
+ odds
680
+ # => [1, 3]
681
+
682
+ @name partition
683
+ @methodOf Array#
684
+ @param {Function} iterator
685
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
686
+ @returns {Array} An array in the form of [trueCollection, falseCollection]
687
+ */
688
+
689
+ Array.prototype.partition = function(iterator, context) {
690
+ var falseCollection, trueCollection;
691
+ trueCollection = [];
692
+ falseCollection = [];
693
+ this.each(function(element) {
694
+ if (iterator.call(context, element)) {
695
+ return trueCollection.push(element);
696
+ } else {
697
+ return falseCollection.push(element);
698
+ }
699
+ });
700
+ return [trueCollection, falseCollection];
701
+ };
702
+
703
+ /**
704
+ Return the group of elements for which the return value of the iterator is true.
705
+
706
+ @name select
707
+ @methodOf Array#
708
+ @param {Function} iterator The iterator receives each element in turn as the first agument.
709
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
710
+ @returns {Array} An array containing the elements for which the iterator returned true.
711
+ */
712
+
713
+ Array.prototype.select = function(iterator, context) {
714
+ return this.partition(iterator, context)[0];
715
+ };
716
+
717
+ /**
718
+ Return the group of elements that are not in the passed in set.
719
+
720
+ [1, 2, 3, 4].without ([2, 3])
721
+ # => [1, 4]
722
+
723
+ @name without
724
+ @methodOf Array#
725
+ @param {Array} values List of elements to exclude.
726
+ @returns {Array} An array containing the elements that are not passed in.
727
+ */
728
+
729
+ Array.prototype.without = function(values) {
730
+ return this.reject(function(element) {
731
+ return values.include(element);
732
+ });
733
+ };
734
+
735
+ /**
736
+ Return the group of elements for which the return value of the iterator is false.
737
+
738
+ @name reject
739
+ @methodOf Array#
740
+ @param {Function} iterator The iterator receives each element in turn as the first agument.
741
+ @param {Object} [context] Optional context parameter to be used as `this` when calling the iterator function.
742
+ @returns {Array} An array containing the elements for which the iterator returned false.
743
+ */
744
+
745
+ Array.prototype.reject = function(iterator, context) {
746
+ return this.partition(iterator, context)[1];
747
+ };
748
+
749
+ /**
750
+ Combines all elements of the array by applying a binary operation.
751
+ for each element in the arra the iterator is passed an accumulator
752
+ value (memo) and the element.
753
+
754
+ @name inject
755
+ @methodOf Array#
756
+ @returns {Object} The result of a
757
+ */
758
+
759
+ Array.prototype.inject = function(initial, iterator) {
760
+ this.each(function(element) {
761
+ return initial = iterator(initial, element);
762
+ });
763
+ return initial;
764
+ };
765
+
766
+ /**
767
+ Add all the elements in the array.
768
+
769
+ [1, 2, 3, 4].sum()
770
+ # => 10
771
+
772
+ @name sum
773
+ @methodOf Array#
774
+ @returns {Number} The sum of the elements in the array.
775
+ */
776
+
777
+ Array.prototype.sum = function() {
778
+ return this.inject(0, function(sum, n) {
779
+ return sum + n;
780
+ });
781
+ };
782
+
783
+ /**
784
+ Multiply all the elements in the array.
785
+
786
+ [1, 2, 3, 4].product()
787
+ # => 24
788
+
789
+ @name product
790
+ @methodOf Array#
791
+ @returns {Number} The product of the elements in the array.
792
+ */
793
+
794
+ Array.prototype.product = function() {
795
+ return this.inject(1, function(product, n) {
796
+ return product * n;
797
+ });
798
+ };
799
+
800
+ /**
801
+ Merges together the values of each of the arrays with the values at the corresponding position.
802
+
803
+ ['a', 'b', 'c'].zip([1, 2, 3])
804
+ # => [['a', 1], ['b', 2], ['c', 3]]
805
+
806
+ @name zip
807
+ @methodOf Array#
808
+ @returns {Array} Array groupings whose values are arranged by their positions in the original input arrays.
809
+ */
810
+
811
+ Array.prototype.zip = function() {
812
+ var args;
813
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
814
+ return this.map(function(element, index) {
815
+ var output;
816
+ output = args.map(function(arr) {
817
+ return arr[index];
818
+ });
819
+ output.unshift(element);
820
+ return output;
821
+ });
822
+ };
823
+
824
+ /**
825
+ Bindable module.
826
+
827
+ player = Core
828
+ x: 5
829
+ y: 10
830
+
831
+ player.bind "update", ->
832
+ updatePlayer()
833
+ # => Uncaught TypeError: Object has no method 'bind'
834
+
835
+ player.include(Bindable)
836
+
837
+ player.bind "update", ->
838
+ updatePlayer()
839
+ # => this will call updatePlayer each time through the main loop
840
+
841
+ @name Bindable
842
+ @module
843
+ @constructor
844
+ */
845
+ var Bindable,
846
+ __slice = Array.prototype.slice;
847
+
848
+ Bindable = function(I, self) {
849
+ var eventCallbacks;
850
+ if (I == null) I = {};
851
+ eventCallbacks = {};
852
+ return {
853
+ bind: function() {
854
+ var args;
855
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
856
+ return self.on.apply(self, args);
857
+ },
858
+ unbind: function() {
859
+ var args;
860
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
861
+ return self.off.apply(self, args);
862
+ },
863
+ /**
864
+ Adds a function as an event listener.
865
+
866
+ # this will call coolEventHandler after
867
+ # yourObject.trigger "someCustomEvent" is called.
868
+ yourObject.on "someCustomEvent", coolEventHandler
869
+
870
+ #or
871
+ yourObject.on "anotherCustomEvent", ->
872
+ doSomething()
873
+
874
+ @name on
875
+ @methodOf Bindable#
876
+ @param {String} event The event to listen to.
877
+ @param {Function} callback The function to be called when the specified event
878
+ is triggered.
879
+ */
880
+ on: function(namespacedEvent, callback) {
881
+ var event, namespace, _ref;
882
+ _ref = namespacedEvent.split("."), event = _ref[0], namespace = _ref[1];
883
+ if (namespace) {
884
+ callback.__PIXIE || (callback.__PIXIE = {});
885
+ callback.__PIXIE[namespace] = true;
886
+ }
887
+ eventCallbacks[event] || (eventCallbacks[event] = []);
888
+ eventCallbacks[event].push(callback);
889
+ return this;
890
+ },
891
+ /**
892
+ Removes a specific event listener, or all event listeners if
893
+ no specific listener is given.
894
+
895
+ # removes the handler coolEventHandler from the event
896
+ # "someCustomEvent" while leaving the other events intact.
897
+ yourObject.off "someCustomEvent", coolEventHandler
898
+
899
+ # removes all handlers attached to "anotherCustomEvent"
900
+ yourObject.off "anotherCustomEvent"
901
+
902
+ @name off
903
+ @methodOf Bindable#
904
+ @param {String} event The event to remove the listener from.
905
+ @param {Function} [callback] The listener to remove.
906
+ */
907
+ off: function(namespacedEvent, callback) {
908
+ var callbacks, event, key, namespace, _ref;
909
+ _ref = namespacedEvent.split("."), event = _ref[0], namespace = _ref[1];
910
+ if (event) {
911
+ eventCallbacks[event] || (eventCallbacks[event] = []);
912
+ if (namespace) {
913
+ eventCallbacks[event] = eventCallbacks.select(function(callback) {
914
+ var _ref2;
915
+ return !(((_ref2 = callback.__PIXIE) != null ? _ref2[namespace] : void 0) != null);
916
+ });
917
+ } else {
918
+ if (callback) {
919
+ eventCallbacks[event].remove(callback);
920
+ } else {
921
+ eventCallbacks[event] = [];
922
+ }
923
+ }
924
+ } else if (namespace) {
925
+ for (key in eventCallbacks) {
926
+ callbacks = eventCallbacks[key];
927
+ eventCallbacks[key] = callbacks.select(function(callback) {
928
+ var _ref2;
929
+ return !(((_ref2 = callback.__PIXIE) != null ? _ref2[namespace] : void 0) != null);
930
+ });
931
+ }
932
+ }
933
+ return this;
934
+ },
935
+ /**
936
+ Calls all listeners attached to the specified event.
937
+
938
+ # calls each event handler bound to "someCustomEvent"
939
+ yourObject.trigger "someCustomEvent"
940
+
941
+ @name trigger
942
+ @methodOf Bindable#
943
+ @param {String} event The event to trigger.
944
+ @param {Array} [parameters] Additional parameters to pass to the event listener.
945
+ */
946
+ trigger: function() {
947
+ var callbacks, event, parameters;
948
+ event = arguments[0], parameters = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
949
+ callbacks = eventCallbacks[event];
950
+ if (callbacks && callbacks.length) {
951
+ self = this;
952
+ return callbacks.each(function(callback) {
953
+ return callback.apply(self, parameters);
954
+ });
955
+ }
956
+ }
957
+ };
958
+ };
959
+
960
+ (typeof exports !== "undefined" && exports !== null ? exports : this)["Bindable"] = Bindable;
961
+
962
+ var CommandStack;
963
+
964
+ CommandStack = function() {
965
+ var index, stack;
966
+ stack = [];
967
+ index = 0;
968
+ return {
969
+ execute: function(command) {
970
+ stack[index] = command;
971
+ command.execute();
972
+ return stack.length = index += 1;
973
+ },
974
+ undo: function() {
975
+ var command;
976
+ if (this.canUndo()) {
977
+ index -= 1;
978
+ command = stack[index];
979
+ command.undo();
980
+ return command;
981
+ }
982
+ },
983
+ redo: function() {
984
+ var command;
985
+ if (this.canRedo()) {
986
+ command = stack[index];
987
+ command.execute();
988
+ index += 1;
989
+ return command;
990
+ }
991
+ },
992
+ current: function() {
993
+ return stack[index - 1];
994
+ },
995
+ canUndo: function() {
996
+ return index > 0;
997
+ },
998
+ canRedo: function() {
999
+ return stack[index] != null;
1000
+ }
1001
+ };
1002
+ };
1003
+
1004
+ (typeof exports !== "undefined" && exports !== null ? exports : this)["CommandStack"] = CommandStack;
1005
+
1006
+ /**
1007
+ The Core class is used to add extended functionality to objects without
1008
+ extending the object class directly. Inherit from Core to gain its utility
1009
+ methods.
1010
+
1011
+ @name Core
1012
+ @constructor
1013
+
1014
+ @param {Object} I Instance variables
1015
+ */
1016
+ var __slice = Array.prototype.slice;
1017
+
1018
+ (function() {
1019
+ var root;
1020
+ root = typeof exports !== "undefined" && exports !== null ? exports : this;
1021
+ return root.Core = function(I) {
1022
+ var Module, moduleName, self, _i, _len, _ref;
1023
+ if (I == null) I = {};
1024
+ Object.reverseMerge(I, {
1025
+ includedModules: []
1026
+ });
1027
+ self = {
1028
+ /**
1029
+ External access to instance variables. Use of this property should be avoided
1030
+ in general, but can come in handy from time to time.
1031
+
1032
+ I =
1033
+ r: 255
1034
+ g: 0
1035
+ b: 100
1036
+
1037
+ myObject = Core(I)
1038
+
1039
+ # a bad idea most of the time, but it's
1040
+ # pretty convenient to have available.
1041
+ myObject.I.r
1042
+ # => 255
1043
+
1044
+ myObject.I.g
1045
+ # => 0
1046
+
1047
+ myObject.I.b
1048
+ # => 100
1049
+
1050
+ @name I
1051
+ @fieldOf Core#
1052
+ */
1053
+ I: I,
1054
+ /**
1055
+ Generates a public jQuery style getter / setter method for each
1056
+ String argument.
1057
+
1058
+ myObject = Core
1059
+ r: 255
1060
+ g: 0
1061
+ b: 100
1062
+
1063
+ myObject.attrAccessor "r", "g", "b"
1064
+
1065
+ myObject.r(254)
1066
+ myObject.r()
1067
+
1068
+ => 254
1069
+
1070
+ @name attrAccessor
1071
+ @methodOf Core#
1072
+ */
1073
+ attrAccessor: function() {
1074
+ var attrNames;
1075
+ attrNames = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1076
+ return attrNames.each(function(attrName) {
1077
+ return self[attrName] = function(newValue) {
1078
+ if (newValue != null) {
1079
+ I[attrName] = newValue;
1080
+ return self;
1081
+ } else {
1082
+ return I[attrName];
1083
+ }
1084
+ };
1085
+ });
1086
+ },
1087
+ /**
1088
+ Generates a public jQuery style getter method for each String argument.
1089
+
1090
+ myObject = Core
1091
+ r: 255
1092
+ g: 0
1093
+ b: 100
1094
+
1095
+ myObject.attrReader "r", "g", "b"
1096
+
1097
+ myObject.r()
1098
+ => 255
1099
+
1100
+ myObject.g()
1101
+ => 0
1102
+
1103
+ myObject.b()
1104
+ => 100
1105
+
1106
+ @name attrReader
1107
+ @methodOf Core#
1108
+ */
1109
+ attrReader: function() {
1110
+ var attrNames;
1111
+ attrNames = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1112
+ return attrNames.each(function(attrName) {
1113
+ return self[attrName] = function() {
1114
+ return I[attrName];
1115
+ };
1116
+ });
1117
+ },
1118
+ /**
1119
+ Extends this object with methods from the passed in object. A shortcut for Object.extend(self, methods)
1120
+
1121
+ I =
1122
+ x: 30
1123
+ y: 40
1124
+ maxSpeed: 5
1125
+
1126
+ # we are using extend to give player
1127
+ # additional methods that Core doesn't have
1128
+ player = Core(I).extend
1129
+ increaseSpeed: ->
1130
+ I.maxSpeed += 1
1131
+
1132
+ player.I.maxSpeed
1133
+ => 5
1134
+
1135
+ player.increaseSpeed()
1136
+
1137
+ player.I.maxSpeed
1138
+ => 6
1139
+
1140
+ @name extend
1141
+ @methodOf Core#
1142
+ @see Object.extend
1143
+ @returns self
1144
+ */
1145
+ extend: function(options) {
1146
+ Object.extend(self, options);
1147
+ return self;
1148
+ },
1149
+ /**
1150
+ Includes a module in this object.
1151
+
1152
+ myObject = Core()
1153
+ myObject.include(Bindable)
1154
+
1155
+ # now you can bind handlers to functions
1156
+ myObject.bind "someEvent", ->
1157
+ alert("wow. that was easy.")
1158
+
1159
+ @name include
1160
+ @methodOf Core#
1161
+ @param {String} Module the module to include. A module is a constructor that takes two parameters, I and self, and returns an object containing the public methods to extend the including object with.
1162
+ */
1163
+ include: function() {
1164
+ var Module, key, moduleName, modules, value, _i, _len;
1165
+ modules = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1166
+ for (_i = 0, _len = modules.length; _i < _len; _i++) {
1167
+ Module = modules[_i];
1168
+ if (typeof Module.isString === "function" ? Module.isString() : void 0) {
1169
+ moduleName = Module;
1170
+ Module = Module.constantize();
1171
+ } else if (moduleName = Module._name) {} else {
1172
+ for (key in root) {
1173
+ value = root[key];
1174
+ if (value === Module) Module._name = moduleName = key;
1175
+ }
1176
+ }
1177
+ if (moduleName) {
1178
+ if (!I.includedModules.include(moduleName)) {
1179
+ I.includedModules.push(moduleName);
1180
+ self.extend(Module(I, self));
1181
+ }
1182
+ } else {
1183
+ warn("Unable to discover name for module: ", Module, "\nSerialization issues may occur.");
1184
+ self.extend(Module(I, self));
1185
+ }
1186
+ }
1187
+ return self;
1188
+ },
1189
+ send: function() {
1190
+ var args, name;
1191
+ name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
1192
+ return self[name].apply(self, args);
1193
+ }
1194
+ };
1195
+ self.include("Bindable");
1196
+ _ref = I.includedModules;
1197
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1198
+ moduleName = _ref[_i];
1199
+ Module = moduleName.constantize();
1200
+ self.extend(Module(I, self));
1201
+ }
1202
+ return self;
1203
+ };
1204
+ })();
1205
+
1206
+
1207
+
1208
+
1209
+ var __slice = Array.prototype.slice;
1210
+
1211
+ Function.prototype.once = function() {
1212
+ var func, memo, ran;
1213
+ func = this;
1214
+ ran = false;
1215
+ memo = void 0;
1216
+ return function() {
1217
+ if (ran) return memo;
1218
+ ran = true;
1219
+ return memo = func.apply(this, arguments);
1220
+ };
1221
+ };
1222
+
1223
+ /**
1224
+ Calling a debounced function will postpone its execution until after
1225
+ wait milliseconds have elapsed since the last time the function was
1226
+ invoked. Useful for implementing behavior that should only happen after
1227
+ the input has stopped arriving. For example: rendering a preview of a
1228
+ Markdown comment, recalculating a layout after the window has stopped
1229
+ being resized...
1230
+
1231
+ lazyLayout = calculateLayout.debounce(300)
1232
+ $(window).resize(lazyLayout)
1233
+
1234
+ @name debounce
1235
+ @methodOf Function#
1236
+ @returns {Function} The debounced version of this function.
1237
+ */
1238
+
1239
+ Function.prototype.debounce = function(wait) {
1240
+ var func, timeout;
1241
+ timeout = null;
1242
+ func = this;
1243
+ return function() {
1244
+ var args, context, later;
1245
+ context = this;
1246
+ args = arguments;
1247
+ later = function() {
1248
+ timeout = null;
1249
+ return func.apply(context, args);
1250
+ };
1251
+ clearTimeout(timeout);
1252
+ return timeout = setTimeout(later, wait);
1253
+ };
1254
+ };
1255
+
1256
+ Function.prototype.returning = function(x) {
1257
+ var func;
1258
+ func = this;
1259
+ return function() {
1260
+ func.apply(this, arguments);
1261
+ return x;
1262
+ };
1263
+ };
1264
+
1265
+ Function.prototype.delay = function() {
1266
+ var args, func, wait;
1267
+ wait = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
1268
+ func = this;
1269
+ return setTimeout(function() {
1270
+ return func.apply(null, args);
1271
+ }, wait);
1272
+ };
1273
+
1274
+ Function.prototype.defer = function() {
1275
+ var args;
1276
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1277
+ return this.delay.apply(this, [1].concat(args));
1278
+ };
1279
+
1280
+ Object.extend(Function, {
1281
+ identity: function(x) {
1282
+ return x;
1283
+ },
1284
+ noop: function() {}
1285
+ });
1286
+
1287
+ /**
1288
+ @name Logging
1289
+ @namespace
1290
+
1291
+ Gives you some convenience methods for outputting data while developing.
1292
+
1293
+ log "Testing123"
1294
+ info "Hey, this is happening"
1295
+ warn "Be careful, this might be a problem"
1296
+ error "Kaboom!"
1297
+ */
1298
+ var __slice = Array.prototype.slice;
1299
+
1300
+ ["log", "info", "warn", "error"].each(function(name) {
1301
+ if (typeof console !== "undefined") {
1302
+ return (typeof exports !== "undefined" && exports !== null ? exports : this)[name] = function() {
1303
+ var args;
1304
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1305
+ if (console[name]) return console[name].apply(console, args);
1306
+ };
1307
+ } else {
1308
+ return (typeof exports !== "undefined" && exports !== null ? exports : this)[name] = function() {};
1309
+ }
1310
+ });
1311
+
1312
+ /**
1313
+ * Matrix.js v1.3.0pre
1314
+ *
1315
+ * Copyright (c) 2010 STRd6
1316
+ *
1317
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
1318
+ * of this software and associated documentation files (the "Software"), to deal
1319
+ * in the Software without restriction, including without limitation the rights
1320
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1321
+ * copies of the Software, and to permit persons to whom the Software is
1322
+ * furnished to do so, subject to the following conditions:
1323
+ *
1324
+ * The above copyright notice and this permission notice shall be included in
1325
+ * all copies or substantial portions of the Software.
1326
+ *
1327
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1328
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1329
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1330
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1331
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1332
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1333
+ * THE SOFTWARE.
1334
+ *
1335
+ * Loosely based on flash:
1336
+ * http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/geom/Matrix.html
1337
+ */
1338
+ (function() {
1339
+ /**
1340
+ <pre>
1341
+ _ _
1342
+ | a c tx |
1343
+ | b d ty |
1344
+ |_0 0 1 _|
1345
+ </pre>
1346
+ Creates a matrix for 2d affine transformations.
1347
+
1348
+ concat, inverse, rotate, scale and translate return new matrices with the
1349
+ transformations applied. The matrix is not modified in place.
1350
+
1351
+ Returns the identity matrix when called with no arguments.
1352
+
1353
+ @name Matrix
1354
+ @param {Number} [a]
1355
+ @param {Number} [b]
1356
+ @param {Number} [c]
1357
+ @param {Number} [d]
1358
+ @param {Number} [tx]
1359
+ @param {Number} [ty]
1360
+ @constructor
1361
+ */
1362
+ var Matrix;
1363
+ Matrix = function(a, b, c, d, tx, ty) {
1364
+ var _ref;
1365
+ if (Object.isObject(a)) {
1366
+ _ref = a, a = _ref.a, b = _ref.b, c = _ref.c, d = _ref.d, tx = _ref.tx, ty = _ref.ty;
1367
+ }
1368
+ return {
1369
+ __proto__: Matrix.prototype,
1370
+ /**
1371
+ @name a
1372
+ @fieldOf Matrix#
1373
+ */
1374
+ a: a != null ? a : 1,
1375
+ /**
1376
+ @name b
1377
+ @fieldOf Matrix#
1378
+ */
1379
+ b: b || 0,
1380
+ /**
1381
+ @name c
1382
+ @fieldOf Matrix#
1383
+ */
1384
+ c: c || 0,
1385
+ /**
1386
+ @name d
1387
+ @fieldOf Matrix#
1388
+ */
1389
+ d: d != null ? d : 1,
1390
+ /**
1391
+ @name tx
1392
+ @fieldOf Matrix#
1393
+ */
1394
+ tx: tx || 0,
1395
+ /**
1396
+ @name ty
1397
+ @fieldOf Matrix#
1398
+ */
1399
+ ty: ty || 0
1400
+ };
1401
+ };
1402
+ Matrix.prototype = {
1403
+ /**
1404
+ Returns the result of this matrix multiplied by another matrix
1405
+ combining the geometric effects of the two. In mathematical terms,
1406
+ concatenating two matrixes is the same as combining them using matrix multiplication.
1407
+ If this matrix is A and the matrix passed in is B, the resulting matrix is A x B
1408
+ http://mathworld.wolfram.com/MatrixMultiplication.html
1409
+ @name concat
1410
+ @methodOf Matrix#
1411
+ @param {Matrix} matrix The matrix to multiply this matrix by.
1412
+ @returns {Matrix} The result of the matrix multiplication, a new matrix.
1413
+ */
1414
+ concat: function(matrix) {
1415
+ return Matrix(this.a * matrix.a + this.c * matrix.b, this.b * matrix.a + this.d * matrix.b, this.a * matrix.c + this.c * matrix.d, this.b * matrix.c + this.d * matrix.d, this.a * matrix.tx + this.c * matrix.ty + this.tx, this.b * matrix.tx + this.d * matrix.ty + this.ty);
1416
+ },
1417
+ /**
1418
+ Copy this matrix.
1419
+ @name copy
1420
+ @methodOf Matrix#
1421
+ @returns {Matrix} A copy of this matrix.
1422
+ */
1423
+ copy: function() {
1424
+ return Matrix(this.a, this.b, this.c, this.d, this.tx, this.ty);
1425
+ },
1426
+ /**
1427
+ Given a point in the pretransform coordinate space, returns the coordinates of
1428
+ that point after the transformation occurs. Unlike the standard transformation
1429
+ applied using the transformPoint() method, the deltaTransformPoint() method
1430
+ does not consider the translation parameters tx and ty.
1431
+ @name deltaTransformPoint
1432
+ @methodOf Matrix#
1433
+ @see #transformPoint
1434
+ @return {Point} A new point transformed by this matrix ignoring tx and ty.
1435
+ */
1436
+ deltaTransformPoint: function(point) {
1437
+ return Point(this.a * point.x + this.c * point.y, this.b * point.x + this.d * point.y);
1438
+ },
1439
+ /**
1440
+ Returns the inverse of the matrix.
1441
+ http://mathworld.wolfram.com/MatrixInverse.html
1442
+ @name inverse
1443
+ @methodOf Matrix#
1444
+ @returns {Matrix} A new matrix that is the inverse of this matrix.
1445
+ */
1446
+ inverse: function() {
1447
+ var determinant;
1448
+ determinant = this.a * this.d - this.b * this.c;
1449
+ return Matrix(this.d / determinant, -this.b / determinant, -this.c / determinant, this.a / determinant, (this.c * this.ty - this.d * this.tx) / determinant, (this.b * this.tx - this.a * this.ty) / determinant);
1450
+ },
1451
+ /**
1452
+ Returns a new matrix that corresponds this matrix multiplied by a
1453
+ a rotation matrix.
1454
+ @name rotate
1455
+ @methodOf Matrix#
1456
+ @see Matrix.rotation
1457
+ @param {Number} theta Amount to rotate in radians.
1458
+ @param {Point} [aboutPoint] The point about which this rotation occurs. Defaults to (0,0).
1459
+ @returns {Matrix} A new matrix, rotated by the specified amount.
1460
+ */
1461
+ rotate: function(theta, aboutPoint) {
1462
+ return this.concat(Matrix.rotation(theta, aboutPoint));
1463
+ },
1464
+ /**
1465
+ Returns a new matrix that corresponds this matrix multiplied by a
1466
+ a scaling matrix.
1467
+ @name scale
1468
+ @methodOf Matrix#
1469
+ @see Matrix.scale
1470
+ @param {Number} sx
1471
+ @param {Number} [sy]
1472
+ @param {Point} [aboutPoint] The point that remains fixed during the scaling
1473
+ @returns {Matrix} A new Matrix. The original multiplied by a scaling matrix.
1474
+ */
1475
+ scale: function(sx, sy, aboutPoint) {
1476
+ return this.concat(Matrix.scale(sx, sy, aboutPoint));
1477
+ },
1478
+ /**
1479
+ Returns a new matrix that corresponds this matrix multiplied by a
1480
+ a skewing matrix.
1481
+
1482
+ @name skew
1483
+ @methodOf Matrix#
1484
+ @see Matrix.skew
1485
+ @param {Number} skewX The angle of skew in the x dimension.
1486
+ @param {Number} skewY The angle of skew in the y dimension.
1487
+ */
1488
+ skew: function(skewX, skewY) {
1489
+ return this.concat(Matrix.skew(skewX, skewY));
1490
+ },
1491
+ /**
1492
+ Returns a string representation of this matrix.
1493
+
1494
+ @name toString
1495
+ @methodOf Matrix#
1496
+ @returns {String} A string reperesentation of this matrix.
1497
+ */
1498
+ toString: function() {
1499
+ return "Matrix(" + this.a + ", " + this.b + ", " + this.c + ", " + this.d + ", " + this.tx + ", " + this.ty + ")";
1500
+ },
1501
+ /**
1502
+ Returns the result of applying the geometric transformation represented by the
1503
+ Matrix object to the specified point.
1504
+ @name transformPoint
1505
+ @methodOf Matrix#
1506
+ @see #deltaTransformPoint
1507
+ @returns {Point} A new point with the transformation applied.
1508
+ */
1509
+ transformPoint: function(point) {
1510
+ return Point(this.a * point.x + this.c * point.y + this.tx, this.b * point.x + this.d * point.y + this.ty);
1511
+ },
1512
+ /**
1513
+ Translates the matrix along the x and y axes, as specified by the tx and ty parameters.
1514
+ @name translate
1515
+ @methodOf Matrix#
1516
+ @see Matrix.translation
1517
+ @param {Number} tx The translation along the x axis.
1518
+ @param {Number} ty The translation along the y axis.
1519
+ @returns {Matrix} A new matrix with the translation applied.
1520
+ */
1521
+ translate: function(tx, ty) {
1522
+ return this.concat(Matrix.translation(tx, ty));
1523
+ }
1524
+ };
1525
+ /**
1526
+ Creates a matrix transformation that corresponds to the given rotation,
1527
+ around (0,0) or the specified point.
1528
+ @see Matrix#rotate
1529
+ @param {Number} theta Rotation in radians.
1530
+ @param {Point} [aboutPoint] The point about which this rotation occurs. Defaults to (0,0).
1531
+ @returns {Matrix} A new matrix rotated by the given amount.
1532
+ */
1533
+ Matrix.rotate = Matrix.rotation = function(theta, aboutPoint) {
1534
+ var rotationMatrix;
1535
+ rotationMatrix = Matrix(Math.cos(theta), Math.sin(theta), -Math.sin(theta), Math.cos(theta));
1536
+ if (aboutPoint != null) {
1537
+ rotationMatrix = Matrix.translation(aboutPoint.x, aboutPoint.y).concat(rotationMatrix).concat(Matrix.translation(-aboutPoint.x, -aboutPoint.y));
1538
+ }
1539
+ return rotationMatrix;
1540
+ };
1541
+ /**
1542
+ Returns a matrix that corresponds to scaling by factors of sx, sy along
1543
+ the x and y axis respectively.
1544
+ If only one parameter is given the matrix is scaled uniformly along both axis.
1545
+ If the optional aboutPoint parameter is given the scaling takes place
1546
+ about the given point.
1547
+ @see Matrix#scale
1548
+ @param {Number} sx The amount to scale by along the x axis or uniformly if no sy is given.
1549
+ @param {Number} [sy] The amount to scale by along the y axis.
1550
+ @param {Point} [aboutPoint] The point about which the scaling occurs. Defaults to (0,0).
1551
+ @returns {Matrix} A matrix transformation representing scaling by sx and sy.
1552
+ */
1553
+ Matrix.scale = function(sx, sy, aboutPoint) {
1554
+ var scaleMatrix;
1555
+ sy = sy || sx;
1556
+ scaleMatrix = Matrix(sx, 0, 0, sy);
1557
+ if (aboutPoint) {
1558
+ scaleMatrix = Matrix.translation(aboutPoint.x, aboutPoint.y).concat(scaleMatrix).concat(Matrix.translation(-aboutPoint.x, -aboutPoint.y));
1559
+ }
1560
+ return scaleMatrix;
1561
+ };
1562
+ /**
1563
+ Returns a matrix that corresponds to a skew of skewX, skewY.
1564
+
1565
+ @see Matrix#skew
1566
+ @param {Number} skewX The angle of skew in the x dimension.
1567
+ @param {Number} skewY The angle of skew in the y dimension.
1568
+ @return {Matrix} A matrix transformation representing a skew by skewX and skewY.
1569
+ */
1570
+ Matrix.skew = function(skewX, skewY) {
1571
+ return Matrix(0, Math.tan(skewY), Math.tan(skewX), 0);
1572
+ };
1573
+ /**
1574
+ Returns a matrix that corresponds to a translation of tx, ty.
1575
+ @see Matrix#translate
1576
+ @param {Number} tx The amount to translate in the x direction.
1577
+ @param {Number} ty The amount to translate in the y direction.
1578
+ @return {Matrix} A matrix transformation representing a translation by tx and ty.
1579
+ */
1580
+ Matrix.translate = Matrix.translation = function(tx, ty) {
1581
+ return Matrix(1, 0, 0, 1, tx, ty);
1582
+ };
1583
+ /**
1584
+ A constant representing the identity matrix.
1585
+ @name IDENTITY
1586
+ @fieldOf Matrix
1587
+ */
1588
+ Matrix.IDENTITY = Matrix();
1589
+ /**
1590
+ A constant representing the horizontal flip transformation matrix.
1591
+ @name HORIZONTAL_FLIP
1592
+ @fieldOf Matrix
1593
+ */
1594
+ Matrix.HORIZONTAL_FLIP = Matrix(-1, 0, 0, 1);
1595
+ /**
1596
+ A constant representing the vertical flip transformation matrix.
1597
+ @name VERTICAL_FLIP
1598
+ @fieldOf Matrix
1599
+ */
1600
+ Matrix.VERTICAL_FLIP = Matrix(1, 0, 0, -1);
1601
+ if (Object.freeze) {
1602
+ Object.freeze(Matrix.IDENTITY);
1603
+ Object.freeze(Matrix.HORIZONTAL_FLIP);
1604
+ Object.freeze(Matrix.VERTICAL_FLIP);
1605
+ }
1606
+ return (typeof exports !== "undefined" && exports !== null ? exports : this)["Matrix"] = Matrix;
1607
+ })();
1608
+
1609
+ /**
1610
+ Returns the absolute value of this number.
1611
+
1612
+ (-4).abs()
1613
+ # => 4
1614
+
1615
+ @name abs
1616
+ @methodOf Number#
1617
+ @returns {Number} The absolute value of the number.
1618
+ */
1619
+ Number.prototype.abs = function() {
1620
+ return Math.abs(this);
1621
+ };
1622
+
1623
+ /**
1624
+ Returns the mathematical ceiling of this number.
1625
+
1626
+ 4.9.ceil()
1627
+ # => 5
1628
+
1629
+ 4.2.ceil()
1630
+ # => 5
1631
+
1632
+ (-1.2).ceil()
1633
+ # => -1
1634
+
1635
+ @name ceil
1636
+ @methodOf Number#
1637
+ @returns {Number} The number truncated to the nearest integer of greater than or equal value.
1638
+ */
1639
+
1640
+ Number.prototype.ceil = function() {
1641
+ return Math.ceil(this);
1642
+ };
1643
+
1644
+ /**
1645
+ Returns the mathematical floor of this number.
1646
+
1647
+ 4.9.floor()
1648
+ # => 4
1649
+
1650
+ 4.2.floor()
1651
+ # => 4
1652
+
1653
+ (-1.2).floor()
1654
+ # => -2
1655
+
1656
+ @name floor
1657
+ @methodOf Number#
1658
+ @returns {Number} The number truncated to the nearest integer of less than or equal value.
1659
+ */
1660
+
1661
+ Number.prototype.floor = function() {
1662
+ return Math.floor(this);
1663
+ };
1664
+
1665
+ /**
1666
+ Returns this number rounded to the nearest integer.
1667
+
1668
+ 4.5.round()
1669
+ # => 5
1670
+
1671
+ 4.4.round()
1672
+ # => 4
1673
+
1674
+ @name round
1675
+ @methodOf Number#
1676
+ @returns {Number} The number rounded to the nearest integer.
1677
+ */
1678
+
1679
+ Number.prototype.round = function() {
1680
+ return Math.round(this);
1681
+ };
1682
+
1683
+ /**
1684
+ Get a bunch of points equally spaced around the unit circle.
1685
+
1686
+ 4.circularPoints (p) ->
1687
+
1688
+ # p gets Point(1, 0), Point(0, 1), Point(-1, 0), Point(0, -1)
1689
+
1690
+ @name circularPoint
1691
+ @methodOf Number#
1692
+ */
1693
+
1694
+ Number.prototype.circularPoints = function(block) {
1695
+ var n;
1696
+ n = this;
1697
+ return n.times(function(i) {
1698
+ return block(Point.fromAngle((i / n).turns), i);
1699
+ });
1700
+ };
1701
+
1702
+ /**
1703
+ Returns a number whose value is limited to the given range.
1704
+
1705
+ # limit the output of this computation to between 0 and 255
1706
+ (2 * 255).clamp(0, 255)
1707
+ # => 255
1708
+
1709
+ @name clamp
1710
+ @methodOf Number#
1711
+ @param {Number} min The lower boundary of the output range
1712
+ @param {Number} max The upper boundary of the output range
1713
+ @returns {Number} A number in the range [min, max]
1714
+ */
1715
+
1716
+ Number.prototype.clamp = function(min, max) {
1717
+ if ((min != null) && (max != null)) {
1718
+ return Math.min(Math.max(this, min), max);
1719
+ } else if (min != null) {
1720
+ return Math.max(this, min);
1721
+ } else if (max != null) {
1722
+ return Math.min(this, max);
1723
+ } else {
1724
+ return this;
1725
+ }
1726
+ };
1727
+
1728
+ /**
1729
+ A mod method useful for array wrapping. The range of the function is
1730
+ constrained to remain in bounds of array indices.
1731
+
1732
+ (-1).mod(5)
1733
+ # => 4
1734
+
1735
+ @name mod
1736
+ @methodOf Number#
1737
+ @param {Number} base
1738
+ @returns {Number} An integer between 0 and (base - 1) if base is positive.
1739
+ */
1740
+
1741
+ Number.prototype.mod = function(base) {
1742
+ var result;
1743
+ result = this % base;
1744
+ if (result < 0 && base > 0) result += base;
1745
+ return result;
1746
+ };
1747
+
1748
+ /**
1749
+ Get the sign of this number as an integer (1, -1, or 0).
1750
+
1751
+ (-5).sign()
1752
+ # => -1
1753
+
1754
+ 0.sign()
1755
+ # => 0
1756
+
1757
+ 5.sign()
1758
+ # => 1
1759
+
1760
+ @name sign
1761
+ @methodOf Number#
1762
+ @returns {Number} The sign of this number, 0 if the number is 0.
1763
+ */
1764
+
1765
+ Number.prototype.sign = function() {
1766
+ if (this > 0) {
1767
+ return 1;
1768
+ } else if (this < 0) {
1769
+ return -1;
1770
+ } else {
1771
+ return 0;
1772
+ }
1773
+ };
1774
+
1775
+ /**
1776
+ Returns true if this number is even (evenly divisible by 2).
1777
+
1778
+ 2.even()
1779
+ # => true
1780
+
1781
+ 3.even()
1782
+ # => false
1783
+
1784
+ 0.even()
1785
+ # => true
1786
+
1787
+ @name even
1788
+ @methodOf Number#
1789
+ @returns {Boolean} true if this number is an even integer, false otherwise.
1790
+ */
1791
+
1792
+ Number.prototype.even = function() {
1793
+ return this % 2 === 0;
1794
+ };
1795
+
1796
+ /**
1797
+ Returns true if this number is odd (has remainder of 1 when divided by 2).
1798
+
1799
+ 2.odd()
1800
+ # => false
1801
+
1802
+ 3.odd()
1803
+ # => true
1804
+
1805
+ 0.odd()
1806
+ # => false
1807
+
1808
+ @name odd
1809
+ @methodOf Number#
1810
+ @returns {Boolean} true if this number is an odd integer, false otherwise.
1811
+ */
1812
+
1813
+ Number.prototype.odd = function() {
1814
+ if (this > 0) {
1815
+ return this % 2 === 1;
1816
+ } else {
1817
+ return this % 2 === -1;
1818
+ }
1819
+ };
1820
+
1821
+ /**
1822
+ Calls iterator the specified number of times, passing in the number of the
1823
+ current iteration as a parameter: 0 on first call, 1 on the second call, etc.
1824
+
1825
+ output = []
1826
+
1827
+ 5.times (n) ->
1828
+ output.push(n)
1829
+
1830
+ output
1831
+ # => [0, 1, 2, 3, 4]
1832
+
1833
+ @name times
1834
+ @methodOf Number#
1835
+ @param {Function} iterator The iterator takes a single parameter, the number of the current iteration.
1836
+ @param {Object} [context] The optional context parameter specifies an object to treat as <code>this</code> in the iterator block.
1837
+ @returns {Number} The number of times the iterator was called.
1838
+ */
1839
+
1840
+ Number.prototype.times = function(iterator, context) {
1841
+ var i;
1842
+ i = -1;
1843
+ while (++i < this) {
1844
+ iterator.call(context, i);
1845
+ }
1846
+ return i;
1847
+ };
1848
+
1849
+ /**
1850
+ Returns the the nearest grid resolution less than or equal to the number.
1851
+
1852
+ 7.snap(8)
1853
+ # => 0
1854
+
1855
+ 4.snap(8)
1856
+ # => 0
1857
+
1858
+ 12.snap(8)
1859
+ # => 8
1860
+
1861
+ @name snap
1862
+ @methodOf Number#
1863
+ @param {Number} resolution The grid resolution to snap to.
1864
+ @returns {Number} The nearest multiple of resolution lower than the number.
1865
+ */
1866
+
1867
+ Number.prototype.snap = function(resolution) {
1868
+ var n;
1869
+ n = this / resolution;
1870
+ 1 / 1;
1871
+ return n.floor() * resolution;
1872
+ };
1873
+
1874
+ /**
1875
+ In number theory, integer factorization or prime factorization is the
1876
+ breaking down of a composite number into smaller non-trivial divisors,
1877
+ which when multiplied together equal the original integer.
1878
+
1879
+ Floors the number for purposes of factorization.
1880
+
1881
+ 60.primeFactors()
1882
+ # => [2, 2, 3, 5]
1883
+
1884
+ 37.primeFactors()
1885
+ # => [37]
1886
+
1887
+ @name primeFactors
1888
+ @methodOf Number#
1889
+ @returns {Array} An array containing the factorization of this number.
1890
+ */
1891
+
1892
+ Number.prototype.primeFactors = function() {
1893
+ var factors, i, iSquared, n;
1894
+ factors = [];
1895
+ n = Math.floor(this);
1896
+ if (n === 0) return;
1897
+ if (n < 0) {
1898
+ factors.push(-1);
1899
+ n /= -1;
1900
+ }
1901
+ i = 2;
1902
+ iSquared = i * i;
1903
+ while (iSquared < n) {
1904
+ while ((n % i) === 0) {
1905
+ factors.push(i);
1906
+ n /= i;
1907
+ }
1908
+ i += 1;
1909
+ iSquared = i * i;
1910
+ }
1911
+ if (n !== 1) factors.push(n);
1912
+ return factors;
1913
+ };
1914
+
1915
+ /**
1916
+ Returns the two character hexidecimal
1917
+ representation of numbers 0 through 255.
1918
+
1919
+ 255.toColorPart()
1920
+ # => "ff"
1921
+
1922
+ 0.toColorPart()
1923
+ # => "00"
1924
+
1925
+ 200.toColorPart()
1926
+ # => "c8"
1927
+
1928
+ @name toColorPart
1929
+ @methodOf Number#
1930
+ @returns {String} Hexidecimal representation of the number
1931
+ */
1932
+
1933
+ Number.prototype.toColorPart = function() {
1934
+ var s;
1935
+ s = parseInt(this.clamp(0, 255), 10).toString(16);
1936
+ if (s.length === 1) s = '0' + s;
1937
+ return s;
1938
+ };
1939
+
1940
+ /**
1941
+ Returns a number that is maxDelta closer to target.
1942
+
1943
+ 255.approach(0, 5)
1944
+ # => 250
1945
+
1946
+ 5.approach(0, 10)
1947
+ # => 0
1948
+
1949
+ @name approach
1950
+ @methodOf Number#
1951
+ @returns {Number} A number maxDelta toward target
1952
+ */
1953
+
1954
+ Number.prototype.approach = function(target, maxDelta) {
1955
+ return (target - this).clamp(-maxDelta, maxDelta) + this;
1956
+ };
1957
+
1958
+ /**
1959
+ Returns a number that is closer to the target by the ratio.
1960
+
1961
+ 255.approachByRatio(0, 0.1)
1962
+ # => 229.5
1963
+
1964
+ @name approachByRatio
1965
+ @methodOf Number#
1966
+ @returns {Number} A number toward target by the ratio
1967
+ */
1968
+
1969
+ Number.prototype.approachByRatio = function(target, ratio) {
1970
+ return this.approach(target, this * ratio);
1971
+ };
1972
+
1973
+ /**
1974
+ Returns a number that is closer to the target angle by the delta.
1975
+
1976
+ Math.PI.approachRotation(0, Math.PI/4)
1977
+ # => 2.356194490192345 # this is (3/4) * Math.PI, which is (1/4) * Math.PI closer to 0 from Math.PI
1978
+
1979
+ @name approachRotation
1980
+ @methodOf Number#
1981
+ @returns {Number} A number toward the target angle by maxDelta
1982
+ */
1983
+
1984
+ Number.prototype.approachRotation = function(target, maxDelta) {
1985
+ while (target > this + Math.PI) {
1986
+ target -= Math.TAU;
1987
+ }
1988
+ while (target < this - Math.PI) {
1989
+ target += Math.TAU;
1990
+ }
1991
+ return (target - this).clamp(-maxDelta, maxDelta) + this;
1992
+ };
1993
+
1994
+ /**
1995
+ Constrains a rotation to between -PI and PI.
1996
+
1997
+ (9/4 * Math.PI).constrainRotation()
1998
+ # => 0.7853981633974483 # this is (1/4) * Math.PI
1999
+
2000
+ @name constrainRotation
2001
+ @methodOf Number#
2002
+ @returns {Number} This number constrained between -PI and PI.
2003
+ */
2004
+
2005
+ Number.prototype.constrainRotation = function() {
2006
+ var target;
2007
+ target = this;
2008
+ while (target > Math.PI) {
2009
+ target -= Math.TAU;
2010
+ }
2011
+ while (target < -Math.PI) {
2012
+ target += Math.TAU;
2013
+ }
2014
+ return target;
2015
+ };
2016
+
2017
+ Number.prototype.truncate = function() {
2018
+ if (this > 0) {
2019
+ return Math.floor(this);
2020
+ } else if (this < 0) {
2021
+ return Math.ceil(this);
2022
+ } else {
2023
+ return this;
2024
+ }
2025
+ };
2026
+
2027
+ /**
2028
+ The mathematical d operator. Useful for simulating dice rolls.
2029
+
2030
+ @name d
2031
+ @methodOf Number#
2032
+ @returns {Number} The sum of rolling <code>this</code> many <code>sides</code>-sided dice
2033
+ */
2034
+
2035
+ Number.prototype.d = function(sides) {
2036
+ var sum;
2037
+ sum = 0;
2038
+ this.times(function() {
2039
+ return sum += rand(sides) + 1;
2040
+ });
2041
+ return sum;
2042
+ };
2043
+
2044
+ /**
2045
+ Utility method to convert a number to a duration of seconds.
2046
+
2047
+ 3.seconds
2048
+ # => 3000
2049
+
2050
+ setTimout doSometing, 3.seconds
2051
+
2052
+ @name seconds
2053
+ @propertyOf Number#
2054
+ @returns {Number} This number as a duration of seconds
2055
+ */
2056
+
2057
+ if (!5..seconds) {
2058
+ Object.defineProperty(Number.prototype, 'seconds', {
2059
+ get: function() {
2060
+ return this * 1000;
2061
+ }
2062
+ });
2063
+ }
2064
+
2065
+ if (!1..second) {
2066
+ Object.defineProperty(Number.prototype, 'second', {
2067
+ get: function() {
2068
+ return this * 1000;
2069
+ }
2070
+ });
2071
+ }
2072
+
2073
+ /**
2074
+ Utility method to convert a number to an amount of rotations.
2075
+
2076
+ 0.5.rotations
2077
+ # => 3.141592653589793
2078
+
2079
+ I.rotation = 0.25.rotations
2080
+
2081
+ @name rotations
2082
+ @propertyOf Number#
2083
+ @returns {Number} This number as an amount of rotations
2084
+ */
2085
+
2086
+ if (!5..rotations) {
2087
+ Object.defineProperty(Number.prototype, 'rotations', {
2088
+ get: function() {
2089
+ return this * Math.TAU;
2090
+ }
2091
+ });
2092
+ }
2093
+
2094
+ if (!1..rotation) {
2095
+ Object.defineProperty(Number.prototype, 'rotation', {
2096
+ get: function() {
2097
+ return this * Math.TAU;
2098
+ }
2099
+ });
2100
+ }
2101
+
2102
+ /**
2103
+ Utility method to convert a number to an amount of rotations.
2104
+
2105
+ 0.5.turns
2106
+ # => 3.141592653589793
2107
+
2108
+ I.rotation = 0.25.turns
2109
+
2110
+ 1.turn # => Math.TAU (aka 2 * Math.PI)
2111
+
2112
+ @name turns
2113
+ @propertyOf Number#
2114
+ @returns {Number} This number as an amount of rotation.
2115
+ 1 turn is one complete rotation.
2116
+ */
2117
+
2118
+ if (!5..turns) {
2119
+ Object.defineProperty(Number.prototype, 'turns', {
2120
+ get: function() {
2121
+ return this * Math.TAU;
2122
+ }
2123
+ });
2124
+ }
2125
+
2126
+ if (!1..turn) {
2127
+ Object.defineProperty(Number.prototype, 'turn', {
2128
+ get: function() {
2129
+ return this * Math.TAU;
2130
+ }
2131
+ });
2132
+ }
2133
+
2134
+ /**
2135
+ Utility method to convert a number to an amount of degrees.
2136
+
2137
+ 180.degrees
2138
+ # => 3.141592653589793
2139
+
2140
+ I.rotation = 90.degrees
2141
+
2142
+ @name degrees
2143
+ @propertyOf Number#
2144
+ @returns {Number} This number as an amount of degrees
2145
+ */
2146
+
2147
+ if (!2..degrees) {
2148
+ Object.defineProperty(Number.prototype, 'degrees', {
2149
+ get: function() {
2150
+ return this * Math.TAU / 360;
2151
+ }
2152
+ });
2153
+ }
2154
+
2155
+ if (!1..degree) {
2156
+ Object.defineProperty(Number.prototype, 'degree', {
2157
+ get: function() {
2158
+ return this * Math.TAU / 360;
2159
+ }
2160
+ });
2161
+ }
2162
+
2163
+ /**
2164
+ The mathematical circle constant of 1 turn.
2165
+
2166
+ @name TAU
2167
+ @fieldOf Math
2168
+ */
2169
+
2170
+ Math.TAU = 2 * Math.PI;
2171
+
2172
+ var __slice = Array.prototype.slice;
2173
+
2174
+ (function() {
2175
+ /**
2176
+ Create a new point with given x and y coordinates. If no arguments are given
2177
+ defaults to (0, 0).
2178
+
2179
+ point = Point()
2180
+
2181
+ p.x
2182
+ # => 0
2183
+
2184
+ p.y
2185
+ # => 0
2186
+
2187
+ point = Point(-2, 5)
2188
+
2189
+ p.x
2190
+ # => -2
2191
+
2192
+ p.y
2193
+ # => 5
2194
+
2195
+ @name Point
2196
+ @param {Number} [x]
2197
+ @param {Number} [y]
2198
+ @constructor
2199
+ */
2200
+ var Point;
2201
+ Point = function(x, y) {
2202
+ var _ref;
2203
+ if (Object.isObject(x)) _ref = x, x = _ref.x, y = _ref.y;
2204
+ return {
2205
+ __proto__: Point.prototype,
2206
+ /**
2207
+ The x coordinate of this point.
2208
+ @name x
2209
+ @fieldOf Point#
2210
+ */
2211
+ x: x || 0,
2212
+ /**
2213
+ The y coordinate of this point.
2214
+ @name y
2215
+ @fieldOf Point#
2216
+ */
2217
+ y: y || 0
2218
+ };
2219
+ };
2220
+ Point.prototype = {
2221
+ /**
2222
+ Constrain the magnitude of a vector.
2223
+
2224
+ @name clamp
2225
+ @methodOf Point#
2226
+ @param {Number} n Maximum value for magnitude.
2227
+ @returns {Point} A new point whose magnitude has been clamped to the given value.
2228
+ */
2229
+ clamp: function(n) {
2230
+ return this.copy().clamp$(n);
2231
+ },
2232
+ clamp$: function(n) {
2233
+ if (this.magnitude() > n) {
2234
+ return this.norm$(n);
2235
+ } else {
2236
+ return this;
2237
+ }
2238
+ },
2239
+ /**
2240
+ Creates a copy of this point.
2241
+
2242
+ @name copy
2243
+ @methodOf Point#
2244
+ @returns {Point} A new point with the same x and y value as this point.
2245
+
2246
+ point = Point(1, 1)
2247
+ pointCopy = point.copy()
2248
+
2249
+ point.equal(pointCopy)
2250
+ # => true
2251
+
2252
+ point == pointCopy
2253
+ # => false
2254
+ */
2255
+ copy: function() {
2256
+ return Point(this.x, this.y);
2257
+ },
2258
+ /**
2259
+ Adds a point to this one and returns the new point. You may
2260
+ also use a two argument call like <code>point.add(x, y)</code>
2261
+ to add x and y values without a second point object.
2262
+
2263
+ point = Point(2, 3).add(Point(3, 4))
2264
+
2265
+ point.x
2266
+ # => 5
2267
+
2268
+ point.y
2269
+ # => 7
2270
+
2271
+ anotherPoint = Point(2, 3).add(3, 4)
2272
+
2273
+ anotherPoint.x
2274
+ # => 5
2275
+
2276
+ anotherPoint.y
2277
+ # => 7
2278
+
2279
+ @name add
2280
+ @methodOf Point#
2281
+ @param {Point} other The point to add this point to.
2282
+ @returns {Point} A new point, the sum of both.
2283
+ */
2284
+ add: function(first, second) {
2285
+ return this.copy().add$(first, second);
2286
+ },
2287
+ /**
2288
+ Adds a point to this one, returning a modified point. You may
2289
+ also use a two argument call like <code>point.add(x, y)</code>
2290
+ to add x and y values without a second point object.
2291
+
2292
+ point = Point(2, 3)
2293
+
2294
+ point.x
2295
+ # => 2
2296
+
2297
+ point.y
2298
+ # => 3
2299
+
2300
+ point.add$(Point(3, 4))
2301
+
2302
+ point.x
2303
+ # => 5
2304
+
2305
+ point.y
2306
+ # => 7
2307
+
2308
+ anotherPoint = Point(2, 3)
2309
+ anotherPoint.add$(3, 4)
2310
+
2311
+ anotherPoint.x
2312
+ # => 5
2313
+
2314
+ anotherPoint.y
2315
+ # => 7
2316
+
2317
+ @name add$
2318
+ @methodOf Point#
2319
+ @param {Point} other The point to add this point to.
2320
+ @returns {Point} The sum of both points.
2321
+ */
2322
+ add$: function(first, second) {
2323
+ if (second != null) {
2324
+ this.x += first;
2325
+ this.y += second;
2326
+ } else {
2327
+ this.x += first.x;
2328
+ this.y += first.y;
2329
+ }
2330
+ return this;
2331
+ },
2332
+ /**
2333
+ Subtracts a point to this one and returns the new point.
2334
+
2335
+ point = Point(1, 2).subtract(Point(2, 0))
2336
+
2337
+ point.x
2338
+ # => -1
2339
+
2340
+ point.y
2341
+ # => 2
2342
+
2343
+ anotherPoint = Point(1, 2).subtract(2, 0)
2344
+
2345
+ anotherPoint.x
2346
+ # => -1
2347
+
2348
+ anotherPoint.y
2349
+ # => 2
2350
+
2351
+ @name subtract
2352
+ @methodOf Point#
2353
+ @param {Point} other The point to subtract from this point.
2354
+ @returns {Point} A new point, this - other.
2355
+ */
2356
+ subtract: function(first, second) {
2357
+ return this.copy().subtract$(first, second);
2358
+ },
2359
+ /**
2360
+ Subtracts a point to this one and returns the new point.
2361
+
2362
+ point = Point(1, 2)
2363
+
2364
+ point.x
2365
+ # => 1
2366
+
2367
+ point.y
2368
+ # => 2
2369
+
2370
+ point.subtract$(Point(2, 0))
2371
+
2372
+ point.x
2373
+ # => -1
2374
+
2375
+ point.y
2376
+ # => 2
2377
+
2378
+ anotherPoint = Point(1, 2)
2379
+ anotherPoint.subtract$(2, 0)
2380
+
2381
+ anotherPoint.x
2382
+ # => -1
2383
+
2384
+ anotherPoint.y
2385
+ # => 2
2386
+
2387
+ @name subtract$
2388
+ @methodOf Point#
2389
+ @param {Point} other The point to subtract from this point.
2390
+ @returns {Point} The difference of the two points.
2391
+ */
2392
+ subtract$: function(first, second) {
2393
+ if (second != null) {
2394
+ this.x -= first;
2395
+ this.y -= second;
2396
+ } else {
2397
+ this.x -= first.x;
2398
+ this.y -= first.y;
2399
+ }
2400
+ return this;
2401
+ },
2402
+ /**
2403
+ Scale this Point (Vector) by a constant amount.
2404
+
2405
+ point = Point(5, 6).scale(2)
2406
+
2407
+ point.x
2408
+ # => 10
2409
+
2410
+ point.y
2411
+ # => 12
2412
+
2413
+ @name scale
2414
+ @methodOf Point#
2415
+ @param {Number} scalar The amount to scale this point by.
2416
+ @returns {Point} A new point, this * scalar.
2417
+ */
2418
+ scale: function(scalar) {
2419
+ return this.copy().scale$(scalar);
2420
+ },
2421
+ /**
2422
+ Scale this Point (Vector) by a constant amount. Modifies the point in place.
2423
+
2424
+ point = Point(5, 6)
2425
+
2426
+ point.x
2427
+ # => 5
2428
+
2429
+ point.y
2430
+ # => 6
2431
+
2432
+ point.scale$(2)
2433
+
2434
+ point.x
2435
+ # => 10
2436
+
2437
+ point.y
2438
+ # => 12
2439
+
2440
+ @name scale$
2441
+ @methodOf Point#
2442
+ @param {Number} scalar The amount to scale this point by.
2443
+ @returns {Point} this * scalar.
2444
+ */
2445
+ scale$: function(scalar) {
2446
+ this.x *= scalar;
2447
+ this.y *= scalar;
2448
+ return this;
2449
+ },
2450
+ /**
2451
+ The norm of a vector is the unit vector pointing in the same direction. This method
2452
+ treats the point as though it is a vector from the origin to (x, y).
2453
+
2454
+ point = Point(2, 3).norm()
2455
+
2456
+ point.x
2457
+ # => 0.5547001962252291
2458
+
2459
+ point.y
2460
+ # => 0.8320502943378437
2461
+
2462
+ anotherPoint = Point(2, 3).norm(2)
2463
+
2464
+ anotherPoint.x
2465
+ # => 1.1094003924504583
2466
+
2467
+ anotherPoint.y
2468
+ # => 1.6641005886756874
2469
+
2470
+ @name norm
2471
+ @methodOf Point#
2472
+ @returns {Point} The unit vector pointing in the same direction as this vector.
2473
+ */
2474
+ norm: function(length) {
2475
+ if (length == null) length = 1.0;
2476
+ return this.copy().norm$(length);
2477
+ },
2478
+ /**
2479
+ The norm of a vector is the unit vector pointing in the same direction. This method
2480
+ treats the point as though it is a vector from the origin to (x, y). Modifies the point in place.
2481
+
2482
+ point = Point(2, 3).norm$()
2483
+
2484
+ point.x
2485
+ # => 0.5547001962252291
2486
+
2487
+ point.y
2488
+ # => 0.8320502943378437
2489
+
2490
+ anotherPoint = Point(2, 3).norm$(2)
2491
+
2492
+ anotherPoint.x
2493
+ # => 1.1094003924504583
2494
+
2495
+ anotherPoint.y
2496
+ # => 1.6641005886756874
2497
+
2498
+ @name norm$
2499
+ @methodOf Point#
2500
+ @returns {Point} The unit vector pointing in the same direction as this vector.
2501
+ */
2502
+ norm$: function(length) {
2503
+ var m;
2504
+ if (length == null) length = 1.0;
2505
+ if (m = this.length()) {
2506
+ return this.scale$(length / m);
2507
+ } else {
2508
+ return this;
2509
+ }
2510
+ },
2511
+ /**
2512
+ Floor the x and y values, returning a new point.
2513
+
2514
+ point = Point(3.4, 5.8).floor()
2515
+
2516
+ point.x
2517
+ # => 3
2518
+
2519
+ point.y
2520
+ # => 5
2521
+
2522
+ @name floor
2523
+ @methodOf Point#
2524
+ @returns {Point} A new point, with x and y values each floored to the largest previous integer.
2525
+ */
2526
+ floor: function() {
2527
+ return this.copy().floor$();
2528
+ },
2529
+ /**
2530
+ Floor the x and y values, returning a modified point.
2531
+
2532
+ point = Point(3.4, 5.8)
2533
+ point.floor$()
2534
+
2535
+ point.x
2536
+ # => 3
2537
+
2538
+ point.y
2539
+ # => 5
2540
+
2541
+ @name floor$
2542
+ @methodOf Point#
2543
+ @returns {Point} A modified point, with x and y values each floored to the largest previous integer.
2544
+ */
2545
+ floor$: function() {
2546
+ this.x = this.x.floor();
2547
+ this.y = this.y.floor();
2548
+ return this;
2549
+ },
2550
+ /**
2551
+ Determine whether this point is equal to another point.
2552
+
2553
+ pointA = Point(2, 3)
2554
+ pointB = Point(2, 3)
2555
+ pointC = Point(4, 5)
2556
+
2557
+ pointA.equal(pointB)
2558
+ # => true
2559
+
2560
+ pointA.equal(pointC)
2561
+ # => false
2562
+
2563
+ @name equal
2564
+ @methodOf Point#
2565
+ @param {Point} other The point to check for equality.
2566
+ @returns {Boolean} true if the other point has the same x, y coordinates, false otherwise.
2567
+ */
2568
+ equal: function(other) {
2569
+ return this.x === other.x && this.y === other.y;
2570
+ },
2571
+ /**
2572
+ Computed the length of this point as though it were a vector from (0,0) to (x,y).
2573
+
2574
+ point = Point(5, 7)
2575
+
2576
+ point.length()
2577
+ # => 8.602325267042627
2578
+
2579
+ @name length
2580
+ @methodOf Point#
2581
+ @returns {Number} The length of the vector from the origin to this point.
2582
+ */
2583
+ length: function() {
2584
+ return Math.sqrt(this.dot(this));
2585
+ },
2586
+ /**
2587
+ Calculate the magnitude of this Point (Vector).
2588
+
2589
+ point = Point(5, 7)
2590
+
2591
+ point.magnitude()
2592
+ # => 8.602325267042627
2593
+
2594
+ @name magnitude
2595
+ @methodOf Point#
2596
+ @returns {Number} The magnitude of this point as if it were a vector from (0, 0) -> (x, y).
2597
+ */
2598
+ magnitude: function() {
2599
+ return this.length();
2600
+ },
2601
+ /**
2602
+ Returns the direction in radians of this point from the origin.
2603
+
2604
+ point = Point(0, 1)
2605
+
2606
+ point.direction()
2607
+ # => 1.5707963267948966 # Math.PI / 2
2608
+
2609
+ @name direction
2610
+ @methodOf Point#
2611
+ @returns {Number} The direction in radians of this point from the origin
2612
+ */
2613
+ direction: function() {
2614
+ return Math.atan2(this.y, this.x);
2615
+ },
2616
+ /**
2617
+ Calculate the dot product of this point and another point (Vector).
2618
+ @name dot
2619
+ @methodOf Point#
2620
+ @param {Point} other The point to dot with this point.
2621
+ @returns {Number} The dot product of this point dot other as a scalar value.
2622
+ */
2623
+ dot: function(other) {
2624
+ return this.x * other.x + this.y * other.y;
2625
+ },
2626
+ /**
2627
+ Calculate the cross product of this point and another point (Vector).
2628
+ Usually cross products are thought of as only applying to three dimensional vectors,
2629
+ but z can be treated as zero. The result of this method is interpreted as the magnitude
2630
+ of the vector result of the cross product between [x1, y1, 0] x [x2, y2, 0]
2631
+ perpendicular to the xy plane.
2632
+
2633
+ @name cross
2634
+ @methodOf Point#
2635
+ @param {Point} other The point to cross with this point.
2636
+ @returns {Number} The cross product of this point with the other point as scalar value.
2637
+ */
2638
+ cross: function(other) {
2639
+ return this.x * other.y - other.x * this.y;
2640
+ },
2641
+ /**
2642
+ Compute the Euclidean distance between this point and another point.
2643
+
2644
+ pointA = Point(2, 3)
2645
+ pointB = Point(9, 2)
2646
+
2647
+ pointA.distance(pointB)
2648
+ # => 7.0710678118654755 # Math.sqrt(50)
2649
+
2650
+ @name distance
2651
+ @methodOf Point#
2652
+ @param {Point} other The point to compute the distance to.
2653
+ @returns {Number} The distance between this point and another point.
2654
+ */
2655
+ distance: function(other) {
2656
+ return Point.distance(this, other);
2657
+ },
2658
+ /**
2659
+ @name toString
2660
+ @methodOf Point#
2661
+ @returns {String} A string representation of this point.
2662
+ */
2663
+ toString: function() {
2664
+ return "Point(" + this.x + ", " + this.y + ")";
2665
+ },
2666
+ abs: function() {
2667
+ return Point({
2668
+ x: this.x.abs(),
2669
+ y: this.y.abs()
2670
+ });
2671
+ },
2672
+ snap: function(n) {
2673
+ return Point({
2674
+ x: this.x.snap(n),
2675
+ y: this.y.snap(n)
2676
+ });
2677
+ },
2678
+ angle: function() {
2679
+ return Math.atan2(this.y, this.x);
2680
+ }
2681
+ };
2682
+ /**
2683
+ Compute the Euclidean distance between two points.
2684
+
2685
+ pointA = Point(2, 3)
2686
+ pointB = Point(9, 2)
2687
+
2688
+ Point.distance(pointA, pointB)
2689
+ # => 7.0710678118654755 # Math.sqrt(50)
2690
+
2691
+ @name distance
2692
+ @fieldOf Point
2693
+ @param {Point} p1
2694
+ @param {Point} p2
2695
+ @returns {Number} The Euclidean distance between two points.
2696
+ */
2697
+ Point.distance = function(p1, p2) {
2698
+ return Math.sqrt(Point.distanceSquared(p1, p2));
2699
+ };
2700
+ /**
2701
+ pointA = Point(2, 3)
2702
+ pointB = Point(9, 2)
2703
+
2704
+ Point.distanceSquared(pointA, pointB)
2705
+ # => 50
2706
+
2707
+ @name distanceSquared
2708
+ @fieldOf Point
2709
+ @param {Point} p1
2710
+ @param {Point} p2
2711
+ @returns {Number} The square of the Euclidean distance between two points.
2712
+ */
2713
+ Point.distanceSquared = function(p1, p2) {
2714
+ return Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2);
2715
+ };
2716
+ /**
2717
+ @name interpolate
2718
+ @fieldOf Point
2719
+
2720
+ @param {Point} p1
2721
+ @param {Point} p2
2722
+ @param {Number} t
2723
+ @returns {Point} A point along the path from p1 to p2
2724
+ */
2725
+ Point.interpolate = function(p1, p2, t) {
2726
+ return p2.subtract(p1).scale(t).add(p1);
2727
+ };
2728
+ /**
2729
+ Construct a point on the unit circle for the given angle.
2730
+
2731
+ point = Point.fromAngle(Math.PI / 2)
2732
+
2733
+ point.x
2734
+ # => 0
2735
+
2736
+ point.y
2737
+ # => 1
2738
+
2739
+ @name fromAngle
2740
+ @fieldOf Point
2741
+ @param {Number} angle The angle in radians
2742
+ @returns {Point} The point on the unit circle.
2743
+ */
2744
+ Point.fromAngle = function(angle) {
2745
+ return Point(Math.cos(angle), Math.sin(angle));
2746
+ };
2747
+ /**
2748
+ If you have two dudes, one standing at point p1, and the other
2749
+ standing at point p2, then this method will return the direction
2750
+ that the dude standing at p1 will need to face to look at p2.
2751
+
2752
+ p1 = Point(0, 0)
2753
+ p2 = Point(7, 3)
2754
+
2755
+ Point.direction(p1, p2)
2756
+ # => 0.40489178628508343
2757
+
2758
+ @name direction
2759
+ @fieldOf Point
2760
+ @param {Point} p1 The starting point.
2761
+ @param {Point} p2 The ending point.
2762
+ @returns {Number} The direction from p1 to p2 in radians.
2763
+ */
2764
+ Point.direction = function(p1, p2) {
2765
+ return Math.atan2(p2.y - p1.y, p2.x - p1.x);
2766
+ };
2767
+ /**
2768
+ The centroid of a set of points is their arithmetic mean.
2769
+
2770
+ @name centroid
2771
+ @methodOf Point
2772
+ @param points... The points to find the centroid of.
2773
+ */
2774
+ Point.centroid = function() {
2775
+ var points;
2776
+ points = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2777
+ return points.inject(Point(0, 0), function(sumPoint, point) {
2778
+ return sumPoint.add(point);
2779
+ }).scale(1 / points.length);
2780
+ };
2781
+ /**
2782
+ Generate a random point on the unit circle.
2783
+
2784
+ @returns {Point} A random point on the unit circle.
2785
+ */
2786
+ Point.random = function() {
2787
+ return Point.fromAngle(Random.angle());
2788
+ };
2789
+ /**
2790
+ @name ZERO
2791
+ @fieldOf Point
2792
+ @returns {Point} The point (0, 0)
2793
+ */
2794
+ Point.ZERO = Point(0, 0);
2795
+ /**
2796
+ @name LEFT
2797
+ @fieldOf Point
2798
+ @returns {Point} The point (-1, 0)
2799
+ */
2800
+ Point.LEFT = Point(-1, 0);
2801
+ /**
2802
+ @name RIGHT
2803
+ @fieldOf Point
2804
+ @returns {Point} The point (1, 0)
2805
+ */
2806
+ Point.RIGHT = Point(1, 0);
2807
+ /**
2808
+ @name UP
2809
+ @fieldOf Point
2810
+ @returns {Point} The point (0, -1)
2811
+ */
2812
+ Point.UP = Point(0, -1);
2813
+ /**
2814
+ @name DOWN
2815
+ @fieldOf Point
2816
+ @returns {Point} The point (0, 1)
2817
+ */
2818
+ Point.DOWN = Point(0, 1);
2819
+ if (Object.freeze) {
2820
+ Object.freeze(Point.ZERO);
2821
+ Object.freeze(Point.LEFT);
2822
+ Object.freeze(Point.RIGHT);
2823
+ Object.freeze(Point.UP);
2824
+ Object.freeze(Point.DOWN);
2825
+ }
2826
+ return (typeof exports !== "undefined" && exports !== null ? exports : this)["Point"] = Point;
2827
+ })();
2828
+
2829
+
2830
+ (function() {
2831
+ /**
2832
+ @name Random
2833
+ @namespace Some useful methods for generating random things.
2834
+ */ (typeof exports !== "undefined" && exports !== null ? exports : this)["Random"] = {
2835
+ /**
2836
+ Returns a random angle, uniformly distributed, between 0 and 2pi.
2837
+
2838
+ @name angle
2839
+ @methodOf Random
2840
+ @returns {Number} A random angle between 0 and 2pi
2841
+ */
2842
+ angle: function() {
2843
+ return rand() * Math.TAU;
2844
+ },
2845
+ /**
2846
+ Returns a random angle between the given angles.
2847
+
2848
+ @name angleBetween
2849
+ @methodOf Random
2850
+ @returns {Number} A random angle between the angles given.
2851
+ */
2852
+ angleBetween: function(min, max) {
2853
+ return rand() * (max - min) + min;
2854
+ },
2855
+ /**
2856
+ Returns a random color.
2857
+
2858
+ @name color
2859
+ @methodOf Random
2860
+ @returns {Color} A random color
2861
+ */
2862
+ color: function() {
2863
+ return Color.random();
2864
+ },
2865
+ /**
2866
+ Happens often.
2867
+
2868
+ @name often
2869
+ @methodOf Random
2870
+ */
2871
+ often: function() {
2872
+ return rand(3);
2873
+ },
2874
+ /**
2875
+ Happens sometimes.
2876
+
2877
+ @name sometimes
2878
+ @methodOf Random
2879
+ */
2880
+ sometimes: function() {
2881
+ return !rand(3);
2882
+ }
2883
+ };
2884
+ /**
2885
+ Returns random integers from [0, n) if n is given.
2886
+ Otherwise returns random float between 0 and 1.
2887
+
2888
+ @name rand
2889
+ @methodOf window
2890
+ @param {Number} n
2891
+ @returns {Number} A random integer from 0 to n - 1 if n is given. If n is not given, a random float between 0 and 1.
2892
+ */
2893
+ (typeof exports !== "undefined" && exports !== null ? exports : this)["rand"] = function(n) {
2894
+ if (n) {
2895
+ return Math.floor(n * Math.random());
2896
+ } else {
2897
+ return Math.random();
2898
+ }
2899
+ };
2900
+ /**
2901
+ Returns random float from [-n / 2, n / 2] if n is given.
2902
+ Otherwise returns random float between -0.5 and 0.5.
2903
+
2904
+ @name signedRand
2905
+ @methodOf window
2906
+ @param {Number} n
2907
+ @returns {Number} A random float from -n / 2 to n / 2 if n is given. If n is not given, a random float between -0.5 and 0.5.
2908
+ */
2909
+ return (typeof exports !== "undefined" && exports !== null ? exports : this)["signedRand"] = function(n) {
2910
+ if (n) {
2911
+ return (n * Math.random()) - (n / 2);
2912
+ } else {
2913
+ return Math.random() - 0.5;
2914
+ }
2915
+ };
2916
+ })();
2917
+
2918
+
2919
+ (function() {
2920
+ var Rectangle;
2921
+ Rectangle = function(_arg) {
2922
+ var height, width, x, y;
2923
+ x = _arg.x, y = _arg.y, width = _arg.width, height = _arg.height;
2924
+ return {
2925
+ __proto__: Rectangle.prototype,
2926
+ x: x || 0,
2927
+ y: y || 0,
2928
+ width: width || 0,
2929
+ height: height || 0
2930
+ };
2931
+ };
2932
+ Rectangle.prototype = {
2933
+ center: function() {
2934
+ return Point(this.x + this.width / 2, this.y + this.height / 2);
2935
+ },
2936
+ equal: function(other) {
2937
+ return this.x === other.x && this.y === other.y && this.width === other.width && this.height === other.height;
2938
+ }
2939
+ };
2940
+ Rectangle.prototype.__defineGetter__('left', function() {
2941
+ return this.x;
2942
+ });
2943
+ Rectangle.prototype.__defineGetter__('right', function() {
2944
+ return this.x + this.width;
2945
+ });
2946
+ Rectangle.prototype.__defineGetter__('top', function() {
2947
+ return this.y;
2948
+ });
2949
+ Rectangle.prototype.__defineGetter__('bottom', function() {
2950
+ return this.y + this.height;
2951
+ });
2952
+ return (typeof exports !== "undefined" && exports !== null ? exports : this)["Rectangle"] = Rectangle;
2953
+ })();
2954
+
2955
+ /**
2956
+ Returns true if this string only contains whitespace characters.
2957
+
2958
+ "".blank()
2959
+ # => true
2960
+
2961
+ "hello".blank()
2962
+ # => false
2963
+
2964
+ " ".blank()
2965
+ # => true
2966
+
2967
+ @name blank
2968
+ @methodOf String#
2969
+ @returns {Boolean} Whether or not this string is blank.
2970
+ */
2971
+ String.prototype.blank = function() {
2972
+ return /^\s*$/.test(this);
2973
+ };
2974
+
2975
+ /**
2976
+ Returns a new string that is a camelCase version.
2977
+
2978
+ "camel_case".camelize()
2979
+ "camel-case".camelize()
2980
+ "camel case".camelize()
2981
+
2982
+ # => "camelCase"
2983
+
2984
+ @name camelize
2985
+ @methodOf String#
2986
+ @returns {String} A new string. camelCase version of `this`.
2987
+ */
2988
+
2989
+ String.prototype.camelize = function() {
2990
+ return this.trim().replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) {
2991
+ if (chr) {
2992
+ return chr.toUpperCase();
2993
+ } else {
2994
+ return '';
2995
+ }
2996
+ });
2997
+ };
2998
+
2999
+ /**
3000
+ Returns a new string with the first letter capitalized and the rest lower cased.
3001
+
3002
+ "capital".capitalize()
3003
+ "cAPITAL".capitalize()
3004
+ "cApItAl".capitalize()
3005
+ "CAPITAL".capitalize()
3006
+
3007
+ # => "Capital"
3008
+
3009
+ @name capitalize
3010
+ @methodOf String#
3011
+ @returns {String} A new string. Capitalized version of `this`
3012
+ */
3013
+
3014
+ String.prototype.capitalize = function() {
3015
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
3016
+ };
3017
+
3018
+ /**
3019
+ Return the class or constant named in this string.
3020
+
3021
+
3022
+ "Constant".constantize()
3023
+ # => Constant
3024
+ # notice this isn't a string. Useful for calling methods on class with the same name as `this`.
3025
+
3026
+ @name constantize
3027
+ @methodOf String#
3028
+ @returns {Object} The class or constant named in this string.
3029
+ */
3030
+
3031
+ String.prototype.constantize = function() {
3032
+ var item, target, _i, _len, _ref;
3033
+ target = typeof exports !== "undefined" && exports !== null ? exports : window;
3034
+ _ref = this.split('.');
3035
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
3036
+ item = _ref[_i];
3037
+ target = target[item];
3038
+ }
3039
+ return target;
3040
+ };
3041
+
3042
+ /**
3043
+ Get the file extension of a string.
3044
+
3045
+ "README.md".extension() # => "md"
3046
+ "README".extension() # => ""
3047
+
3048
+ @name extension
3049
+ @methodOf String#
3050
+ @returns {String} File extension
3051
+ */
3052
+
3053
+ String.prototype.extension = function() {
3054
+ var extension, _ref;
3055
+ if (extension = (_ref = this.match(/\.([^\.]*)$/, '')) != null ? _ref.last() : void 0) {
3056
+ return extension;
3057
+ } else {
3058
+ return '';
3059
+ }
3060
+ };
3061
+
3062
+ /**
3063
+ Returns a new string that is a more human readable version.
3064
+
3065
+ "player_id".humanize()
3066
+ # => "Player"
3067
+
3068
+ "player_ammo".humanize()
3069
+ # => "Player ammo"
3070
+
3071
+ @name humanize
3072
+ @methodOf String#
3073
+ @returns {String} A new string. Replaces _id and _ with "" and capitalizes the word.
3074
+ */
3075
+
3076
+ String.prototype.humanize = function() {
3077
+ return this.replace(/_id$/, "").replace(/_/g, " ").capitalize();
3078
+ };
3079
+
3080
+ /**
3081
+ Returns true.
3082
+
3083
+ @name isString
3084
+ @methodOf String#
3085
+ @returns {Boolean} true
3086
+ */
3087
+
3088
+ String.prototype.isString = function() {
3089
+ return true;
3090
+ };
3091
+
3092
+ /**
3093
+ Parse this string as though it is JSON and return the object it represents. If it
3094
+ is not valid JSON returns the string itself.
3095
+
3096
+ # this is valid json, so an object is returned
3097
+ '{"a": 3}'.parse()
3098
+ # => {a: 3}
3099
+
3100
+ # double quoting instead isn't valid JSON so a string is returned
3101
+ "{'a': 3}".parse()
3102
+ # => "{'a': 3}"
3103
+
3104
+
3105
+ @name parse
3106
+ @methodOf String#
3107
+ @returns {Object} Returns an object from the JSON this string contains. If it is not valid JSON returns the string itself.
3108
+ */
3109
+
3110
+ String.prototype.parse = function() {
3111
+ try {
3112
+ return JSON.parse(this.toString());
3113
+ } catch (e) {
3114
+ return this.toString();
3115
+ }
3116
+ };
3117
+
3118
+ /**
3119
+ Returns true if this string starts with the given string.
3120
+
3121
+ @name startsWith
3122
+ @methodOf String#
3123
+ @param {String} str The string to check.
3124
+
3125
+ @returns {Boolean} True if this string starts with the given string, false otherwise.
3126
+ */
3127
+
3128
+ String.prototype.startsWith = function(str) {
3129
+ return this.lastIndexOf(str, 0) === 0;
3130
+ };
3131
+
3132
+ /**
3133
+ Returns a new string in Title Case.
3134
+
3135
+ "title-case".titleize()
3136
+ # => "Title Case"
3137
+
3138
+ "title case".titleize()
3139
+ # => "Title Case"
3140
+
3141
+ @name titleize
3142
+ @methodOf String#
3143
+ @returns {String} A new string. Title Cased.
3144
+ */
3145
+
3146
+ String.prototype.titleize = function() {
3147
+ return this.split(/[- ]/).map(function(word) {
3148
+ return word.capitalize();
3149
+ }).join(' ');
3150
+ };
3151
+
3152
+ /**
3153
+ Underscore a word, changing camelCased with under_scored.
3154
+
3155
+ "UNDERScore".underscore()
3156
+ # => "under_score"
3157
+
3158
+ "UNDER-SCORE".underscore()
3159
+ # => "under_score"
3160
+
3161
+ "UnDEr-SCorE".underscore()
3162
+ # => "un_d_er_s_cor_e"
3163
+
3164
+ @name underscore
3165
+ @methodOf String#
3166
+ @returns {String} A new string. Separated by _.
3167
+ */
3168
+
3169
+ String.prototype.underscore = function() {
3170
+ return this.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/-/g, '_').toLowerCase();
3171
+ };
3172
+
3173
+ /**
3174
+ Assumes the string is something like a file name and returns the
3175
+ contents of the string without the extension.
3176
+
3177
+ "neat.png".witouthExtension()
3178
+ # => "neat"
3179
+
3180
+ @name withoutExtension
3181
+ @methodOf String#
3182
+ @returns {String} A new string without the extension name.
3183
+ */
3184
+
3185
+ String.prototype.withoutExtension = function() {
3186
+ return this.replace(/\.[^\.]*$/, '');
3187
+ };
3188
+
3189
+ String.prototype.toInt = function(base) {
3190
+ if (base == null) base = 10;
3191
+ return parseInt(this, base);
3192
+ };
3193
+
3194
+ String.prototype.parseHex = function() {
3195
+ var alpha, hexString, i, rgb;
3196
+ hexString = this.replace(/#/, '');
3197
+ switch (hexString.length) {
3198
+ case 3:
3199
+ case 4:
3200
+ if (hexString.length === 4) {
3201
+ alpha = (parseInt(hexString.substr(3, 1), 16) * 0x11) / 255;
3202
+ } else {
3203
+ alpha = 1;
3204
+ }
3205
+ rgb = (function() {
3206
+ var _results;
3207
+ _results = [];
3208
+ for (i = 0; i <= 2; i++) {
3209
+ _results.push(parseInt(hexString.substr(i, 1), 16) * 0x11);
3210
+ }
3211
+ return _results;
3212
+ })();
3213
+ rgb.push(alpha);
3214
+ return rgb;
3215
+ case 6:
3216
+ case 8:
3217
+ if (hexString.length === 8) {
3218
+ alpha = parseInt(hexString.substr(6, 2), 16) / 255;
3219
+ } else {
3220
+ alpha = 1;
3221
+ }
3222
+ rgb = (function() {
3223
+ var _results;
3224
+ _results = [];
3225
+ for (i = 0; i <= 2; i++) {
3226
+ _results.push(parseInt(hexString.substr(2 * i, 2), 16));
3227
+ }
3228
+ return _results;
3229
+ })();
3230
+ rgb.push(alpha);
3231
+ return rgb;
3232
+ }
3233
+ };
3234
+
3235
+ /*!
3236
+ Math.uuid.js (v1.4)
3237
+ http://www.broofa.com
3238
+ mailto:robert@broofa.com
3239
+
3240
+ Copyright (c) 2010 Robert Kieffer
3241
+ Dual licensed under the MIT and GPL licenses.
3242
+ */
3243
+
3244
+ /**
3245
+ Generate a random uuid.
3246
+
3247
+ <code><pre>
3248
+ // No arguments - returns RFC4122, version 4 ID
3249
+ Math.uuid()
3250
+ => "92329D39-6F5C-4520-ABFC-AAB64544E172"
3251
+
3252
+ // One argument - returns ID of the specified length
3253
+ Math.uuid(15) // 15 character ID (default base=62)
3254
+ => "VcydxgltxrVZSTV"
3255
+
3256
+ // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
3257
+ Math.uuid(8, 2) // 8 character ID (base=2)
3258
+ => "01001010"
3259
+
3260
+ Math.uuid(8, 10) // 8 character ID (base=10)
3261
+ => "47473046"
3262
+
3263
+ Math.uuid(8, 16) // 8 character ID (base=16)
3264
+ => "098F4D35"
3265
+ </pre></code>
3266
+
3267
+ @name uuid
3268
+ @methodOf Math
3269
+ @param length The desired number of characters
3270
+ @param radix The number of allowable values for each character.
3271
+ */
3272
+ (function() {
3273
+ // Private array of chars to use
3274
+ var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
3275
+
3276
+ Math.uuid = function (len, radix) {
3277
+ var chars = CHARS, uuid = [];
3278
+ radix = radix || chars.length;
3279
+
3280
+ if (len) {
3281
+ // Compact form
3282
+ for (var i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
3283
+ } else {
3284
+ // rfc4122, version 4 form
3285
+ var r;
3286
+
3287
+ // rfc4122 requires these characters
3288
+ uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
3289
+ uuid[14] = '4';
3290
+
3291
+ // Fill in random data. At i==19 set the high bits of clock sequence as
3292
+ // per rfc4122, sec. 4.1.5
3293
+ for (var i = 0; i < 36; i++) {
3294
+ if (!uuid[i]) {
3295
+ r = 0 | Math.random()*16;
3296
+ uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
3297
+ }
3298
+ }
3299
+ }
3300
+
3301
+ return uuid.join('');
3302
+ };
3303
+
3304
+ // A more performant, but slightly bulkier, RFC4122v4 solution. We boost performance
3305
+ // by minimizing calls to random()
3306
+ Math.uuidFast = function() {
3307
+ var chars = CHARS, uuid = new Array(36), rnd=0, r;
3308
+ for (var i = 0; i < 36; i++) {
3309
+ if (i==8 || i==13 || i==18 || i==23) {
3310
+ uuid[i] = '-';
3311
+ } else if (i==14) {
3312
+ uuid[i] = '4';
3313
+ } else {
3314
+ if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
3315
+ r = rnd & 0xf;
3316
+ rnd = rnd >> 4;
3317
+ uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
3318
+ }
3319
+ }
3320
+ return uuid.join('');
3321
+ };
3322
+
3323
+ // A more compact, but less performant, RFC4122v4 solution:
3324
+ Math.uuidCompact = function() {
3325
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
3326
+ var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
3327
+ return v.toString(16);
3328
+ }).toUpperCase();
3329
+ };
3330
+ })();
3331
+