Math/Utils - various cleanup and deprecations/moves

There are no known breaking changes.

- Timer
  - Uses standard Math.min/Math.max (it's better 2, 3 items).

- Math
  - Updated documentation
  - Marked various Math functions as deprecated, proxying as appropriate
    - Array-based functions -> ArrayUtils
    - RNG-based functions -> Utils
    - Updated core-usage
    - floor/ceil should not be used (alternatives provided)
  - Altered for some equivalencies
  - Also fixes some assorted issues
  - Marked a few internal functions as private

- Utils
  - Moved polyfills to their own file for better visibility
  - Moved array functions to ArrayUtils and marked proxies as deprecated

- Created Phaser.ArrayUtils for array-related functions

- polyfills moved to their own file
  - Functions given function names
  - Added Math.trunc
This commit is contained in:
Paul 2014-11-09 01:42:28 -08:00
parent 0fc70db14c
commit a6d2da2a8a
9 changed files with 610 additions and 520 deletions

View file

@ -1595,7 +1595,7 @@ Phaser.Group.prototype.getRandom = function (startIndex, length) {
startIndex = startIndex || 0;
length = length || this.children.length;
return this.game.math.getRandom(this.children, startIndex, length);
return Phaser.ArrayUtils.getRandomItem(this.children, startIndex, length);
};

View file

@ -125,21 +125,13 @@ Phaser.Circle.prototype = {
* (can be Circle, Point or anything with x/y properties)
* @method Phaser.Circle#distance
* @param {object} dest - The target object. Must have visible x and y properties that represent the center of the object.
* @param {boolean} [round] - Round the distance to the nearest integer (default false).
* @param {boolean} [round=false] - Round the distance to the nearest integer.
* @return {number} The distance between this Point object and the destination Point object.
*/
distance: function (dest, round) {
if (typeof round === "undefined") { round = false; }
if (round)
{
return Phaser.Math.distanceRounded(this.x, this.y, dest.x, dest.y);
}
else
{
return Phaser.Math.distance(this.x, this.y, dest.x, dest.y);
}
var distance = Phaser.Math.distance(this.x, this.y, dest.x, dest.y);
return round ? Math.round(distance) : distance;
},

View file

@ -708,21 +708,13 @@ Phaser.Point.rperp = function (a, out) {
* @method Phaser.Point.distance
* @param {object} a - The target object. Must have visible x and y properties that represent the center of the object.
* @param {object} b - The target object. Must have visible x and y properties that represent the center of the object.
* @param {boolean} [round] - Round the distance to the nearest integer (default false).
* @param {boolean} [round=false] - Round the distance to the nearest integer.
* @return {number} The distance between this Point object and the destination Point object.
*/
Phaser.Point.distance = function (a, b, round) {
if (typeof round === "undefined") { round = false; }
if (round)
{
return Phaser.Math.distanceRounded(a.x, a.y, b.x, b.y);
}
else
{
return Phaser.Math.distance(a.x, a.y, b.x, b.y);
}
var distance = Phaser.Math.distance(a.x, a.y, b.x, b.y);
return round ? Math.round(distance) : distance;
};

View file

@ -12,102 +12,105 @@
Phaser.Math = {
/**
* = 2 π
* @method Phaser.Math#PI2
* Twice PI.
* @property {number} Phaser.Math#PI2
* @default ~6.283
*/
PI2: Math.PI * 2,
/**
* Two number are fuzzyEqual if their difference is less than ε.
* Two number are fuzzyEqual if their difference is less than epsilon.
*
* @method Phaser.Math#fuzzyEqual
* @param {number} a
* @param {number} b
* @param {number} epsilon
* @return {boolean} True if |a-b|<&epsilon;
* @param {number} [epsilon=(small value)]
* @return {boolean} True if |a-b|<epsilon
*/
fuzzyEqual: function (a, b, epsilon) {
if (typeof epsilon === "undefined") { epsilon = 0.0001; }
if (typeof epsilon === 'undefined') { epsilon = 0.0001; }
return Math.abs(a - b) < epsilon;
},
/**
* a is fuzzyLessThan b if it is less than b + &epsilon;.
* `a` is fuzzyLessThan `b` if it is less than b + epsilon.
*
* @method Phaser.Math#fuzzyLessThan
* @param {number} a
* @param {number} b
* @param {number} epsilon
* @return {boolean} True if a<b+&epsilon;
* @param {number} [epsilon=(small value)]
* @return {boolean} True if a<b+epsilon
*/
fuzzyLessThan: function (a, b, epsilon) {
if (typeof epsilon === "undefined") { epsilon = 0.0001; }
if (typeof epsilon === 'undefined') { epsilon = 0.0001; }
return a < b + epsilon;
},
/**
* a is fuzzyGreaterThan b if it is more than b - &epsilon;.
* `a` is fuzzyGreaterThan `b` if it is more than b - epsilon.
*
* @method Phaser.Math#fuzzyGreaterThan
* @param {number} a
* @param {number} b
* @param {number} epsilon
* @return {boolean} True if a>b+&epsilon;
* @param {number} [epsilon=(small value)]
* @return {boolean} True if a>b+epsilon
*/
fuzzyGreaterThan: function (a, b, epsilon) {
if (typeof epsilon === "undefined") { epsilon = 0.0001; }
if (typeof epsilon === 'undefined') { epsilon = 0.0001; }
return a > b - epsilon;
},
/**
* @method Phaser.Math#fuzzyCeil
*
* @param {number} val
* @param {number} epsilon
* @return {boolean} ceiling(val-&epsilon;)
* @param {number} [epsilon=(small value)]
* @return {boolean} ceiling(val-epsilon)
*/
fuzzyCeil: function (val, epsilon) {
if (typeof epsilon === "undefined") { epsilon = 0.0001; }
if (typeof epsilon === 'undefined') { epsilon = 0.0001; }
return Math.ceil(val - epsilon);
},
/**
* @method Phaser.Math#fuzzyFloor
*
* @param {number} val
* @param {number} epsilon
* @return {boolean} floor(val-&epsilon;)
* @param {number} [epsilon=(small value)]
* @return {boolean} floor(val-epsilon)
*/
fuzzyFloor: function (val, epsilon) {
if (typeof epsilon === "undefined") { epsilon = 0.0001; }
if (typeof epsilon === 'undefined') { epsilon = 0.0001; }
return Math.floor(val + epsilon);
},
/**
* Averages all values passed to the function and returns the result. You can pass as many parameters as you like.
* Averages all values passed to the function and returns the result.
*
* @method Phaser.Math#average
* @params {...number} The numbers to average
* @return {number} The average of all given values.
*/
average: function () {
var args = [];
var sum = 0;
for (var _i = 0; _i < (arguments.length - 0); _i++) {
args[_i] = arguments[_i + 0];
for (var i = 0; i < arguments.length; i++) {
sum += (+arguments[i]);
}
var avg = 0;
for (var i = 0; i < args.length; i++) {
avg += args[i];
}
return avg / args.length;
return sum / arguments.length;
},
/**
* @method Phaser.Math#truncate
* @param {number} n
* @return {number}
* @return {integer}
* @deprecated 2.1.4 - Use `Math.trunc` (now with polyfill)
*/
truncate: function (n) {
return (n > 0) ? Math.floor(n) : Math.ceil(n);
return Math.trunc(n);
},
/**
@ -132,7 +135,7 @@ Phaser.Math = {
*/
snapTo: function (input, gap, start) {
if (typeof start === "undefined") { start = 0; }
if (typeof start === 'undefined') { start = 0; }
if (gap === 0) {
return input;
@ -158,7 +161,7 @@ Phaser.Math = {
*/
snapToFloor: function (input, gap, start) {
if (typeof start === "undefined") { start = 0; }
if (typeof start === 'undefined') { start = 0; }
if (gap === 0) {
return input;
@ -184,7 +187,7 @@ Phaser.Math = {
*/
snapToCeil: function (input, gap, start) {
if (typeof start === "undefined") { start = 0; }
if (typeof start === 'undefined') { start = 0; }
if (gap === 0) {
return input;
@ -197,66 +200,53 @@ Phaser.Math = {
},
/**
* Snaps a value to the nearest value in an array.
*
* @method Phaser.Math#snapToInArray
* @param {number} input
* @param {array} arr
* @param {number[]} arr
* @param {boolean} sort - True if the array needs to be sorted.
* @return {number}
* @deprecated 2.1.4 - See {@link Phaser.Utils.Arrays.findClosest} for an alternative.
*/
snapToInArray: function (input, arr, sort) {
if (typeof sort === "undefined") { sort = true; }
if (typeof sort === 'undefined') { sort = true; }
if (sort) {
arr.sort();
}
if (input < arr[0]) {
return arr[0];
}
var i = 1;
while (arr[i] < input) {
i++;
}
var low = arr[i - 1];
var high = (i < arr.length) ? arr[i] : Number.POSITIVE_INFINITY;
return ((high - input) <= (input - low)) ? high : low;
return Phaser.Utils.Arrays.findClosest(input, arr);
},
/**
* Round to some place comparative to a 'base', default is 10 for decimal place.
* Round to some place comparative to a `base`, default is 10 for decimal place.
* The `place` is represented by the power applied to `base` to get that place.
*
* 'place' is represented by the power applied to 'base' to get that place
* e.g.
* 2000/7 ~= 285.714285714285714285714 ~= (bin)100011101.1011011011011011
* e.g. 2000/7 ~= 285.714285714285714285714 ~= (bin)100011101.1011011011011011
*
* roundTo(2000/7,3) === 0
* roundTo(2000/7,2) == 300
* roundTo(2000/7,1) == 290
* roundTo(2000/7,0) == 286
* roundTo(2000/7,-1) == 285.7
* roundTo(2000/7,-2) == 285.71
* roundTo(2000/7,-3) == 285.714
* roundTo(2000/7,-4) == 285.7143
* roundTo(2000/7,-5) == 285.71429
* roundTo(2000/7,3) === 0
* roundTo(2000/7,2) == 300
* roundTo(2000/7,1) == 290
* roundTo(2000/7,0) == 286
* roundTo(2000/7,-1) == 285.7
* roundTo(2000/7,-2) == 285.71
* roundTo(2000/7,-3) == 285.714
* roundTo(2000/7,-4) == 285.7143
* roundTo(2000/7,-5) == 285.71429
*
* roundTo(2000/7,3,2) == 288 -- 100100000
* roundTo(2000/7,2,2) == 284 -- 100011100
* roundTo(2000/7,1,2) == 286 -- 100011110
* roundTo(2000/7,0,2) == 286 -- 100011110
* roundTo(2000/7,-1,2) == 285.5 -- 100011101.1
* roundTo(2000/7,-2,2) == 285.75 -- 100011101.11
* roundTo(2000/7,-3,2) == 285.75 -- 100011101.11
* roundTo(2000/7,-4,2) == 285.6875 -- 100011101.1011
* roundTo(2000/7,-5,2) == 285.71875 -- 100011101.10111
* roundTo(2000/7,3,2) == 288 -- 100100000
* roundTo(2000/7,2,2) == 284 -- 100011100
* roundTo(2000/7,1,2) == 286 -- 100011110
* roundTo(2000/7,0,2) == 286 -- 100011110
* roundTo(2000/7,-1,2) == 285.5 -- 100011101.1
* roundTo(2000/7,-2,2) == 285.75 -- 100011101.11
* roundTo(2000/7,-3,2) == 285.75 -- 100011101.11
* roundTo(2000/7,-4,2) == 285.6875 -- 100011101.1011
* roundTo(2000/7,-5,2) == 285.71875 -- 100011101.10111
*
* Note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed
* because we are rounding 100011.1011011011011011 which rounds up.
@ -269,8 +259,8 @@ Phaser.Math = {
*/
roundTo: function (value, place, base) {
if (typeof place === "undefined") { place = 0; }
if (typeof base === "undefined") { base = 10; }
if (typeof place === 'undefined') { place = 0; }
if (typeof base === 'undefined') { base = 10; }
var p = Math.pow(base, -place);
@ -287,8 +277,8 @@ Phaser.Math = {
*/
floorTo: function (value, place, base) {
if (typeof place === "undefined") { place = 0; }
if (typeof base === "undefined") { base = 10; }
if (typeof place === 'undefined') { place = 0; }
if (typeof base === 'undefined') { base = 10; }
var p = Math.pow(base, -place);
@ -305,8 +295,8 @@ Phaser.Math = {
*/
ceilTo: function (value, place, base) {
if (typeof place === "undefined") { place = 0; }
if (typeof base === "undefined") { base = 10; }
if (typeof place === 'undefined') { place = 0; }
if (typeof base === 'undefined') { base = 10; }
var p = Math.pow(base, -place);
@ -333,7 +323,7 @@ Phaser.Math = {
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @return {number}
* @return {number} The angle, in radians.
*/
angleBetween: function (x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
@ -349,7 +339,7 @@ Phaser.Math = {
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @return {number}
* @return {number} The angle, in radians.
*/
angleBetweenY: function (x1, y1, x2, y2) {
return Math.atan2(x2 - x1, y2 - y1);
@ -360,7 +350,7 @@ Phaser.Math = {
* @method Phaser.Math#angleBetweenPoints
* @param {Phaser.Point} point1
* @param {Phaser.Point} point2
* @return {number}
* @return {number} The angle, in radians.
*/
angleBetweenPoints: function (point1, point2) {
return Math.atan2(point2.y - point1.y, point2.x - point1.x);
@ -371,7 +361,7 @@ Phaser.Math = {
* @method Phaser.Math#angleBetweenPointsY
* @param {Phaser.Point} point1
* @param {Phaser.Point} point2
* @return {number}
* @return {number} The angle, in radians.
*/
angleBetweenPointsY: function (point1, point2) {
return Math.atan2(point2.x - point1.x, point2.y - point1.y);
@ -405,9 +395,10 @@ Phaser.Math = {
* @method Phaser.Math#normalizeLatitude
* @param {number} lat - The latitude to normalize, in degrees.
* @return {number} Returns the latitude, fit within the [-90,90] range.
* @deprecated 2.1.4 - Use {@link Phaser.Math#clamp}.
*/
normalizeLatitude: function (lat) {
return Math.max(-90, Math.min(90, lat));
return Phaser.Math.clamp(lat, -90, 90);
},
/**
@ -415,53 +406,25 @@ Phaser.Math = {
* @method Phaser.Math#normalizeLongitude
* @param {number} lng - The longitude to normalize, in degrees.
* @return {number} Returns the longitude, fit within the [-180,180] range.
* @deprecated 2.1.4 - Use {@link Phaser.Math#wrap}.
*/
normalizeLongitude: function (lng) {
if (lng % 360 == 180)
{
return 180;
}
lng = lng % 360;
return lng < -180 ? lng + 360 : lng > 180 ? lng - 360 : lng;
return Phaser.Math.wrap(lng, -180, 180);
},
/**
* Generate a random bool result based on the chance value.
* <p>
*
* Returns true or false based on the chance value (default 50%). For example if you wanted a player to have a 30% chance
* of getting a bonus, call chanceRoll(30) - true means the chance passed, false means it failed.
* </p>
*
* @method Phaser.Math#chanceRoll
* @param {number} chance - The chance of receiving the value. A number between 0 and 100 (effectively 0% to 100%).
* @return {boolean} True if the roll passed, or false otherwise.
* @deprecated 2.1.4 - Use {@link Phaser.Utils.chanceRoll}
*/
chanceRoll: function (chance) {
if (typeof chance === "undefined") { chance = 50; }
if (chance <= 0)
{
return false;
}
else if (chance >= 100)
{
return true;
}
else
{
if (Math.random() * 100 >= chance)
{
return false;
}
else
{
return true;
}
}
return Phaser.Utils.chanceRoll(chance);
},
/**
@ -491,14 +454,12 @@ Phaser.Math = {
* `start` up to but not including `end`. If `start` is less than `stop` a
* zero-length range is created unless a negative `step` is specified.
*
* @static
* @method Phaser.Math#numberArrayStep
* @param {number} [start=0] - The start of the range.
* @param {number} end - The end of the range.
* @param {number} [step=1] - The value to increment or decrement by.
* @returns {Array} Returns the new array of numbers.
* @example
*
* Phaser.Math.numberArrayStep(4);
* // => [0, 1, 2, 3]
*
@ -544,7 +505,7 @@ Phaser.Math = {
// use `Array(length)` so engines like Chakra and V8 avoid slower modes
// http://youtu.be/XAqIpGU8ZZk#t=17m25s
var index = -1;
var length = Phaser.Math.max(Phaser.Math.ceil((end - start) / (step || 1)), 0);
var length = Math.max(Phaser.Math.roundAwayFromZero((end - start) / (step || 1)), 0);
var result = new Array(length);
while (++index < length)
@ -563,20 +524,11 @@ Phaser.Math = {
* @method Phaser.Math#maxAdd
* @param {number} value - The value to add the amount to.
* @param {number} amount - The amount to add to the value.
* @param {number} max- The maximum the value is allowed to be.
* @param {number} max - The maximum the value is allowed to be.
* @return {number}
*/
maxAdd: function (value, amount, max) {
value += amount;
if (value > max)
{
value = max;
}
return value;
return Math.min(value + amount, max);
},
/**
@ -589,16 +541,7 @@ Phaser.Math = {
* @return {number} The new value.
*/
minSub: function (value, amount, min) {
value -= amount;
if (value < min)
{
value = min;
}
return value;
return Math.max(value - amount, min);
},
/**
@ -661,67 +604,58 @@ Phaser.Math = {
* @param {number} min - The minimum the value can be.
* @param {number} max - The maximum the value can be.
* @return {number} The limited value.
* @deprecated 2.1.4 - Use {@link Phaser.Math#clamp}
*/
limitValue: function(value, min, max) {
return value < min ? min : value > max ? max : value;
return Phaser.Math.clamp(value, min, max);
},
/**
* Randomly returns either a 1 or -1.
*
* @method Phaser.Math#randomSign
* @return {number} 1 or -1
* @return {number} Either 1 or -1
* @deprecated 2.1.4 - Use {@link Phaser.Utils.randomChoice} or other
*/
randomSign: function () {
return (Math.random() > 0.5) ? 1 : -1;
return Phaser.Utils.randomChoice(-1, 1);
},
/**
* Returns true if the number given is odd.
*
* @method Phaser.Math#isOdd
* @param {number} n - The number to check.
* @return {boolean} True if the given number is odd. False if the given number is even.
* @param {integer} n - The number to check.
* @return {boolean} True if the given number is odd. False if the given number is even.
*/
isOdd: function (n) {
// Does not work with extremely large values
return (n & 1);
},
/**
* Returns true if the number given is even.
*
* @method Phaser.Math#isEven
* @param {number} n - The number to check.
* @param {integer} n - The number to check.
* @return {boolean} True if the given number is even. False if the given number is odd.
*/
isEven: function (n) {
if (n & 1)
{
return false;
}
else
{
return true;
}
// Does not work with extremely large values
return !(n & 1);
},
/**
* Updated version of Math.min that can be passed either an array of numbers or the numbers as parameters.
* See http://jsperf.com/math-s-min-max-vs-homemade/5
* Variation of Math.min that can be passed either an array of numbers or the numbers as parameters.
*
* Prefer the standard `Math.min` function when appropriate.
*
* @method Phaser.Math#min
* @return {number} The lowest value from those given.
* @see {@link http://jsperf.com/math-s-min-max-vs-homemade}
*/
min: function () {
if (arguments.length === 1 && typeof arguments[0] === 'object')
{
var data = arguments[0];
@ -730,7 +664,7 @@ Phaser.Math = {
{
var data = arguments;
}
for (var i = 1, min = 0, len = data.length; i < len; i++)
{
if (data[i] < data[min])
@ -744,13 +678,16 @@ Phaser.Math = {
},
/**
* Updated version of Math.max that can be passed either an array of numbers or the numbers as parameters.
* Variation of Math.max that can be passed either an array of numbers or the numbers as parameters.
*
* Prefer the standard `Math.max` function when appropriate.
*
* @method Phaser.Math#max
* @return {number} The largest value from those given.
* @see {@link http://jsperf.com/math-s-min-max-vs-homemade}
*/
max: function () {
if (arguments.length === 1 && typeof arguments[0] === 'object')
{
var data = arguments[0];
@ -759,7 +696,7 @@ Phaser.Math = {
{
var data = arguments;
}
for (var i = 1, max = 0, len = data.length; i < len; i++)
{
if (data[i] > data[max])
@ -773,7 +710,7 @@ Phaser.Math = {
},
/**
* Updated version of Math.min that can be passed a property and either an array of objects or the objects as parameters.
* Vartiation of Math.min that can be passed a property and either an array of objects or the objects as parameters.
* It will find the lowest matching property value from the given objects.
*
* @method Phaser.Math#minProperty
@ -803,7 +740,7 @@ Phaser.Math = {
},
/**
* Updated version of Math.max that can be passed a property and either an array of objects or the objects as parameters.
* Variation of Math.max that can be passed a property and either an array of objects or the objects as parameters.
* It will find the largest matching property value from the given objects.
*
* @method Phaser.Math#maxProperty
@ -969,6 +906,7 @@ Phaser.Math = {
* @param {number} p1
* @param {number} t
* @return {number}
* @private
*/
linear: function (p0, p1, t) {
return (p1 - p0) * t + p0;
@ -979,6 +917,7 @@ Phaser.Math = {
* @param {number} n
* @param {number} i
* @return {number}
* @private
*/
bernstein: function (n, i) {
return this.factorial(n) / this.factorial(i) / this.factorial(n - i);
@ -988,6 +927,7 @@ Phaser.Math = {
* @method Phaser.Math#factorial
* @param {number} value - the number you want to evaluate
* @return {number}
* @private
*/
factorial : function( value ){
@ -1004,6 +944,7 @@ Phaser.Math = {
}
return res;
},
/**
@ -1016,6 +957,7 @@ Phaser.Math = {
* @param {number} p3
* @param {number} t
* @return {number}
* @private
*/
catmullRom: function (p0, p1, p2, p3, t) {
@ -1044,29 +986,10 @@ Phaser.Math = {
* @param {number} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {number} length - Optional restriction on the number of values you want to randomly select from.
* @return {object} The random object that was selected.
* @deprecated 2.1.4 - Use {@link Phaser.Utils.Arrays.getRandomItem}
*/
getRandom: function (objects, startIndex, length) {
if (typeof startIndex === "undefined") { startIndex = 0; }
if (typeof length === "undefined") { length = 0; }
if (objects != null) {
var l = length;
if ((l === 0) || (l > objects.length - startIndex))
{
l = objects.length - startIndex;
}
if (l > 0)
{
return objects[startIndex + Math.floor(Math.random() * l)];
}
}
return null;
return Phaser.Utils.Arrays.getRandomItem(objects, startIndex, length);
},
/**
@ -1078,78 +1001,74 @@ Phaser.Math = {
* @param {number} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {number} length - Optional restriction on the number of values you want to randomly select from.
* @return {object} The random object that was removed.
* @deprecated 2.1.4 - Use {@link Phaser.Utils.Arrays.removeRandomItem}
*/
removeRandom: function (objects, startIndex, length) {
if (typeof startIndex === "undefined") { startIndex = 0; }
if (typeof length === "undefined") { length = 0; }
if (objects != null) {
var l = length;
if ((l === 0) || (l > objects.length - startIndex))
{
l = objects.length - startIndex;
}
if (l > 0)
{
var idx = startIndex + Math.floor(Math.random() * l);
var removed = objects.splice(idx, 1);
return removed[0];
}
}
return null;
return Phaser.Utils.Arrays.removeRandomItem(objects, startIndex, length);
},
/**
* Round down to the next whole number. E.g. floor(1.7) == 1, and floor(-2.7) == -2.
* _Do not use this function._
*
* Round to the next whole number _towards_ zero.
*
* E.g. `floor(1.7) == 1`, and `floor(-2.7) == -2`.
*
* @method Phaser.Math#floor
* @param {number} Value Any number.
* @return {number} The rounded value of that number.
* @param {number} value - Any number.
* @return {integer} The rounded value of that number.
* @deprecated 2.1.4 - Use {@link Phaser.Math#truncate} or instead.
*/
floor: function (value) {
var n = value | 0;
return (value > 0) ? (n) : ((n != value) ? (n - 1) : (n));
return Math.trunc(value);
},
/**
* Round up to the next whole number. E.g. ceil(1.3) == 2, and ceil(-2.3) == -3.
* _Do not use this function._
*
* Round to the next whole number _away_ from zero.
*
* E.g. `ceil(1.3) == 2`, and `ceil(-2.3) == -3`.
*
* @method Phaser.Math#ceil
* @param {number} value - Any number.
* @return {number} The rounded value of that number.
* @return {integer} The rounded value of that number.
* @deprecated 2.1.4 - Use {@link Phaser.Math#roundAwayFromZero} instead.
*/
ceil: function (value) {
var n = value | 0;
return (value > 0) ? ((n != value) ? (n + 1) : (n)) : (n);
return Phaser.Math.roundAwayFromZero(value);
},
/**
* Round to the next whole number _away_ from zero.
*
* @method Phaser.Math#roundAwayFromZero
* @param {number} value - Any number.
* @return {integer} The rounded value of that number.
*/
roundAwayFromZero: function (value) {
// "Opposite" of truncate.
return (value > 0) ? Math.ceil(value) : Math.floor(value);
},
/**
* Generate a sine and cosine table simultaneously and extremely quickly. Based on research by Franky of scene.at
* <p>
*
* The parameters allow you to specify the length, amplitude and frequency of the wave. Once you have called this function
* you should get the results via getSinTable() and getCosTable(). This generator is fast enough to be used in real-time.
* </p>
*
* @method Phaser.Math#sinCosGenerator
* @param {number} length - The length of the wave
* @param {number} sinAmplitude - The amplitude to apply to the sine table (default 1.0) if you need values between say -+ 125 then give 125 as the value
* @param {number} cosAmplitude - The amplitude to apply to the cosine table (default 1.0) if you need values between say -+ 125 then give 125 as the value
* @param {number} frequency - The frequency of the sine and cosine table data
* @return {Array} Returns the sine table
* @return {{sin:number[], cos:number[]}} Returns the table data.
*/
sinCosGenerator: function (length, sinAmplitude, cosAmplitude, frequency) {
if (typeof sinAmplitude === "undefined") { sinAmplitude = 1.0; }
if (typeof cosAmplitude === "undefined") { cosAmplitude = 1.0; }
if (typeof frequency === "undefined") { frequency = 1.0; }
if (typeof sinAmplitude === 'undefined') { sinAmplitude = 1.0; }
if (typeof cosAmplitude === 'undefined') { cosAmplitude = 1.0; }
if (typeof frequency === 'undefined') { frequency = 1.0; }
var sin = sinAmplitude;
var cos = cosAmplitude;
@ -1179,6 +1098,7 @@ Phaser.Math = {
* @method Phaser.Math#shift
* @param {array} stack - The array to shift.
* @return {any} The shifted value.
* @deprecated 2.1.4 - Not used internally, better to do locally
*/
shift: function (stack) {
@ -1190,23 +1110,14 @@ Phaser.Math = {
},
/**
* Shuffles the data in the given array into a new order
* Shuffles the data in the given array into a new order.
* @method Phaser.Math#shuffleArray
* @param {array} array - The array to shuffle
* @return {array} The array
* @deprecated 2.1.4 - Use {@link Phaser.Utils.Arrays.shuffle}
*/
shuffleArray: function (array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
return Phaser.Utils.Arrays.shuffle(array);
},
/**
@ -1256,6 +1167,7 @@ Phaser.Math = {
* @param {number} x2
* @param {number} y2
* @return {number} The distance between this Point object and the destination Point object.
* @deprecated 2.1.4 - Do the rounding locally.
*/
distanceRounded: function (x1, y1, x2, y2) {
@ -1264,8 +1176,7 @@ Phaser.Math = {
},
/**
* Force a value within the boundaries of two values.
* Clamp value to range <a, b>
* Force a value within the boundaries by clamping `x` to the range `[a, b]`.
*
* @method Phaser.Math#clamp
* @param {number} x
@ -1273,21 +1184,22 @@ Phaser.Math = {
* @param {number} b
* @return {number}
*/
clamp: function ( x, a, b ) {
clamp: function (x, a, b) {
return ( x < a ) ? a : ( ( x > b ) ? b : x );
},
/**
* Clamp value to range <a, inf).
* Clamp value to range `[a, inf)`.
* Roughly the same as `Math.max(x, a)`, except for NaN handling.
*
* @method Phaser.Math#clampBottom
* @param {number} x
* @param {number} a
* @return {number}
*/
clampBottom: function ( x, a ) {
clampBottom: function (x, a) {
return x < a ? a : x;
@ -1301,8 +1213,9 @@ Phaser.Math = {
* @param {number} b - The second number to check
* @param {number} tolerance - The tolerance. Anything equal to or less than this is considered within the range.
* @return {boolean} True if a is <= tolerance of b.
* @see {@link Phaser.Math.fuzzyEqual}
*/
within: function ( a, b, tolerance ) {
within: function (a, b, tolerance) {
return (Math.abs(a - b) <= tolerance);
@ -1319,7 +1232,7 @@ Phaser.Math = {
* @param {number} b2 final endpoint of the range <b1, b2>
* @return {number}
*/
mapLinear: function ( x, a1, a2, b1, b2 ) {
mapLinear: function (x, a1, a2, b1, b2) {
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
@ -1334,7 +1247,7 @@ Phaser.Math = {
* @param {number} max
* @return {number}
*/
smoothstep: function ( x, min, max ) {
smoothstep: function (x, min, max) {
x = Math.max(0, Math.min(1, (x - min) / (max - min)));
return x * x * (3 - 2 * x);
@ -1350,7 +1263,7 @@ Phaser.Math = {
* @param {number} max
* @return {number}
*/
smootherstep: function ( x, min, max ) {
smootherstep: function (x, min, max) {
x = Math.max(0, Math.min(1, (x - min) / (max - min)));
return x * x * x * (x * (x * 6 - 15) + 10);
@ -1358,21 +1271,22 @@ Phaser.Math = {
},
/**
* A value representing the sign of the value.
* -1 for negative, +1 for positive, 0 if value is 0
* A value representing the sign of the value: -1 for negative, +1 for positive, 0 if value is 0.
*
* This works differently from `Math.sign` for value of NaN and -0, etc.
*
* @method Phaser.Math#sign
* @param {number} x
* @return {number}
* @return {integer} An integer in {-1, 0, 1}
*/
sign: function ( x ) {
sign: function (x) {
return ( x < 0 ) ? -1 : ( ( x > 0 ) ? 1 : 0 );
},
/**
* Work out what percentage value a is of value b using the given base.
* Work out what percentage value `a` is of value `b` using the given base.
*
* @method Phaser.Math#percent
* @param {number} a - The value to work out the percentage for.
@ -1403,16 +1317,15 @@ Phaser.Math = {
* Convert degrees to radians.
*
* @method Phaser.Math#degToRad
* @return {function}
* @param {number} degrees - Angle in degrees.
* @return {number} Angle in radians.
*/
degToRad: (function() {
var degreeToRadiansFactor = Math.PI / 180;
return function ( degrees ) {
return function (degrees) {
return degrees * degreeToRadiansFactor;
};
}()),
@ -1421,16 +1334,15 @@ Phaser.Math = {
* Convert degrees to radians.
*
* @method Phaser.Math#radToDeg
* @return {function}
* @param {number} radians - Angle in radians.
* @return {number} Angle in degrees
*/
radToDeg: (function() {
var radianToDegreesFactor = 180 / Math.PI;
return function ( radians ) {
return function (radians) {
return radians * radianToDegreesFactor;
};
}())

154
src/polyfills.js Normal file
View file

@ -0,0 +1,154 @@
/**
* @copyright 2014 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
// ES6 Math.trunc - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
if (!Math.trunc) {
Math.trunc = function trunc(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
};
}
/**
* A polyfill for Function.prototype.bind
*/
if (!Function.prototype.bind) {
/* jshint freeze: false */
Function.prototype.bind = (function () {
var slice = Array.prototype.slice;
return function (thisArg) {
var target = this, boundArgs = slice.call(arguments, 1);
if (typeof target !== 'function')
{
throw new TypeError();
}
function bound() {
var args = boundArgs.concat(slice.call(arguments));
target.apply(this instanceof bound ? this : thisArg, args);
}
bound.prototype = (function F(proto) {
if (proto)
{
F.prototype = proto;
}
if (!(this instanceof F))
{
/* jshint supernew: true */
return new F;
}
})(target.prototype);
return bound;
};
})();
}
/**
* A polyfill for Array.isArray
*/
if (!Array.isArray)
{
Array.isArray = function (arg)
{
return Object.prototype.toString.call(arg) == '[object Array]';
};
}
/**
* A polyfill for Array.forEach
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
*/
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisArg */)
{
"use strict";
if (this === void 0 || this === null)
{
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
{
throw new TypeError();
}
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t)
{
fun.call(thisArg, t[i], i, t);
}
}
};
}
/**
* Low-budget Float32Array knock-off, suitable for use with P2.js in IE9
* Source: http://www.html5gamedevs.com/topic/5988-phaser-12-ie9/
* Cameron Foale (http://www.kibibu.com)
*/
if (typeof window.Uint32Array !== "function" && typeof window.Uint32Array !== "object")
{
var CheapArray = function(type)
{
var proto = new Array(); // jshint ignore:line
window[type] = function(arg) {
if (typeof(arg) === "number")
{
Array.call(this, arg);
this.length = arg;
for (var i = 0; i < this.length; i++)
{
this[i] = 0;
}
}
else
{
Array.call(this, arg.length);
this.length = arg.length;
for (var i = 0; i < this.length; i++)
{
this[i] = arg[i];
}
}
};
window[type].prototype = proto;
window[type].constructor = window[type];
};
CheapArray('Uint32Array'); // jshint ignore:line
CheapArray('Int16Array'); // jshint ignore:line
}
/**
* Also fix for the absent console in IE9
*/
if (!window.console)
{
window.console = {};
window.console.log = window.console.assert = function(){};
window.console.warn = window.console.assert = function(){};
}

View file

@ -288,7 +288,7 @@ Phaser.Time.prototype = {
this.elapsed = this.now - this.prevTime;
// time to call this function again in ms in case we're using timers instead of RequestAnimationFrame to update the game
this.timeToCall = Math.floor(this.game.math.max(0, (1000.0 / this.desiredFps) - (this.timeCallExpected - time)));
this.timeToCall = Math.floor(Math.max(0, (1000.0 / this.desiredFps) - (this.timeCallExpected - time)));
// time when the next call is expected if using timers
this.timeCallExpected = time + this.timeToCall;
@ -316,16 +316,16 @@ Phaser.Time.prototype = {
if (this.advancedTiming)
{
this.msMin = this.game.math.min(this.msMin, this.elapsed);
this.msMax = this.game.math.max(this.msMax, this.elapsed);
this.msMin = Math.min(this.msMin, this.elapsed);
this.msMax = Math.max(this.msMax, this.elapsed);
this.frames++;
if (this.now > this._timeLastSecond + 1000)
{
this.fps = Math.round((this.frames * 1000) / (this.now - this._timeLastSecond));
this.fpsMin = this.game.math.min(this.fpsMin, this.fps);
this.fpsMax = this.game.math.max(this.fpsMax, this.fps);
this.fpsMin = Math.min(this.fpsMin, this.fps);
this.fpsMax = Math.max(this.fpsMax, this.fps);
this._timeLastSecond = this.now;
this.frames = 0;
}

199
src/utils/ArrayUtils.js Normal file
View file

@ -0,0 +1,199 @@
/* jshint supernew: true */
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2014 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* Utility functions for dealing with Arrays.
*
* @class Phaser.ArrayUtils
* @static
*/
Phaser.ArrayUtils = {
/**
* Fetch a random entry from the given array.
* Will return null if random selection is missing, or array has no entries.
*
* @method
* @param {any[]} objects - An array of objects.
* @param {integer} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {integer} length - Optional restriction on the number of values you want to randomly select from.
* @return {object} The random object that was selected.
*/
getRandomItem: function (objects, startIndex, length) {
if (typeof startIndex === 'undefined') { startIndex = 0; }
if (typeof length === 'undefined') { length = 0; }
if (objects == null) { // undefined or null
return null;
}
var l = length;
if ((l === 0) || (l > objects.length - startIndex))
{
l = objects.length - startIndex;
}
var randomIndex = startIndex + Math.floor(Math.random() * l);
return objects[randomIndex] || null;
},
/**
* Removes a random object from the given array and returns it.
* Will return null if random selection is missing, or array has no entries.
*
* @method
* @param {any[]} objects - An array of objects.
* @param {integer} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {integer} length - Optional restriction on the number of values you want to randomly select from.
* @return {object} The random object that was removed.
*/
removeRandomItem: function (objects, startIndex, length) {
if (typeof startIndex === 'undefined') { startIndex = 0; }
if (typeof length === 'undefined') { length = 0; }
if (objects == null) { // undefined or null
return null;
}
var l = length;
if ((l === 0) || (l > objects.length - startIndex))
{
l = objects.length - startIndex;
}
if (l > 0)
{
var idx = startIndex + Math.floor(Math.random() * l);
var removed = objects.splice(idx, 1);
return removed[0];
}
return null;
},
/**
* A standard Fisher-Yates Array shuffle implementation which modifies the array in place.
*
* @method
* @param {array} array - The array to shuffle.
* @return {array} The original array, now shuffled.
*/
shuffle: function (array) {
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
},
/**
* Transposes the elements of the given Array.
*
* @method
* @param {array} array - The array to transpose.
* @return {array} The transposed array.
*/
transpose: function (array) {
var result = new Array(array[0].length);
for (var i = 0; i < array[0].length; i++)
{
result[i] = new Array(array.length - 1);
for (var j = array.length - 1; j > -1; j--)
{
result[i][j] = array[j][i];
}
}
return result;
},
/**
* Rotates the given array.
* Based on the routine from http://jsfiddle.net/MrPolywhirl/NH42z/
*
* @method
* @param {array} matrix - The array to rotate.
* @param {number|string} direction - The amount to rotate. Either a number: 90, -90, 270, -270, 180 or a string: 'rotateLeft', 'rotateRight' or 'rotate180'
* @return {array} The rotated array
*/
rotate: function (matrix, direction) {
if (typeof direction !== 'string')
{
direction = ((direction % 360) + 360) % 360;
}
if (direction === 90 || direction === -270 || direction === 'rotateLeft')
{
matrix = Phaser.Utils.transposeArray(matrix);
matrix = matrix.reverse();
}
else if (direction === -90 || direction === 270 || direction === 'rotateRight')
{
matrix = matrix.reverse();
matrix = Phaser.Utils.transposeArray(matrix);
}
else if (Math.abs(direction) === 180 || direction === 'rotate180')
{
for (var i = 0; i < matrix.length; i++)
{
matrix[i].reverse();
}
matrix = matrix.reverse();
}
return matrix;
},
/**
* Snaps a value to the nearest value in an array.
* The result will always be in the range `[first_value, last_value]`.
*
* @method
* @param {number} value - The search value
* @param {number[]} arr - The input array which _must_ be sorted.
* @return {number} The nearest value found.
*/
findClosest: function (value, arr) {
if (value < arr[0]) {
return arr[0];
}
var i = 1;
while (arr[i] < value) {
i++;
}
var low = arr[i - 1];
var high = (i < arr.length) ? arr[i] : Number.POSITIVE_INFINITY;
return ((high - value) <= (value - low)) ? high : low;
},
};

View file

@ -77,68 +77,68 @@ Phaser.Utils = {
},
/**
* Transposes the elements of the given Array.
*
* @method Phaser.Utils.transposeArray
* @param {array} array - The array to transpose.
* @return {array} The transposed array.
*/
transposeArray: function (array) {
var result = new Array(array[0].length);
for (var i = 0; i < array[0].length; i++)
{
result[i] = new Array(array.length - 1);
for (var j = array.length - 1; j > -1; j--)
{
result[i][j] = array[j][i];
}
}
return result;
* Generate a random bool result based on the chance value.
*
* Returns true or false based on the chance value (default 50%). For example if you wanted a player to have a 30% chance
* of getting a bonus, call chanceRoll(30) - true means the chance passed, false means it failed.
*
* @method Phaser.Math#chanceRoll
* @param {number} chance - The chance of receiving the value. A number between 0 and 100 (effectively 0% to 100%).
* @return {boolean} True if the roll passed, or false otherwise.
*/
chanceRoll: function (chance) {
if (typeof chance === 'undefined') { chance = 50; }
return chance > 0 && (Math.random() * 100 <= chance);
},
/**
* Rotates the given array.
* Based on the routine from http://jsfiddle.net/MrPolywhirl/NH42z/
*
* @method Phaser.Utils.rotateArray
* @param {array} matrix - The array to rotate.
* @param {number|string} direction - The amount to rotate. Either a number: 90, -90, 270, -270, 180 or a string: 'rotateLeft', 'rotateRight' or 'rotate180'
* @return {array} The rotated array
*/
* Choose between one of two values randomly.
*
* @method Phaser.Utils#randomChoice
* @param {any} choice1
* @param {any} choice2
* @return {any} The randomly selected choice
*/
randomChoice: function (choice1, choice2) {
return (Math.random() < 0.5) ? choice1 : choice2;
},
/**
* Transposes the elements of the given Array.
*
* @method Phaser.Utils.transposeArray
* @param {array} array - The array to transpose.
* @return {array} The transposed array.
* @deprecated 2.1.4 - Use Phaser.ArrayUtils.transpose
*/
transposeArray: function (array) {
return Phaser.ArrayUtils.transpose(array);
},
/**
* Rotates the given array.
* Based on the routine from http://jsfiddle.net/MrPolywhirl/NH42z/
*
* @method Phaser.Utils.rotateArray
* @param {array} matrix - The array to rotate.
* @param {number|string} direction - The amount to rotate. Either a number: 90, -90, 270, -270, 180 or a string: 'rotateLeft', 'rotateRight' or 'rotate180'
* @return {array} The rotated array
* @deprecated 2.1.4 - Use Phaser.ArrayUtils.rotate
*/
rotateArray: function (matrix, direction) {
return Phaser.ArrayUtils.rotate(matrix, direction);
},
if (typeof direction !== 'string')
{
direction = ((direction % 360) + 360) % 360;
}
if (direction === 90 || direction === -270 || direction === 'rotateLeft')
{
matrix = Phaser.Utils.transposeArray(matrix);
matrix = matrix.reverse();
}
else if (direction === -90 || direction === 270 || direction === 'rotateRight')
{
matrix = matrix.reverse();
matrix = Phaser.Utils.transposeArray(matrix);
}
else if (Math.abs(direction) === 180 || direction === 'rotate180')
{
for (var i = 0; i < matrix.length; i++)
{
matrix[i].reverse();
}
matrix = matrix.reverse();
}
return matrix;
/**
* A standard Fisher-Yates Array shuffle implementation.
*
* @method Phaser.Utils.shuffle
* @param {array} array - The array to shuffle.
* @return {array} The shuffled array.
* @deprecated 2.1.4 - User Phaser.ArrayUtils.shuffle
*/
shuffle: function (array) {
return Phaser.ArrayUtils.shuffle(array);
},
/**
@ -184,30 +184,9 @@ Phaser.Utils = {
},
/**
* A standard Fisher-Yates Array shuffle implementation.
* @method Phaser.Utils.shuffle
* @param {array} array - The array to shuffle.
* @return {array} The shuffled array.
*/
shuffle: function (array) {
for (var i = array.length - 1; i > 0; i--)
{
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
},
/**
* Javascript string pad http://www.webtoolkit.info/.
* pad = the string to pad it out with (defaults to a space)
* dir = 1 (left), 2 (right), 3 (both)
*
* @method Phaser.Utils.pad
* @param {string} str - The target string.
* @param {number} len - The number of characters to be added.
@ -248,7 +227,8 @@ Phaser.Utils = {
},
/**
* This is a slightly modified version of jQuery.isPlainObject. A plain object is an object whose internal class property is [object Object].
* This is a slightly modified version of jQuery.isPlainObject.
* A plain object is an object whose internal class property is [object Object].
* @method Phaser.Utils.isPlainObject
* @param {object} obj - The object to inspect.
* @return {boolean} - true if the object is plain, otherwise false.
@ -411,144 +391,3 @@ Phaser.Utils = {
}
};
/**
* A polyfill for Function.prototype.bind
*/
if (typeof Function.prototype.bind !== 'function') {
/* jshint freeze: false */
Function.prototype.bind = (function () {
var slice = Array.prototype.slice;
return function (thisArg) {
var target = this, boundArgs = slice.call(arguments, 1);
if (typeof target !== 'function')
{
throw new TypeError();
}
function bound() {
var args = boundArgs.concat(slice.call(arguments));
target.apply(this instanceof bound ? this : thisArg, args);
}
bound.prototype = (function F(proto) {
if (proto)
{
F.prototype = proto;
}
if (!(this instanceof F))
{
return new F;
}
})(target.prototype);
return bound;
};
})();
}
/**
* A polyfill for Array.isArray
*/
if (!Array.isArray)
{
Array.isArray = function (arg)
{
return Object.prototype.toString.call(arg) == '[object Array]';
};
}
/**
* A polyfill for Array.forEach
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
*/
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisArg */)
{
"use strict";
if (this === void 0 || this === null)
{
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
{
throw new TypeError();
}
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++)
{
if (i in t)
{
fun.call(thisArg, t[i], i, t);
}
}
};
}
/**
* Low-budget Float32Array knock-off, suitable for use with P2.js in IE9
* Source: http://www.html5gamedevs.com/topic/5988-phaser-12-ie9/
* Cameron Foale (http://www.kibibu.com)
*/
if (typeof window.Uint32Array !== "function" && typeof window.Uint32Array !== "object")
{
var CheapArray = function(type)
{
var proto = new Array(); // jshint ignore:line
window[type] = function(arg) {
if (typeof(arg) === "number")
{
Array.call(this, arg);
this.length = arg;
for (var i = 0; i < this.length; i++)
{
this[i] = 0;
}
}
else
{
Array.call(this, arg.length);
this.length = arg.length;
for (var i = 0; i < this.length; i++)
{
this[i] = arg[i];
}
}
};
window[type].prototype = proto;
window[type].constructor = window[type];
};
CheapArray('Uint32Array'); // jshint ignore:line
CheapArray('Int16Array'); // jshint ignore:line
}
/**
* Also fix for the absent console in IE9
*/
if (!window.console)
{
window.console = {};
window.console.log = window.console.assert = function(){};
window.console.warn = window.console.assert = function(){};
}

View file

@ -1,6 +1,7 @@
[
"src/Intro.js",
"src/Phaser.js",
"src/polyfill.js",
"src/utils/Utils.js",
"src/geom/Circle.js",
@ -91,6 +92,7 @@
"src/sound/Sound.js",
"src/sound/SoundManager.js",
"src/utils/ArrayUtils.js",
"src/utils/Debug.js",
"src/utils/Color.js",