mirror of
https://github.com/photonstorm/phaser
synced 2024-11-30 08:31:01 +00:00
368 lines
11 KiB
JavaScript
368 lines
11 KiB
JavaScript
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2016 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 there are no array items that fall within the specified range
|
|
* or if there is no item for the randomly chosen index.
|
|
*
|
|
* @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 (objects === null) { return null; }
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (length === undefined) { length = objects.length; }
|
|
|
|
var randomIndex = startIndex + Math.floor(Math.random() * length);
|
|
|
|
return objects[randomIndex] === undefined ? null : objects[randomIndex];
|
|
|
|
},
|
|
|
|
/**
|
|
* Removes a random object from the given array and returns it.
|
|
*
|
|
* Will return null if there are no array items that fall within the specified range
|
|
* or if there is no item for the randomly chosen index.
|
|
*
|
|
* @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 (objects == null) { // undefined or null
|
|
return null;
|
|
}
|
|
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (length === undefined) { length = objects.length; }
|
|
|
|
var randomIndex = startIndex + Math.floor(Math.random() * length);
|
|
if (randomIndex < objects.length)
|
|
{
|
|
var removed = objects.splice(randomIndex, 1);
|
|
return removed[0] === undefined ? null : removed[0];
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* A standard Fisher-Yates Array shuffle implementation which modifies the array in place.
|
|
*
|
|
* @method
|
|
* @param {any[]} array - The array to shuffle.
|
|
* @return {any[]} 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 matrix (array of arrays).
|
|
*
|
|
* @method
|
|
* @param {Array<any[]>} array - The matrix to transpose.
|
|
* @return {Array<any[]>} A new transposed matrix
|
|
*/
|
|
transposeMatrix: function (array) {
|
|
|
|
var sourceRowCount = array.length;
|
|
var sourceColCount = array[0].length;
|
|
|
|
var result = new Array(sourceColCount);
|
|
|
|
for (var i = 0; i < sourceColCount; i++)
|
|
{
|
|
result[i] = new Array(sourceRowCount);
|
|
|
|
for (var j = sourceRowCount - 1; j > -1; j--)
|
|
{
|
|
result[i][j] = array[j][i];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
/**
|
|
* Rotates the given matrix (array of arrays).
|
|
*
|
|
* Based on the routine from {@link http://jsfiddle.net/MrPolywhirl/NH42z/}.
|
|
*
|
|
* @method
|
|
* @param {Array<any[]>} matrix - The array to rotate; this matrix _may_ be altered.
|
|
* @param {number|string} direction - The amount to rotate: the rotation in degrees (90, -90, 270, -270, 180) or a string command ('rotateLeft', 'rotateRight' or 'rotate180').
|
|
* @return {Array<any[]>} The rotated matrix. The source matrix should be discarded for the returned matrix.
|
|
*/
|
|
rotateMatrix: function (matrix, direction) {
|
|
|
|
if (typeof direction !== 'string')
|
|
{
|
|
direction = ((direction % 360) + 360) % 360;
|
|
}
|
|
|
|
if (direction === 90 || direction === -270 || direction === 'rotateLeft')
|
|
{
|
|
matrix = Phaser.ArrayUtils.transposeMatrix(matrix);
|
|
matrix = matrix.reverse();
|
|
}
|
|
else if (direction === -90 || direction === 270 || direction === 'rotateRight')
|
|
{
|
|
matrix = matrix.reverse();
|
|
matrix = Phaser.ArrayUtils.transposeMatrix(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 (!arr.length)
|
|
{
|
|
return NaN;
|
|
}
|
|
else if (arr.length === 1 || 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;
|
|
|
|
},
|
|
|
|
/**
|
|
* Moves the element from the end of the array to the start, shifting all items in the process.
|
|
* The "rotation" happens to the right.
|
|
*
|
|
* Before: `[ A, B, C, D, E, F ]`
|
|
* After: `[ F, A, B, C, D, E ]`
|
|
*
|
|
* See also Phaser.ArrayUtils.rotateLeft.
|
|
*
|
|
* @method Phaser.ArrayUtils.rotateRight
|
|
* @param {any[]} array - The array to rotate. The array is modified.
|
|
* @return {any} The shifted value.
|
|
*/
|
|
rotateRight: function (array) {
|
|
|
|
var s = array.pop();
|
|
array.unshift(s);
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
/**
|
|
* Moves the element from the start of the array to the end, shifting all items in the process.
|
|
* The "rotation" happens to the left.
|
|
*
|
|
* Before: `[ A, B, C, D, E, F ]`
|
|
* After: `[ B, C, D, E, F, A ]`
|
|
*
|
|
* See also Phaser.ArrayUtils.rotateRight
|
|
*
|
|
* @method Phaser.ArrayUtils.rotateLeft
|
|
* @param {any[]} array - The array to rotate. The array is modified.
|
|
* @return {any} The rotated value.
|
|
*/
|
|
rotateLeft: function (array) {
|
|
|
|
var s = array.shift();
|
|
array.push(s);
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
/**
|
|
* Moves the element from the start of the array to the end, shifting all items in the process.
|
|
* The "rotation" happens to the left.
|
|
*
|
|
* Before: `[ A, B, C, D, E, F ]`
|
|
* After: `[ B, C, D, E, F, A ]`
|
|
*
|
|
* See also Phaser.ArrayUtils.rotateRight
|
|
*
|
|
* @method Phaser.ArrayUtils.rotate
|
|
* @deprecated Please use Phaser.ArrayUtils.rotate instead.
|
|
* @param {any[]} array - The array to rotate. The array is modified.
|
|
* @return {any} The rotated value.
|
|
*/
|
|
rotate: function (array) {
|
|
|
|
var s = array.shift();
|
|
array.push(s);
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
/**
|
|
* Create an array representing the range of numbers (usually integers), between, and inclusive of,
|
|
* the given `start` and `end` arguments. For example:
|
|
*
|
|
* `var array = numberArray(2, 4); // array = [2, 3, 4]`
|
|
* `var array = numberArray(0, 9); // array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`
|
|
*
|
|
* This is equivalent to `numberArrayStep(start, end, 1)`.
|
|
*
|
|
* You can optionally provide a prefix and / or suffix string. If given the array will contain
|
|
* strings, not integers. For example:
|
|
*
|
|
* `var array = numberArray(1, 4, 'Level '); // array = ["Level 1", "Level 2", "Level 3", "Level 4"]`
|
|
* `var array = numberArray(5, 7, 'HD-', '.png'); // array = ["HD-5.png", "HD-6.png", "HD-7.png"]`
|
|
*
|
|
* @method Phaser.ArrayUtils#numberArray
|
|
* @param {number} start - The minimum value the array starts with.
|
|
* @param {number} end - The maximum value the array contains.
|
|
* @param {string} [prefix] - Optional prefix to place before the number. If provided the array will contain strings, not integers.
|
|
* @param {string} [suffix] - Optional suffix to place after the number. If provided the array will contain strings, not integers.
|
|
* @return {number[]|string[]} The array of number values, or strings if a prefix or suffix was provided.
|
|
*/
|
|
numberArray: function (start, end, prefix, suffix)
|
|
{
|
|
var result = [];
|
|
|
|
for (var i = start; i <= end; i++)
|
|
{
|
|
if (prefix || suffix)
|
|
{
|
|
var key = (prefix) ? prefix + i.toString() : i.toString();
|
|
|
|
if (suffix)
|
|
{
|
|
key = key.concat(suffix);
|
|
}
|
|
|
|
result.push(key);
|
|
}
|
|
else
|
|
{
|
|
result.push(i);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Create an array of numbers (positive and/or negative) progressing from `start`
|
|
* up to but not including `end` by advancing by `step`.
|
|
*
|
|
* If `start` is less than `end` a zero-length range is created unless a negative `step` is specified.
|
|
*
|
|
* Certain values for `start` and `end` (eg. NaN/undefined/null) are currently coerced to 0;
|
|
* for forward compatibility make sure to pass in actual numbers.
|
|
*
|
|
* @method Phaser.ArrayUtils#numberArrayStep
|
|
* @param {number} start - The start of the range.
|
|
* @param {number} [end] - The end of the range.
|
|
* @param {number} [step=1] - The value to increment or decrement by.
|
|
* @return {Array} Returns the new array of numbers.
|
|
* @example
|
|
* Phaser.ArrayUtils.numberArrayStep(4);
|
|
* // => [0, 1, 2, 3]
|
|
*
|
|
* Phaser.ArrayUtils.numberArrayStep(1, 5);
|
|
* // => [1, 2, 3, 4]
|
|
*
|
|
* Phaser.ArrayUtils.numberArrayStep(0, 20, 5);
|
|
* // => [0, 5, 10, 15]
|
|
*
|
|
* Phaser.ArrayUtils.numberArrayStep(0, -4, -1);
|
|
* // => [0, -1, -2, -3]
|
|
*
|
|
* Phaser.ArrayUtils.numberArrayStep(1, 4, 0);
|
|
* // => [1, 1, 1]
|
|
*
|
|
* Phaser.ArrayUtils.numberArrayStep(0);
|
|
* // => []
|
|
*/
|
|
numberArrayStep: function (start, end, step) {
|
|
|
|
if (start === undefined || start === null) { start = 0; }
|
|
|
|
if (end === undefined || end === null)
|
|
{
|
|
end = start;
|
|
start = 0;
|
|
}
|
|
|
|
if (step === undefined) { step = 1; }
|
|
|
|
var result = [];
|
|
var total = Math.max(Phaser.Math.roundAwayFromZero((end - start) / (step || 1)), 0);
|
|
|
|
for (var i = 0; i < total; i++)
|
|
{
|
|
result.push(start);
|
|
start += step;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|