Added phaser build and hellophaser sample

This commit is contained in:
2014-06-09 21:32:48 -07:00
parent 49f23abbe8
commit 48b5c5714a
856 changed files with 954584 additions and 0 deletions

950
src/utils/Color.js Normal file
View File

@@ -0,0 +1,950 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2014 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* The Phaser.Color class is a set of static methods that assist in color manipulation and conversion.
*
* @class Phaser.Color
*/
Phaser.Color = {
/**
* Packs the r, g, b, a components into a single integer, for use with Int32Array.
* If device is little endian then ABGR order is used. Otherwise RGBA order is used.
*
* @author Matt DesLauriers (@mattdesl)
* @method Phaser.Color.packPixel
* @static
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @param {number} a - The alpha color component, in the range 0 - 255.
* @return {number} The packed color
*/
packPixel: function (r, g, b, a) {
if (Phaser.Device.LITTLE_ENDIAN)
{
return (a << 24) | (b << 16) | (g << 8) | r;
}
else
{
return (r << 24) | (g << 16) | (b << 8) | a;
}
},
/**
* Unpacks the r, g, b, a components into the specified color object, or a new
* object, for use with Int32Array. If little endian, then ABGR order is used when
* unpacking, otherwise, RGBA order is used. The resulting color object has the
* `r, g, b, a` properties which are unrelated to endianness.
*
* Note that the integer is assumed to be packed in the correct endianness. On little-endian
* the format is 0xAABBGGRR and on big-endian the format is 0xRRGGBBAA. If you want a
* endian-independent method, use fromRGBA(rgba) and toRGBA(r, g, b, a).
*
* @author Matt DesLauriers (@mattdesl)
* @method Phaser.Color.unpackPixel
* @static
* @param {number} rgba - The integer, packed in endian order by packPixel.
* @param {object} [out] - An object into which 3 properties will be created: r, g and b. If not provided a new object will be created.
* @param {boolean} [hsl=false] - Also convert the rgb values into hsl?
* @param {boolean} [hsv=false] - Also convert the rgb values into hsv?
* @return {object} An object with the red, green and blue values set in the r, g and b properties.
*/
unpackPixel: function (rgba, out, hsl, hsv) {
if (typeof out === 'undefined' || out === null) { out = Phaser.Color.createColor(); }
if (typeof hsl === 'undefined' || hsl === null) { hsl = false; }
if (typeof hsv === 'undefined' || hsv === null) { hsv = false; }
if (Phaser.Device.LITTLE_ENDIAN)
{
out.a = ((rgba & 0xff000000) >>> 24);
out.b = ((rgba & 0x00ff0000) >>> 16);
out.g = ((rgba & 0x0000ff00) >>> 8);
out.r = ((rgba & 0x000000ff));
}
else
{
out.r = ((rgba & 0xff000000) >>> 24);
out.g = ((rgba & 0x00ff0000) >>> 16);
out.b = ((rgba & 0x0000ff00) >>> 8);
out.a = ((rgba & 0x000000ff));
}
out.color = rgba;
out.rgba = 'rgba(' + out.r + ',' + out.g + ',' + out.b + ',' + (out.a / 255) + ')';
if (hsl)
{
Phaser.Color.RGBtoHSL(out.r, out.g, out.b, out);
}
if (hsv)
{
Phaser.Color.RGBtoHSV(out.r, out.g, out.b, out);
}
return out;
},
/**
* A utility to convert an integer in 0xRRGGBBAA format to a color object.
* This does not rely on endianness.
*
* @author Matt DesLauriers (@mattdesl)
* @method Phaser.Color.fromRGBA
* @static
* @param {number} rgba - An RGBA hex
* @param {object} [out] - The object to use, optional.
* @return {object} A color object.
*/
fromRGBA: function (rgba, out) {
if (!out)
{
out = Phaser.Color.createColor();
}
out.r = ((rgba & 0xff000000) >>> 24);
out.g = ((rgba & 0x00ff0000) >>> 16);
out.b = ((rgba & 0x0000ff00) >>> 8);
out.a = ((rgba & 0x000000ff));
out.rgba = 'rgba(' + out.r + ',' + out.g + ',' + out.b + ',' + out.a + ')';
return out;
},
/**
* A utility to convert RGBA components to a 32 bit integer in RRGGBBAA format.
*
* @author Matt DesLauriers (@mattdesl)
* @method Phaser.Color.toRGBA
* @static
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @param {number} a - The alpha color component, in the range 0 - 255.
* @return {number} A RGBA-packed 32 bit integer
*/
toRGBA: function (r, g, b, a) {
return (r << 24) | (g << 16) | (b << 8) | a;
},
/**
* Converts an RGB color value to HSL (hue, saturation and lightness).
* Conversion forumla from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes RGB values are contained in the set [0, 255] and returns h, s and l in the set [0, 1].
* Based on code by Michael Jackson (https://github.com/mjijackson)
*
* @method Phaser.Color.RGBtoHSL
* @static
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @param {object} [out] - An object into which 3 properties will be created, h, s and l. If not provided a new object will be created.
* @return {object} An object with the hue, saturation and lightness values set in the h, s and l properties.
*/
RGBtoHSL: function (r, g, b, out) {
if (!out)
{
out = Phaser.Color.createColor(r, g, b, 1);
}
r /= 255;
g /= 255;
b /= 255;
var min = Math.min(r, g, b);
var max = Math.max(r, g, b);
// achromatic by default
out.h = 0;
out.s = 0;
out.l = (max + min) / 2;
if (max !== min)
{
var d = max - min;
out.s = out.l > 0.5 ? d / (2 - max - min) : d / (max + min);
if (max === r)
{
out.h = (g - b) / d + (g < b ? 6 : 0);
}
else if (max === g)
{
out.h = (b - r) / d + 2;
}
else if (max === b)
{
out.h = (r - g) / d + 4;
}
out.h /= 6;
}
return out;
},
/**
* Converts an HSL (hue, saturation and lightness) color value to RGB.
* Conversion forumla from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes HSL values are contained in the set [0, 1] and returns r, g and b values in the set [0, 255].
* Based on code by Michael Jackson (https://github.com/mjijackson)
*
* @method Phaser.Color.HSLtoRGB
* @static
* @param {number} h - The hue, in the range 0 - 1.
* @param {number} s - The saturation, in the range 0 - 1.
* @param {number} l - The lightness, in the range 0 - 1.
* @param {object} [out] - An object into which 3 properties will be created: r, g and b. If not provided a new object will be created.
* @return {object} An object with the red, green and blue values set in the r, g and b properties.
*/
HSLtoRGB: function (h, s, l, out) {
if (!out)
{
out = Phaser.Color.createColor(l, l, l);
}
else
{
// achromatic by default
out.r = l;
out.g = l;
out.b = l;
}
if (s !== 0)
{
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
out.r = Phaser.Color.hueToColor(p, q, h + 1 / 3);
out.g = Phaser.Color.hueToColor(p, q, h);
out.b = Phaser.Color.hueToColor(p, q, h - 1 / 3);
}
// out.r = (out.r * 255 | 0);
// out.g = (out.g * 255 | 0);
// out.b = (out.b * 255 | 0);
out.r = Math.floor((out.r * 255 | 0));
out.g = Math.floor((out.g * 255 | 0));
out.b = Math.floor((out.b * 255 | 0));
Phaser.Color.updateColor(out);
return out;
},
/**
* Converts an RGB color value to HSV (hue, saturation and value).
* Conversion forumla from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes RGB values are contained in the set [0, 255] and returns h, s and v in the set [0, 1].
* Based on code by Michael Jackson (https://github.com/mjijackson)
*
* @method Phaser.Color.RGBtoHSV
* @static
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @param {object} [out] - An object into which 3 properties will be created, h, s and v. If not provided a new object will be created.
* @return {object} An object with the hue, saturation and value set in the h, s and v properties.
*/
RGBtoHSV: function (r, g, b, out) {
if (!out)
{
out = Phaser.Color.createColor(r, g, b, 255);
}
r /= 255;
g /= 255;
b /= 255;
var min = Math.min(r, g, b);
var max = Math.max(r, g, b);
var d = max - min;
// achromatic by default
out.h = 0;
out.s = max === 0 ? 0 : d / max;
out.v = max;
if (max !== min)
{
if (max === r)
{
out.h = (g - b) / d + (g < b ? 6 : 0);
}
else if (max === g)
{
out.h = (b - r) / d + 2;
}
else if (max === b)
{
out.h = (r - g) / d + 4;
}
out.h /= 6;
}
return out;
},
/**
* Converts an HSV (hue, saturation and value) color value to RGB.
* Conversion forumla from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes HSV values are contained in the set [0, 1] and returns r, g and b values in the set [0, 255].
* Based on code by Michael Jackson (https://github.com/mjijackson)
*
* @method Phaser.Color.HSVtoRGB
* @static
* @param {number} h - The hue, in the range 0 - 1.
* @param {number} s - The saturation, in the range 0 - 1.
* @param {number} v - The value, in the range 0 - 1.
* @param {object} [out] - An object into which 3 properties will be created: r, g and b. If not provided a new object will be created.
* @return {object} An object with the red, green and blue values set in the r, g and b properties.
*/
HSVtoRGB: function (h, s, v, out) {
if (typeof out === 'undefined') { out = Phaser.Color.createColor(0, 0, 0, 1, h, s, 0, v); }
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch (i % 6)
{
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
out.r = Math.floor(r * 255);
out.g = Math.floor(g * 255);
out.b = Math.floor(b * 255);
Phaser.Color.updateColor(out);
return out;
},
/**
* Converts a hue to an RGB color.
* Based on code by Michael Jackson (https://github.com/mjijackson)
*
* @method Phaser.Color.hueToColor
* @static
* @param {number} p
* @param {number} q
* @param {number} t
* @return {number} The color component value.
*/
hueToColor: function (p, q, t) {
if (t < 0)
{
t += 1;
}
if (t > 1)
{
t -= 1;
}
if (t < 1 / 6)
{
return p + (q - p) * 6 * t;
}
if (t < 1 / 2)
{
return q;
}
if (t < 2 / 3)
{
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
},
/**
* A utility function to create a lightweight 'color' object with the default components.
* Any components that are not specified will default to zero.
*
* This is useful when you want to use a shared color object for the getPixel and getPixelAt methods.
*
* @author Matt DesLauriers (@mattdesl)
* @method Phaser.Color.createColor
* @static
* @param {number} [r=0] - The red color component, in the range 0 - 255.
* @param {number} [g=0] - The green color component, in the range 0 - 255.
* @param {number} [b=0] - The blue color component, in the range 0 - 255.
* @param {number} [a=1] - The alpha color component, in the range 0 - 1.
* @param {number} [h=0] - The hue, in the range 0 - 1.
* @param {number} [s=0] - The saturation, in the range 0 - 1.
* @param {number} [l=0] - The lightness, in the range 0 - 1.
* @param {number} [v=0] - The value, in the range 0 - 1.
* @return {object} The resulting object with r, g, b, a properties and h, s, l and v.
*/
createColor: function (r, g, b, a, h, s, l, v) {
var out = { r: r || 0, g: g || 0, b: b || 0, a: a || 1, h: h || 0, s: s || 0, l: l || 0, v: v || 0, color: 0 };
out.rgba = 'rgba(' + out.r + ',' + out.g + ',' + out.b + ',' + out.a + ')';
return out;
},
/**
* Takes a color object and updates the rgba property.
*
* @method Phaser.Color.updateColor
* @static
* @param {object} out - The color object to update.
* @returns {number} A native color value integer (format: 0xAARRGGBB).
*/
updateColor: function (out) {
out.rgba = 'rgba(' + out.r + ',' + out.g + ',' + out.b + ',' + out.a + ')';
return out;
},
/**
* Given an alpha and 3 color values this will return an integer representation of it.
*
* @method Phaser.Color.getColor32
* @static
* @param {number} a - The alpha color component, in the range 0 - 255.
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @returns {number} A native color value integer (format: 0xAARRGGBB).
*/
getColor32: function (a, r, g, b) {
return a << 24 | r << 16 | g << 8 | b;
},
/**
* Given 3 color values this will return an integer representation of it.
*
* @method Phaser.Color.getColor
* @static
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @returns {number} A native color value integer (format: 0xRRGGBB).
*/
getColor: function (r, g, b) {
return r << 16 | g << 8 | b;
},
/**
* Converts the given color values into a string.
* If prefix was '#' it will be in the format `#RRGGBB` otherwise `0xAARRGGBB`.
*
* @method Phaser.Color.RGBtoString
* @static
* @param {number} r - The red color component, in the range 0 - 255.
* @param {number} g - The green color component, in the range 0 - 255.
* @param {number} b - The blue color component, in the range 0 - 255.
* @param {number} [a=255] - The alpha color component, in the range 0 - 255.
* @param {string} [prefix='#'] - The prefix used in the return string. If '#' it will return `#RRGGBB`, else `0xAARRGGBB`.
* @return {string} A string containing the color values. If prefix was '#' it will be in the format `#RRGGBB` otherwise `0xAARRGGBB`.
*/
RGBtoString: function (r, g, b, a, prefix) {
if (typeof a === 'undefined') { a = 255; }
if (typeof prefix === 'undefined') { prefix = '#'; }
if (prefix === '#')
{
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
else
{
return '0x' + Phaser.Color.componentToHex(a) + Phaser.Color.componentToHex(r) + Phaser.Color.componentToHex(g) + Phaser.Color.componentToHex(b);
}
},
/**
* Converts a hex string into an integer color value.
*
* @method Phaser.Color.hexToRGB
* @static
* @param {string} hex - The hex string to convert. Can be in the short-hand format `#03f` or `#0033ff`.
* @return {number} The rgb color value in the format 0xAARRGGBB.
*/
hexToRGB: function (hex) {
var rgb = Phaser.Color.hexToColor(hex);
if (rgb)
{
return Phaser.Color.getColor32(rgb.a, rgb.r, rgb.g, rgb.b);
}
},
/**
* Converts a hex string into a Phaser Color object.
*
* @method Phaser.Color.hexToColor
* @static
* @param {string} hex - The hex string to convert. Can be in the short-hand format `#03f` or `#0033ff`.
* @param {object} [out] - An object into which 3 properties will be created: r, g and b. If not provided a new object will be created.
* @return {object} An object with the red, green and blue values set in the r, g and b properties.
*/
hexToColor: function (hex, out) {
if (!out)
{
out = Phaser.Color.createColor();
}
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (result)
{
out.r = parseInt(result[1], 16);
out.g = parseInt(result[2], 16);
out.b = parseInt(result[3], 16);
}
return out;
},
/**
* Return a string containing a hex representation of the given color component.
*
* @method Phaser.Color.componentToHex
* @static
* @param {number} color - The color channel to get the hex value for, must be a value between 0 and 255.
* @returns {string} A string of length 2 characters, i.e. 255 = ff, 100 = 64.
*/
componentToHex: function (color) {
var hex = color.toString(16);
return hex.length == 1 ? "0" + hex : hex;
},
/**
* Get HSV color wheel values in an array which will be 360 elements in size.
*
* @method Phaser.Color.HSVColorWheel
* @static
* @param {number} [s=1] - The saturation, in the range 0 - 1.
* @param {number} [v=1] - The value, in the range 0 - 1.
* @return {array} An array containing 360 elements corresponding to the HSV color wheel.
*/
HSVColorWheel: function (s, v) {
if (typeof s === 'undefined') { s = 1.0; }
if (typeof v === 'undefined') { v = 1.0; }
var colors = [];
for (var c = 0; c <= 359; c++)
{
colors.push(Phaser.Color.HSVtoRGB(c / 359, s, v));
}
return colors;
},
/**
* Get HSL color wheel values in an array which will be 360 elements in size.
*
* @method Phaser.Color.HSLColorWheel
* @static
* @param {number} [s=0.5] - The saturation, in the range 0 - 1.
* @param {number} [l=0.5] - The lightness, in the range 0 - 1.
* @return {array} An array containing 360 elements corresponding to the HSL color wheel.
*/
HSLColorWheel: function (s, l) {
if (typeof s === 'undefined') { s = 0.5; }
if (typeof l === 'undefined') { l = 0.5; }
var colors = [];
for (var c = 0; c <= 359; c++)
{
colors.push(Phaser.Color.HSLtoRGB(c / 359, s, l));
}
return colors;
},
/**
* Interpolates the two given colours based on the supplied step and currentStep properties.
*
* @method Phaser.Color.interpolateColor
* @static
* @param {number} color1 - The first color value.
* @param {number} color2 - The second color value.
* @param {number} steps - The number of steps to run the interpolation over.
* @param {number} currentStep - The currentStep value. If the interpolation will take 100 steps, a currentStep value of 50 would be half-way between the two.
* @param {number} alpha - The alpha of the returned color.
* @returns {number} The interpolated color value.
*/
interpolateColor: function (color1, color2, steps, currentStep, alpha) {
if (typeof alpha === "undefined") { alpha = 255; }
var src1 = Phaser.Color.getRGB(color1);
var src2 = Phaser.Color.getRGB(color2);
var r = (((src2.red - src1.red) * currentStep) / steps) + src1.red;
var g = (((src2.green - src1.green) * currentStep) / steps) + src1.green;
var b = (((src2.blue - src1.blue) * currentStep) / steps) + src1.blue;
return Phaser.Color.getColor32(alpha, r, g, b);
},
/**
* Interpolates the two given colours based on the supplied step and currentStep properties.
* @method Phaser.Color.interpolateColorWithRGB
* @static
* @param {number} color - The first color value.
* @param {number} r - The red color value, between 0 and 0xFF (255).
* @param {number} g - The green color value, between 0 and 0xFF (255).
* @param {number} b - The blue color value, between 0 and 0xFF (255).
* @param {number} steps - The number of steps to run the interpolation over.
* @param {number} currentStep - The currentStep value. If the interpolation will take 100 steps, a currentStep value of 50 would be half-way between the two.
* @returns {number} The interpolated color value.
*/
interpolateColorWithRGB: function (color, r, g, b, steps, currentStep) {
var src = Phaser.Color.getRGB(color);
var or = (((r - src.red) * currentStep) / steps) + src.red;
var og = (((g - src.green) * currentStep) / steps) + src.green;
var ob = (((b - src.blue) * currentStep) / steps) + src.blue;
return Phaser.Color.getColor(or, og, ob);
},
/**
* Interpolates the two given colours based on the supplied step and currentStep properties.
* @method Phaser.Color.interpolateRGB
* @static
* @param {number} r1 - The red color value, between 0 and 0xFF (255).
* @param {number} g1 - The green color value, between 0 and 0xFF (255).
* @param {number} b1 - The blue color value, between 0 and 0xFF (255).
* @param {number} r2 - The red color value, between 0 and 0xFF (255).
* @param {number} g2 - The green color value, between 0 and 0xFF (255).
* @param {number} b2 - The blue color value, between 0 and 0xFF (255).
* @param {number} steps - The number of steps to run the interpolation over.
* @param {number} currentStep - The currentStep value. If the interpolation will take 100 steps, a currentStep value of 50 would be half-way between the two.
* @returns {number} The interpolated color value.
*/
interpolateRGB: function (r1, g1, b1, r2, g2, b2, steps, currentStep) {
var r = (((r2 - r1) * currentStep) / steps) + r1;
var g = (((g2 - g1) * currentStep) / steps) + g1;
var b = (((b2 - b1) * currentStep) / steps) + b1;
return Phaser.Color.getColor(r, g, b);
},
/**
* Returns a random color value between black and white
* Set the min value to start each channel from the given offset.
* Set the max value to restrict the maximum color used per channel.
*
* @method Phaser.Color.getRandomColor
* @static
* @param {number} min - The lowest value to use for the color.
* @param {number} max - The highest value to use for the color.
* @param {number} alpha - The alpha value of the returning color (default 255 = fully opaque).
* @returns {number} 32-bit color value with alpha.
*/
getRandomColor: function (min, max, alpha) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 255; }
if (typeof alpha === "undefined") { alpha = 255; }
// Sanity checks
if (max > 255 || min > max)
{
return Phaser.Color.getColor(255, 255, 255);
}
var red = min + Math.round(Math.random() * (max - min));
var green = min + Math.round(Math.random() * (max - min));
var blue = min + Math.round(Math.random() * (max - min));
return Phaser.Color.getColor32(alpha, red, green, blue);
},
/**
* Return the component parts of a color as an Object with the properties alpha, red, green, blue.
*
* Alpha will only be set if it exist in the given color (0xAARRGGBB)
*
* @method Phaser.Color.getRGB
* @static
* @param {number} color - Color in RGB (0xRRGGBB) or ARGB format (0xAARRGGBB).
* @returns {object} An Object with properties: alpha, red, green, blue (also r, g, b and a). Alpha will only be present if a color value > 16777215 was given.
*/
getRGB: function (color) {
if (color > 16777215)
{
// The color value has an alpha component
return {
alpha: color >>> 24,
red: color >> 16 & 0xFF,
green: color >> 8 & 0xFF,
blue: color & 0xFF,
a: color >>> 24,
r: color >> 16 & 0xFF,
g: color >> 8 & 0xFF,
b: color & 0xFF
};
}
else
{
return {
alpha: 255,
red: color >> 16 & 0xFF,
green: color >> 8 & 0xFF,
blue: color & 0xFF,
a: 255,
r: color >> 16 & 0xFF,
g: color >> 8 & 0xFF,
b: color & 0xFF
};
}
},
/**
* Returns a CSS friendly string value from the given color.
*
* @method Phaser.Color.getWebRGB
* @static
* @param {number} color - Color in RGB (0xRRGGBB) or ARGB format (0xAARRGGBB).
* @returns {string} A string in the format: 'rgba(r,g,b,a)'
*/
getWebRGB: function (color) {
var rgb = Phaser.Color.getRGB(color);
return 'rgba(' + rgb.r.toString() + ',' + rgb.g.toString() + ',' + rgb.b.toString() + ',' + rgb.a.toString() + ')';
},
/**
* Given a native color value (in the format 0xAARRGGBB) this will return the Alpha component, as a value between 0 and 255.
*
* @method Phaser.Color.getAlpha
* @static
* @param {number} color - In the format 0xAARRGGBB.
* @returns {number} The Alpha component of the color, will be between 0 and 1 (0 being no Alpha (opaque), 1 full Alpha (transparent)).
*/
getAlpha: function (color) {
return color >>> 24;
},
/**
* Given a native color value (in the format 0xAARRGGBB) this will return the Alpha component as a value between 0 and 1.
*
* @method Phaser.Color.getAlphaFloat
* @static
* @param {number} color - In the format 0xAARRGGBB.
* @returns {number} The Alpha component of the color, will be between 0 and 1 (0 being no Alpha (opaque), 1 full Alpha (transparent)).
*/
getAlphaFloat: function (color) {
return (color >>> 24) / 255;
},
/**
* Given a native color value (in the format 0xAARRGGBB) this will return the Red component, as a value between 0 and 255.
*
* @method Phaser.Color.getRed
* @static
* @param {number} color In the format 0xAARRGGBB.
* @returns {number} The Red component of the color, will be between 0 and 255 (0 being no color, 255 full Red).
*/
getRed: function (color) {
return color >> 16 & 0xFF;
},
/**
* Given a native color value (in the format 0xAARRGGBB) this will return the Green component, as a value between 0 and 255.
*
* @method Phaser.Color.getGreen
* @static
* @param {number} color - In the format 0xAARRGGBB.
* @returns {number} The Green component of the color, will be between 0 and 255 (0 being no color, 255 full Green).
*/
getGreen: function (color) {
return color >> 8 & 0xFF;
},
/**
* Given a native color value (in the format 0xAARRGGBB) this will return the Blue component, as a value between 0 and 255.
*
* @method Phaser.Color.getBlue
* @static
* @param {number} color - In the format 0xAARRGGBB.
* @returns {number} The Blue component of the color, will be between 0 and 255 (0 being no color, 255 full Blue).
*/
getBlue: function (color) {
return color & 0xFF;
},
// The following are all DEPRECATED
/**
* DEPRECATED: This method will be removed in Phaser 2.1.
* Returns a string containing handy information about the given color including string hex value,
* RGB format information. Each section starts on a newline, 3 lines in total.
*
* @method Phaser.Color.getColorInfo
* @static
* @param {number} color - A color value in the format 0xAARRGGBB.
* @returns {string} String containing the 3 lines of information.
*/
getColorInfo: function (color) {
var argb = Phaser.Color.getRGB(color);
// Hex format
var result = Phaser.Color.RGBtoHexstring(color) + "\n";
// RGB format
result = result.concat("Alpha: " + argb.alpha + " Red: " + argb.red + " Green: " + argb.green + " Blue: " + argb.blue) + "\n";
return result;
},
/**
* DEPRECATED: This method will be removed in Phaser 2.1. Please use Phaser.Color.RGBtoString instead.
* Return a string representation of the color in the format 0xAARRGGBB.
*
* @method Phaser.Color.RGBtoHexstring
* @static
* @param {number} color - The color to get the string representation for
* @returns {string} A string of length 10 characters in the format 0xAARRGGBB
*/
RGBtoHexstring: function (color) {
var argb = Phaser.Color.getRGB(color);
return "0x" + Phaser.Color.colorToHexstring(argb.alpha) + Phaser.Color.colorToHexstring(argb.red) + Phaser.Color.colorToHexstring(argb.green) + Phaser.Color.colorToHexstring(argb.blue);
},
/**
* DEPRECATED: This method will be removed in Phaser 2.1. Please use Phaser.Color.RGBtoString instead.
* Return a string representation of the color in the format #RRGGBB.
*
* @method Phaser.Color.RGBtoWebstring
* @static
* @param {number} color - The color to get the string representation for.
* @returns {string} A string of length 10 characters in the format 0xAARRGGBB.
*/
RGBtoWebstring: function (color) {
var argb = Phaser.Color.getRGB(color);
return "#" + Phaser.Color.colorToHexstring(argb.red) + Phaser.Color.colorToHexstring(argb.green) + Phaser.Color.colorToHexstring(argb.blue);
},
/**
* DEPRECATED: This method will be removed in Phaser 2.1. Please use Phaser.Color.componentToHex instead.
* Return a string containing a hex representation of the given color.
*
* @method Phaser.Color.colorToHexstring
* @static
* @param {number} color - The color channel to get the hex value for, must be a value between 0 and 255).
* @returns {string} A string of length 2 characters, i.e. 255 = FF, 0 = 00.
*/
colorToHexstring: function (color) {
var digits = "0123456789ABCDEF";
var lsd = color % 16;
var msd = (color - lsd) / 16;
var hexified = digits.charAt(msd) + digits.charAt(lsd);
return hexified;
}
};

738
src/utils/Debug.js Normal file
View File

@@ -0,0 +1,738 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2014 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* A collection of methods for displaying debug information about game objects.
* If your game is running in WebGL then Debug will create a Sprite that is placed at the top of the Stage display list and bind a canvas texture
* to it, which must be uploaded every frame. Be advised: this is expenive.
* If your game is using a Canvas renderer then the debug information is literally drawn on the top of the active game canvas and no Sprite is used.
*
* @class Phaser.Utils.Debug
* @constructor
* @param {Phaser.Game} game - A reference to the currently running game.
*/
Phaser.Utils.Debug = function (game) {
/**
* @property {Phaser.Game} game - A reference to the currently running Game.
*/
this.game = game;
/**
* @property {PIXI.Sprite} sprite - If debugging in WebGL mode we need this.
*/
this.sprite = null;
/**
* @property {HTMLCanvasElement} canvas - The canvas to which this BitmapData draws.
*/
this.canvas = null;
/**
* @property {PIXI.BaseTexture} baseTexture - Required Pixi var.
*/
this.baseTexture = null;
/**
* @property {PIXI.Texture} texture - Required Pixi var.
*/
this.texture = null;
/**
* @property {Phaser.Frame} textureFrame - Dimensions of the renderable area.
*/
this.textureFrame = null;
/**
* @property {CanvasRenderingContext2D} context - The 2d context of the canvas.
*/
this.context = null;
/**
* @property {string} font - The font that the debug information is rendered in.
* @default '14px Courier'
*/
this.font = '14px Courier';
/**
* @property {number} columnWidth - The spacing between columns.
*/
this.columnWidth = 100;
/**
* @property {number} lineHeight - The line height between the debug text.
*/
this.lineHeight = 16;
/**
* @property {boolean} renderShadow - Should the text be rendered with a slight shadow? Makes it easier to read on different types of background.
*/
this.renderShadow = true;
/**
* @property {Context} currentX - The current X position the debug information will be rendered at.
* @default
*/
this.currentX = 0;
/**
* @property {number} currentY - The current Y position the debug information will be rendered at.
* @default
*/
this.currentY = 0;
/**
* @property {number} currentAlpha - The current alpha the debug information will be rendered at.
* @default
*/
this.currentAlpha = 1;
/**
* @property {boolean} dirty - Does the canvas need re-rendering?
*/
this.dirty = false;
};
Phaser.Utils.Debug.prototype = {
/**
* Internal method that boots the debug displayer.
*
* @method Phaser.Utils.Debug#boot
* @protected
*/
boot: function () {
if (this.game.renderType === Phaser.CANVAS)
{
this.context = this.game.context;
}
else
{
this.canvas = Phaser.Canvas.create(this.game.width, this.game.height, '', true);
this.context = this.canvas.getContext('2d');
this.baseTexture = new PIXI.BaseTexture(this.canvas);
this.texture = new PIXI.Texture(this.baseTexture);
this.textureFrame = new Phaser.Frame(0, 0, 0, this.game.width, this.game.height, 'debug', this.game.rnd.uuid());
this.sprite = this.game.make.image(0, 0, this.texture, this.textureFrame);
this.game.stage.addChild(this.sprite);
}
},
/**
* Internal method that clears the canvas (if a Sprite) ready for a new debug session.
*
* @method Phaser.Utils.Debug#preUpdate
*/
preUpdate: function () {
if (this.dirty && this.sprite)
{
this.context.clearRect(0, 0, this.game.width, this.game.height);
this.dirty = false;
}
},
/**
* Internal method that resets and starts the debug output values.
*
* @method Phaser.Utils.Debug#start
* @protected
* @param {number} [x=0] - The X value the debug info will start from.
* @param {number} [y=0] - The Y value the debug info will start from.
* @param {string} [color='rgb(255,255,255)'] - The color the debug text will drawn in.
* @param {number} [columnWidth=0] - The spacing between columns.
*/
start: function (x, y, color, columnWidth) {
if (typeof x !== 'number') { x = 0; }
if (typeof y !== 'number') { y = 0; }
color = color || 'rgb(255,255,255)';
if (typeof columnWidth === 'undefined') { columnWidth = 0; }
this.currentX = x;
this.currentY = y;
this.currentColor = color;
this.currentAlpha = this.context.globalAlpha;
this.columnWidth = columnWidth;
if (this.sprite)
{
this.dirty = true;
}
this.context.save();
this.context.setTransform(1, 0, 0, 1, 0, 0);
this.context.strokeStyle = color;
this.context.fillStyle = color;
this.context.font = this.font;
this.context.globalAlpha = 1;
},
/**
* Internal method that stops the debug output.
*
* @method Phaser.Utils.Debug#stop
* @protected
*/
stop: function () {
this.context.restore();
this.context.globalAlpha = this.currentAlpha;
if (this.sprite)
{
PIXI.updateWebGLTexture(this.baseTexture, this.game.renderer.gl);
}
},
/**
* Internal method that outputs a single line of text split over as many columns as needed, one per parameter.
*
* @method Phaser.Utils.Debug#line
* @protected
*/
line: function () {
var x = this.currentX;
for (var i = 0; i < arguments.length; i++)
{
if (this.renderShadow)
{
this.context.fillStyle = 'rgb(0,0,0)';
this.context.fillText(arguments[i], x + 1, this.currentY + 1);
this.context.fillStyle = this.currentColor;
}
this.context.fillText(arguments[i], x, this.currentY);
x += this.columnWidth;
}
this.currentY += this.lineHeight;
},
/**
* Render Sound information, including decoded state, duration, volume and more.
*
* @method Phaser.Utils.Debug#soundInfo
* @param {Phaser.Sound} sound - The sound object to debug.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
soundInfo: function (sound, x, y, color) {
this.start(x, y, color);
this.line('Sound: ' + sound.key + ' Locked: ' + sound.game.sound.touchLocked);
this.line('Is Ready?: ' + this.game.cache.isSoundReady(sound.key) + ' Pending Playback: ' + sound.pendingPlayback);
this.line('Decoded: ' + sound.isDecoded + ' Decoding: ' + sound.isDecoding);
this.line('Total Duration: ' + sound.totalDuration + ' Playing: ' + sound.isPlaying);
this.line('Time: ' + sound.currentTime);
this.line('Volume: ' + sound.volume + ' Muted: ' + sound.mute);
this.line('WebAudio: ' + sound.usingWebAudio + ' Audio: ' + sound.usingAudioTag);
if (sound.currentMarker !== '')
{
this.line('Marker: ' + sound.currentMarker + ' Duration: ' + sound.duration + ' (ms: ' + sound.durationMS + ')');
this.line('Start: ' + sound.markers[sound.currentMarker].start + ' Stop: ' + sound.markers[sound.currentMarker].stop);
this.line('Position: ' + sound.position);
}
this.stop();
},
/**
* Render camera information including dimensions and location.
*
* @method Phaser.Utils.Debug#cameraInfo
* @param {Phaser.Camera} camera - The Phaser.Camera to show the debug information for.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
cameraInfo: function (camera, x, y, color) {
this.start(x, y, color);
this.line('Camera (' + camera.width + ' x ' + camera.height + ')');
this.line('X: ' + camera.x + ' Y: ' + camera.y);
this.line('Bounds x: ' + camera.bounds.x + ' Y: ' + camera.bounds.y + ' w: ' + camera.bounds.width + ' h: ' + camera.bounds.height);
this.line('View x: ' + camera.view.x + ' Y: ' + camera.view.y + ' w: ' + camera.view.width + ' h: ' + camera.view.height);
this.stop();
},
/**
* Render Timer information.
*
* @method Phaser.Utils.Debug#timer
* @param {Phaser.Timer} timer - The Phaser.Timer to show the debug information for.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
timer: function (timer, x, y, color) {
this.start(x, y, color);
this.line('Timer (running: ' + timer.running + ' expired: ' + timer.expired + ')');
this.line('Next Tick: ' + timer.next + ' Duration: ' + timer.duration);
this.line('Paused: ' + timer.paused + ' Length: ' + timer.length);
this.stop();
},
/**
* Renders the Pointer.circle object onto the stage in green if down or red if up along with debug text.
*
* @method Phaser.Utils.Debug#pointer
* @param {Phaser.Pointer} pointer - The Pointer you wish to display.
* @param {boolean} [hideIfUp=false] - Doesn't render the circle if the pointer is up.
* @param {string} [downColor='rgba(0,255,0,0.5)'] - The color the circle is rendered in if down.
* @param {string} [upColor='rgba(255,0,0,0.5)'] - The color the circle is rendered in if up (and hideIfUp is false).
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
pointer: function (pointer, hideIfUp, downColor, upColor, color) {
if (pointer == null)
{
return;
}
if (typeof hideIfUp === 'undefined') { hideIfUp = false; }
downColor = downColor || 'rgba(0,255,0,0.5)';
upColor = upColor || 'rgba(255,0,0,0.5)';
if (hideIfUp === true && pointer.isUp === true)
{
return;
}
this.start(pointer.x, pointer.y - 100, color);
this.context.beginPath();
this.context.arc(pointer.x, pointer.y, pointer.circle.radius, 0, Math.PI * 2);
if (pointer.active)
{
this.context.fillStyle = downColor;
}
else
{
this.context.fillStyle = upColor;
}
this.context.fill();
this.context.closePath();
// Render the points
this.context.beginPath();
this.context.moveTo(pointer.positionDown.x, pointer.positionDown.y);
this.context.lineTo(pointer.position.x, pointer.position.y);
this.context.lineWidth = 2;
this.context.stroke();
this.context.closePath();
// Render the text
this.line('ID: ' + pointer.id + " Active: " + pointer.active);
this.line('World X: ' + pointer.worldX + " World Y: " + pointer.worldY);
this.line('Screen X: ' + pointer.x + " Screen Y: " + pointer.y);
this.line('Duration: ' + pointer.duration + " ms");
this.line('is Down: ' + pointer.isDown + " is Up: " + pointer.isUp);
this.stop();
},
/**
* Render Sprite Input Debug information.
*
* @method Phaser.Utils.Debug#spriteInputInfo
* @param {Phaser.Sprite|Phaser.Image} sprite - The sprite to display the input data for.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
spriteInputInfo: function (sprite, x, y, color) {
this.start(x, y, color);
this.line('Sprite Input: (' + sprite.width + ' x ' + sprite.height + ')');
this.line('x: ' + sprite.input.pointerX().toFixed(1) + ' y: ' + sprite.input.pointerY().toFixed(1));
this.line('over: ' + sprite.input.pointerOver() + ' duration: ' + sprite.input.overDuration().toFixed(0));
this.line('down: ' + sprite.input.pointerDown() + ' duration: ' + sprite.input.downDuration().toFixed(0));
this.line('just over: ' + sprite.input.justOver() + ' just out: ' + sprite.input.justOut());
this.stop();
},
/**
* Renders Phaser.Key object information.
*
* @method Phaser.Utils.Debug#key
* @param {Phaser.Key} key - The Key to render the information for.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
key: function (key, x, y, color) {
this.start(x, y, color, 150);
this.line('Key:', key.keyCode, 'isDown:', key.isDown);
this.line('justPressed:', key.justPressed(), 'justReleased:', key.justReleased());
this.line('Time Down:', key.timeDown.toFixed(0), 'duration:', key.duration.toFixed(0));
this.stop();
},
/**
* Render debug information about the Input object.
*
* @method Phaser.Utils.Debug#inputInfo
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
inputInfo: function (x, y, color) {
this.start(x, y, color);
this.line('Input');
this.line('X: ' + this.game.input.x + ' Y: ' + this.game.input.y);
this.line('World X: ' + this.game.input.worldX + ' World Y: ' + this.game.input.worldY);
this.line('Scale X: ' + this.game.input.scale.x.toFixed(1) + ' Scale Y: ' + this.game.input.scale.x.toFixed(1));
this.line('Screen X: ' + this.game.input.activePointer.screenX + ' Screen Y: ' + this.game.input.activePointer.screenY);
this.stop();
},
/**
* Renders the Sprites bounds. Note: This is really expensive as it has to calculate the bounds every time you call it!
*
* @method Phaser.Utils.Debug#spriteBounds
* @param {Phaser.Sprite|Phaser.Image} sprite - The sprite to display the bounds of.
* @param {string} [color] - Color of the debug info to be rendered (format is css color string).
* @param {boolean} [filled=true] - Render the rectangle as a fillRect (default, true) or a strokeRect (false)
*/
spriteBounds: function (sprite, color, filled) {
var bounds = sprite.getBounds();
bounds.x += this.game.camera.x;
bounds.y += this.game.camera.y;
this.rectangle(bounds, color, filled);
},
/**
* Render debug infos (including name, bounds info, position and some other properties) about the Sprite.
*
* @method Phaser.Utils.Debug#spriteInfo
* @param {Phaser.Sprite} sprite - The Sprite to display the information of.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
spriteInfo: function (sprite, x, y, color) {
this.start(x, y, color);
this.line('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') anchor: ' + sprite.anchor.x + ' x ' + sprite.anchor.y);
this.line('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1));
this.line('angle: ' + sprite.angle.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1));
this.line('visible: ' + sprite.visible + ' in camera: ' + sprite.inCamera);
this.stop();
},
/**
* Renders the sprite coordinates in local, positional and world space.
*
* @method Phaser.Utils.Debug#spriteCoords
* @param {Phaser.Sprite|Phaser.Image} sprite - The sprite to display the coordinates for.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
spriteCoords: function (sprite, x, y, color) {
this.start(x, y, color, 100);
if (sprite.name)
{
this.line(sprite.name);
}
this.line('x:', sprite.x.toFixed(2), 'y:', sprite.y.toFixed(2));
this.line('pos x:', sprite.position.x.toFixed(2), 'pos y:', sprite.position.y.toFixed(2));
this.line('world x:', sprite.world.x.toFixed(2), 'world y:', sprite.world.y.toFixed(2));
this.stop();
},
/**
* Renders Line information in the given color.
*
* @method Phaser.Utils.Debug#lineInfo
* @param {Phaser.Line} line - The Line to display the data for.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
lineInfo: function (line, x, y, color) {
this.start(x, y, color, 80);
this.line('start.x:', line.start.x.toFixed(2), 'start.y:', line.start.y.toFixed(2));
this.line('end.x:', line.end.x.toFixed(2), 'end.y:', line.end.y.toFixed(2));
this.line('length:', line.length.toFixed(2), 'angle:', line.angle);
this.stop();
},
/**
* Renders a single pixel at the given size.
*
* @method Phaser.Utils.Debug#pixel
* @param {number} x - X position of the pixel to be rendered.
* @param {number} y - Y position of the pixel to be rendered.
* @param {string} [color] - Color of the pixel (format is css color string).
* @param {number} [size=2] - The 'size' to render the pixel at.
*/
pixel: function (x, y, color, size) {
size = size || 2;
this.start();
this.context.fillStyle = color;
this.context.fillRect(x, y, size, size);
this.stop();
},
/**
* Renders a Phaser geometry object including Rectangle, Circle, Point or Line.
*
* @method Phaser.Utils.Debug#geom
* @param {Phaser.Rectangle|Phaser.Circle|Phaser.Point|Phaser.Line} object - The geometry object to render.
* @param {string} [color] - Color of the debug info to be rendered (format is css color string).
* @param {boolean} [filled=true] - Render the objected as a filled (default, true) or a stroked (false)
* @param {number} [forceType=0] - Force rendering of a specific type. If 0 no type will be forced, otherwise 1 = Rectangle, 2 = Circle, 3 = Point and 4 = Line.
*/
geom: function (object, color, filled, forceType) {
if (typeof filled === 'undefined') { filled = true; }
if (typeof forceType === 'undefined') { forceType = 0; }
color = color || 'rgba(0,255,0,0.4)';
this.start();
this.context.fillStyle = color;
this.context.strokeStyle = color;
if (object instanceof Phaser.Rectangle || forceType === 1)
{
if (filled)
{
this.context.fillRect(object.x - this.game.camera.x, object.y - this.game.camera.y, object.width, object.height);
}
else
{
this.context.strokeRect(object.x - this.game.camera.x, object.y - this.game.camera.y, object.width, object.height);
}
}
else if (object instanceof Phaser.Circle || forceType === 2)
{
this.context.beginPath();
this.context.arc(object.x - this.game.camera.x, object.y - this.game.camera.y, object.radius, 0, Math.PI * 2, false);
this.context.closePath();
if (filled)
{
this.context.fill();
}
else
{
this.context.stroke();
}
}
else if (object instanceof Phaser.Point || forceType === 3)
{
this.context.fillRect(object.x - this.game.camera.x, object.y - this.game.camera.y, 4, 4);
}
else if (object instanceof Phaser.Line || forceType === 4)
{
this.context.lineWidth = 1;
this.context.beginPath();
this.context.moveTo((object.start.x + 0.5) - this.game.camera.x, (object.start.y + 0.5) - this.game.camera.y);
this.context.lineTo((object.end.x + 0.5) - this.game.camera.x, (object.end.y + 0.5) - this.game.camera.y);
this.context.closePath();
this.context.stroke();
}
this.stop();
},
/**
* Renders a Rectangle.
*
* @method Phaser.Utils.Debug#geom
* @param {Phaser.Rectangle|object} object - The geometry object to render.
* @param {string} [color] - Color of the debug info to be rendered (format is css color string).
* @param {boolean} [filled=true] - Render the objected as a filled (default, true) or a stroked (false)
*/
rectangle: function (object, color, filled) {
if (typeof filled === 'undefined') { filled = true; }
color = color || 'rgba(0, 255, 0, 0.4)';
this.start();
if (filled)
{
this.context.fillStyle = color;
this.context.fillRect(object.x - this.game.camera.x, object.y - this.game.camera.y, object.width, object.height);
}
else
{
this.context.strokeStyle = color;
this.context.strokeRect(object.x - this.game.camera.x, object.y - this.game.camera.y, object.width, object.height);
}
this.stop();
},
/**
* Render a string of text.
*
* @method Phaser.Utils.Debug#text
* @param {string} text - The line of text to draw.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color] - Color of the debug info to be rendered (format is css color string).
* @param {string} [font] - The font of text to draw.
*/
text: function (text, x, y, color, font) {
color = color || 'rgb(255,255,255)';
font = font || '16px Courier';
this.start();
this.context.font = font;
if (this.renderShadow)
{
this.context.fillStyle = 'rgb(0,0,0)';
this.context.fillText(text, x + 1, y + 1);
}
this.context.fillStyle = color;
this.context.fillText(text, x, y);
this.stop();
},
/**
* Visually renders a QuadTree to the display.
*
* @method Phaser.Utils.Debug#quadTree
* @param {Phaser.QuadTree} quadtree - The quadtree to render.
* @param {string} color - The color of the lines in the quadtree.
*/
quadTree: function (quadtree, color) {
color = color || 'rgba(255,0,0,0.3)';
this.start();
var bounds = quadtree.bounds;
if (quadtree.nodes.length === 0)
{
this.context.strokeStyle = color;
this.context.strokeRect(bounds.x, bounds.y, bounds.width, bounds.height);
this.text('size: ' + quadtree.objects.length, bounds.x + 4, bounds.y + 16, 'rgb(0,200,0)', '12px Courier');
this.context.strokeStyle = 'rgb(0,255,0)';
for (var i = 0; i < quadtree.objects.length; i++)
{
this.context.strokeRect(quadtree.objects[i].x, quadtree.objects[i].y, quadtree.objects[i].width, quadtree.objects[i].height);
}
}
else
{
for (var i = 0; i < quadtree.nodes.length; i++)
{
this.quadTree(quadtree.nodes[i]);
}
}
this.stop();
},
/**
* Render a Sprites Physics body if it has one set. Note this only works for Arcade Physics.
* To display a P2 body you should enable debug mode on the body when creating it.
*
* @method Phaser.Utils.Debug#body
* @param {Phaser.Sprite} sprite - The sprite whos body will be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
* @param {boolean} [filled=true] - Render the objected as a filled (default, true) or a stroked (false)
*/
body: function (sprite, color, filled) {
if (sprite.body)
{
if (sprite.body.type === Phaser.Physics.ARCADE)
{
this.start();
Phaser.Physics.Arcade.Body.render(this.context, sprite.body, color, filled);
this.stop();
}
}
},
/**
* Render a Sprites Physic Body information.
*
* @method Phaser.Utils.Debug#bodyInfo
* @param {Phaser.Sprite} sprite - The sprite to be rendered.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
bodyInfo: function (sprite, x, y, color) {
if (sprite.body)
{
if (sprite.body.type === Phaser.Physics.ARCADE)
{
this.start(x, y, color, 210);
Phaser.Physics.Arcade.Body.renderBodyInfo(this, sprite.body);
this.stop();
}
}
}
};
Phaser.Utils.Debug.prototype.constructor = Phaser.Utils.Debug;

440
src/utils/Utils.js Normal file
View File

@@ -0,0 +1,440 @@
/* 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}
*/
/**
* @class Phaser.Utils
* @static
*/
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;
},
/**
* 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
*/
rotateArray: 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;
},
/**
* Get a unit dimension from a string.
*
* @method Phaser.Utils.parseDimension
* @param {string|number} size - The size to parse.
* @param {number} dimension - The window dimension to check.
* @return {number} The parsed dimension.
*/
parseDimension: function (size, dimension) {
var f = 0;
var px = 0;
if (typeof size === 'string')
{
// %?
if (size.substr(-1) === '%')
{
f = parseInt(size, 10) / 100;
if (dimension === 0)
{
px = window.innerWidth * f;
}
else
{
px = window.innerHeight * f;
}
}
else
{
px = parseInt(size, 10);
}
}
else
{
px = size;
}
return px;
},
/**
* 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.
* @param {number} pad - The string to pad it out with (defaults to a space).
* @param {number} [dir=3] The direction dir = 1 (left), 2 (right), 3 (both).
* @return {string} The padded string
*/
pad: function (str, len, pad, dir) {
if (typeof(len) == "undefined") { var len = 0; }
if (typeof(pad) == "undefined") { var pad = ' '; }
if (typeof(dir) == "undefined") { var dir = 3; }
var padlen = 0;
if (len + 1 >= str.length)
{
switch (dir)
{
case 1:
str = new Array(len + 1 - str.length).join(pad) + str;
break;
case 3:
var right = Math.ceil((padlen = len - str.length) / 2);
var left = padlen - right;
str = new Array(left+1).join(pad) + str + new Array(right+1).join(pad);
break;
default:
str = str + new Array(len + 1 - str.length).join(pad);
break;
}
}
return str;
},
/**
* 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.
*/
isPlainObject: function (obj) {
// Not plain objects:
// - Any object or value whose internal [[Class]] property is not "[object Object]"
// - DOM nodes
// - window
if (typeof(obj) !== "object" || obj.nodeType || obj === obj.window)
{
return false;
}
// Support: Firefox <20
// The try/catch suppresses exceptions thrown when attempting to access
// the "constructor" property of certain host objects, ie. |window.location|
// https://bugzilla.mozilla.org/show_bug.cgi?id=814622
try {
if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf"))
{
return false;
}
} catch (e) {
return false;
}
// If the function hasn't returned already, we're confident that
// |obj| is a plain object, created by {} or constructed with new Object
return true;
},
/**
* This is a slightly modified version of http://api.jquery.com/jQuery.extend/
* @method Phaser.Utils.extend
* @param {boolean} deep - Perform a deep copy?
* @param {object} target - The target object to copy to.
* @return {object} The extended object.
*/
extend: function () {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if (typeof target === "boolean")
{
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// extend Phaser if only one argument is passed
if (length === i)
{
target = this;
--i;
}
for (; i < length; i++)
{
// Only deal with non-null/undefined values
if ((options = arguments[i]) != null)
{
// Extend the base object
for (name in options)
{
src = target[name];
copy = options[name];
// Prevent never-ending loop
if (target === copy)
{
continue;
}
// Recurse if we're merging plain objects or arrays
if (deep && copy && (Phaser.Utils.isPlainObject(copy) || (copyIsArray = Array.isArray(copy))))
{
if (copyIsArray)
{
copyIsArray = false;
clone = src && Array.isArray(src) ? src : [];
}
else
{
clone = src && Phaser.Utils.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[name] = Phaser.Utils.extend(deep, clone, copy);
// Don't bring in undefined values
}
else if (copy !== undefined)
{
target[name] = copy;
}
}
}
}
// Return the modified object
return target;
}
};
/**
* 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")
{
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(){};
}