/build/custom/phaser-arcade-physics.js

https://gitlab.com/lobsterhands/phaser · JavaScript · 34313 lines · 15693 code · 6594 blank · 12026 comment · 2653 complexity · 3d0643572fac43e8b7e174e36a9f2ebf MD5 · raw file

  1. /**
  2. * @author Richard Davey <rich@photonstorm.com>
  3. * @copyright 2014 Photon Storm Ltd.
  4. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  5. *
  6. * @overview
  7. *
  8. * Phaser - http://phaser.io
  9. *
  10. * v2.0.3 "Allorallen" - Built: Fri Apr 11 2014 13:08:30
  11. *
  12. * By Richard Davey http://www.photonstorm.com @photonstorm
  13. *
  14. * Phaser is a fun, free and fast 2D game framework for making HTML5 games
  15. * for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
  16. *
  17. * Phaser uses Pixi.js for rendering, created by Mat Groves http://matgroves.com @Doormat23
  18. * Phaser uses p2.js for full-body physics, created by Stefan Hedman https://github.com/schteppe/p2.js @schteppe
  19. * Phaser contains a port of N+ Physics, converted by Richard Davey, original by http://www.metanetsoftware.com
  20. *
  21. * Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel, from which both Phaser
  22. * and my love of framework development originate.
  23. *
  24. * Follow development at http://phaser.io and on our forum
  25. *
  26. * "If you want your children to be intelligent, read them fairy tales."
  27. * "If you want them to be more intelligent, read them more fairy tales."
  28. * -- Albert Einstein
  29. */
  30. /**
  31. * @author Mat Groves http://matgroves.com/ @Doormat23
  32. */
  33. (function(){
  34. var root = this;
  35. /**
  36. * @author Mat Groves http://matgroves.com/ @Doormat23
  37. */
  38. /**
  39. * @module PIXI
  40. */
  41. var PIXI = PIXI || {};
  42. /*
  43. *
  44. * This file contains a lot of pixi consts which are used across the rendering engine
  45. * @class Consts
  46. */
  47. PIXI.WEBGL_RENDERER = 0;
  48. PIXI.CANVAS_RENDERER = 1;
  49. // useful for testing against if your lib is using pixi.
  50. PIXI.VERSION = "v1.5.2";
  51. // the various blend modes supported by pixi
  52. PIXI.blendModes = {
  53. NORMAL:0,
  54. ADD:1,
  55. MULTIPLY:2,
  56. SCREEN:3,
  57. OVERLAY:4,
  58. DARKEN:5,
  59. LIGHTEN:6,
  60. COLOR_DODGE:7,
  61. COLOR_BURN:8,
  62. HARD_LIGHT:9,
  63. SOFT_LIGHT:10,
  64. DIFFERENCE:11,
  65. EXCLUSION:12,
  66. HUE:13,
  67. SATURATION:14,
  68. COLOR:15,
  69. LUMINOSITY:16
  70. };
  71. // the scale modes
  72. PIXI.scaleModes = {
  73. DEFAULT:0,
  74. LINEAR:0,
  75. NEAREST:1
  76. };
  77. // interaction frequency
  78. PIXI.INTERACTION_FREQUENCY = 30;
  79. PIXI.AUTO_PREVENT_DEFAULT = true;
  80. PIXI.RAD_TO_DEG = 180 / Math.PI;
  81. PIXI.DEG_TO_RAD = Math.PI / 180;
  82. /**
  83. * @author Mat Groves http://matgroves.com/ @Doormat23
  84. */
  85. /**
  86. * The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis.
  87. *
  88. * @class Point
  89. * @constructor
  90. * @param x {Number} position of the point on the x axis
  91. * @param y {Number} position of the point on the y axis
  92. */
  93. PIXI.Point = function(x, y)
  94. {
  95. /**
  96. * @property x
  97. * @type Number
  98. * @default 0
  99. */
  100. this.x = x || 0;
  101. /**
  102. * @property y
  103. * @type Number
  104. * @default 0
  105. */
  106. this.y = y || 0;
  107. };
  108. /**
  109. * Creates a clone of this point
  110. *
  111. * @method clone
  112. * @return {Point} a copy of the point
  113. */
  114. PIXI.Point.prototype.clone = function()
  115. {
  116. return new PIXI.Point(this.x, this.y);
  117. };
  118. // constructor
  119. PIXI.Point.prototype.constructor = PIXI.Point;
  120. PIXI.Point.prototype.set = function(x, y)
  121. {
  122. this.x = x || 0;
  123. this.y = y || ( (y !== 0) ? this.x : 0 ) ;
  124. };
  125. /**
  126. * @author Mat Groves http://matgroves.com/
  127. */
  128. /**
  129. * the Rectangle object is an area defined by its position, as indicated by its top-left corner point (x, y) and by its width and its height.
  130. *
  131. * @class Rectangle
  132. * @constructor
  133. * @param x {Number} The X coord of the upper-left corner of the rectangle
  134. * @param y {Number} The Y coord of the upper-left corner of the rectangle
  135. * @param width {Number} The overall width of this rectangle
  136. * @param height {Number} The overall height of this rectangle
  137. */
  138. PIXI.Rectangle = function(x, y, width, height)
  139. {
  140. /**
  141. * @property x
  142. * @type Number
  143. * @default 0
  144. */
  145. this.x = x || 0;
  146. /**
  147. * @property y
  148. * @type Number
  149. * @default 0
  150. */
  151. this.y = y || 0;
  152. /**
  153. * @property width
  154. * @type Number
  155. * @default 0
  156. */
  157. this.width = width || 0;
  158. /**
  159. * @property height
  160. * @type Number
  161. * @default 0
  162. */
  163. this.height = height || 0;
  164. };
  165. /**
  166. * Creates a clone of this Rectangle
  167. *
  168. * @method clone
  169. * @return {Rectangle} a copy of the rectangle
  170. */
  171. PIXI.Rectangle.prototype.clone = function()
  172. {
  173. return new PIXI.Rectangle(this.x, this.y, this.width, this.height);
  174. };
  175. /**
  176. * Checks whether the x and y coordinates passed to this function are contained within this Rectangle
  177. *
  178. * @method contains
  179. * @param x {Number} The X coordinate of the point to test
  180. * @param y {Number} The Y coordinate of the point to test
  181. * @return {Boolean} Whether the x/y coords are within this Rectangle
  182. */
  183. PIXI.Rectangle.prototype.contains = function(x, y)
  184. {
  185. if(this.width <= 0 || this.height <= 0)
  186. return false;
  187. var x1 = this.x;
  188. if(x >= x1 && x <= x1 + this.width)
  189. {
  190. var y1 = this.y;
  191. if(y >= y1 && y <= y1 + this.height)
  192. {
  193. return true;
  194. }
  195. }
  196. return false;
  197. };
  198. // constructor
  199. PIXI.Rectangle.prototype.constructor = PIXI.Rectangle;
  200. PIXI.EmptyRectangle = new PIXI.Rectangle(0,0,0,0);
  201. /**
  202. * @author Adrien Brault <adrien.brault@gmail.com>
  203. */
  204. /**
  205. * @class Polygon
  206. * @constructor
  207. * @param points* {Array<Point>|Array<Number>|Point...|Number...} This can be an array of Points that form the polygon,
  208. * a flat array of numbers that will be interpreted as [x,y, x,y, ...], or the arguments passed can be
  209. * all the points of the polygon e.g. `new PIXI.Polygon(new PIXI.Point(), new PIXI.Point(), ...)`, or the
  210. * arguments passed can be flat x,y values e.g. `new PIXI.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are
  211. * Numbers.
  212. */
  213. PIXI.Polygon = function(points)
  214. {
  215. //if points isn't an array, use arguments as the array
  216. if(!(points instanceof Array))
  217. points = Array.prototype.slice.call(arguments);
  218. //if this is a flat array of numbers, convert it to points
  219. if(typeof points[0] === 'number') {
  220. var p = [];
  221. for(var i = 0, il = points.length; i < il; i+=2) {
  222. p.push(
  223. new PIXI.Point(points[i], points[i + 1])
  224. );
  225. }
  226. points = p;
  227. }
  228. this.points = points;
  229. };
  230. /**
  231. * Creates a clone of this polygon
  232. *
  233. * @method clone
  234. * @return {Polygon} a copy of the polygon
  235. */
  236. PIXI.Polygon.prototype.clone = function()
  237. {
  238. var points = [];
  239. for (var i=0; i<this.points.length; i++) {
  240. points.push(this.points[i].clone());
  241. }
  242. return new PIXI.Polygon(points);
  243. };
  244. /**
  245. * Checks whether the x and y coordinates passed to this function are contained within this polygon
  246. *
  247. * @method contains
  248. * @param x {Number} The X coordinate of the point to test
  249. * @param y {Number} The Y coordinate of the point to test
  250. * @return {Boolean} Whether the x/y coordinates are within this polygon
  251. */
  252. PIXI.Polygon.prototype.contains = function(x, y)
  253. {
  254. var inside = false;
  255. // use some raycasting to test hits
  256. // https://github.com/substack/point-in-polygon/blob/master/index.js
  257. for(var i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {
  258. var xi = this.points[i].x, yi = this.points[i].y,
  259. xj = this.points[j].x, yj = this.points[j].y,
  260. intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
  261. if(intersect) inside = !inside;
  262. }
  263. return inside;
  264. };
  265. // constructor
  266. PIXI.Polygon.prototype.constructor = PIXI.Polygon;
  267. /**
  268. * @author Chad Engler <chad@pantherdev.com>
  269. */
  270. /**
  271. * The Circle object can be used to specify a hit area for displayObjects
  272. *
  273. * @class Circle
  274. * @constructor
  275. * @param x {Number} The X coordinate of the upper-left corner of the framing rectangle of this circle
  276. * @param y {Number} The Y coordinate of the upper-left corner of the framing rectangle of this circle
  277. * @param radius {Number} The radius of the circle
  278. */
  279. PIXI.Circle = function(x, y, radius)
  280. {
  281. /**
  282. * @property x
  283. * @type Number
  284. * @default 0
  285. */
  286. this.x = x || 0;
  287. /**
  288. * @property y
  289. * @type Number
  290. * @default 0
  291. */
  292. this.y = y || 0;
  293. /**
  294. * @property radius
  295. * @type Number
  296. * @default 0
  297. */
  298. this.radius = radius || 0;
  299. };
  300. /**
  301. * Creates a clone of this Circle instance
  302. *
  303. * @method clone
  304. * @return {Circle} a copy of the polygon
  305. */
  306. PIXI.Circle.prototype.clone = function()
  307. {
  308. return new PIXI.Circle(this.x, this.y, this.radius);
  309. };
  310. /**
  311. * Checks whether the x, and y coordinates passed to this function are contained within this circle
  312. *
  313. * @method contains
  314. * @param x {Number} The X coordinate of the point to test
  315. * @param y {Number} The Y coordinate of the point to test
  316. * @return {Boolean} Whether the x/y coordinates are within this polygon
  317. */
  318. PIXI.Circle.prototype.contains = function(x, y)
  319. {
  320. if(this.radius <= 0)
  321. return false;
  322. var dx = (this.x - x),
  323. dy = (this.y - y),
  324. r2 = this.radius * this.radius;
  325. dx *= dx;
  326. dy *= dy;
  327. return (dx + dy <= r2);
  328. };
  329. // constructor
  330. PIXI.Circle.prototype.constructor = PIXI.Circle;
  331. /**
  332. * @author Chad Engler <chad@pantherdev.com>
  333. */
  334. /**
  335. * The Ellipse object can be used to specify a hit area for displayObjects
  336. *
  337. * @class Ellipse
  338. * @constructor
  339. * @param x {Number} The X coordinate of the upper-left corner of the framing rectangle of this ellipse
  340. * @param y {Number} The Y coordinate of the upper-left corner of the framing rectangle of this ellipse
  341. * @param width {Number} The overall width of this ellipse
  342. * @param height {Number} The overall height of this ellipse
  343. */
  344. PIXI.Ellipse = function(x, y, width, height)
  345. {
  346. /**
  347. * @property x
  348. * @type Number
  349. * @default 0
  350. */
  351. this.x = x || 0;
  352. /**
  353. * @property y
  354. * @type Number
  355. * @default 0
  356. */
  357. this.y = y || 0;
  358. /**
  359. * @property width
  360. * @type Number
  361. * @default 0
  362. */
  363. this.width = width || 0;
  364. /**
  365. * @property height
  366. * @type Number
  367. * @default 0
  368. */
  369. this.height = height || 0;
  370. };
  371. /**
  372. * Creates a clone of this Ellipse instance
  373. *
  374. * @method clone
  375. * @return {Ellipse} a copy of the ellipse
  376. */
  377. PIXI.Ellipse.prototype.clone = function()
  378. {
  379. return new PIXI.Ellipse(this.x, this.y, this.width, this.height);
  380. };
  381. /**
  382. * Checks whether the x and y coordinates passed to this function are contained within this ellipse
  383. *
  384. * @method contains
  385. * @param x {Number} The X coordinate of the point to test
  386. * @param y {Number} The Y coordinate of the point to test
  387. * @return {Boolean} Whether the x/y coords are within this ellipse
  388. */
  389. PIXI.Ellipse.prototype.contains = function(x, y)
  390. {
  391. if(this.width <= 0 || this.height <= 0)
  392. return false;
  393. //normalize the coords to an ellipse with center 0,0
  394. var normx = ((x - this.x) / this.width),
  395. normy = ((y - this.y) / this.height);
  396. normx *= normx;
  397. normy *= normy;
  398. return (normx + normy <= 1);
  399. };
  400. /**
  401. * Returns the framing rectangle of the ellipse as a PIXI.Rectangle object
  402. *
  403. * @method getBounds
  404. * @return {Rectangle} the framing rectangle
  405. */
  406. PIXI.Ellipse.prototype.getBounds = function()
  407. {
  408. return new PIXI.Rectangle(this.x, this.y, this.width, this.height);
  409. };
  410. // constructor
  411. PIXI.Ellipse.prototype.constructor = PIXI.Ellipse;
  412. /**
  413. * @author Mat Groves http://matgroves.com/ @Doormat23
  414. */
  415. PIXI.determineMatrixArrayType = function() {
  416. return (typeof Float32Array !== 'undefined') ? Float32Array : Array;
  417. };
  418. /*
  419. * @class Matrix2
  420. * The Matrix2 class will choose the best type of array to use between
  421. * a regular javascript Array and a Float32Array if the latter is available
  422. *
  423. */
  424. PIXI.Matrix2 = PIXI.determineMatrixArrayType();
  425. /*
  426. * @class Matrix
  427. * The Matrix class is now an object, which makes it a lot faster,
  428. * here is a representation of it :
  429. * | a | b | tx|
  430. * | c | c | ty|
  431. * | 0 | 0 | 1 |
  432. *
  433. */
  434. PIXI.Matrix = function()
  435. {
  436. this.a = 1;
  437. this.b = 0;
  438. this.c = 0;
  439. this.d = 1;
  440. this.tx = 0;
  441. this.ty = 0;
  442. };
  443. /**
  444. * Creates a pixi matrix object based on the array given as a parameter
  445. *
  446. * @method fromArray
  447. * @param array {Array} The array that the matrix will be filled with
  448. */
  449. PIXI.Matrix.prototype.fromArray = function(array)
  450. {
  451. this.a = array[0];
  452. this.b = array[1];
  453. this.c = array[3];
  454. this.d = array[4];
  455. this.tx = array[2];
  456. this.ty = array[5];
  457. };
  458. /**
  459. * Creates an array from the current Matrix object
  460. *
  461. * @method toArray
  462. * @param transpose {Boolean} Whether we need to transpose the matrix or not
  463. * @return array {Array} the newly created array which contains the matrix
  464. */
  465. PIXI.Matrix.prototype.toArray = function(transpose)
  466. {
  467. if(!this.array) this.array = new Float32Array(9);
  468. var array = this.array;
  469. if(transpose)
  470. {
  471. this.array[0] = this.a;
  472. this.array[1] = this.c;
  473. this.array[2] = 0;
  474. this.array[3] = this.b;
  475. this.array[4] = this.d;
  476. this.array[5] = 0;
  477. this.array[6] = this.tx;
  478. this.array[7] = this.ty;
  479. this.array[8] = 1;
  480. }
  481. else
  482. {
  483. this.array[0] = this.a;
  484. this.array[1] = this.b;
  485. this.array[2] = this.tx;
  486. this.array[3] = this.c;
  487. this.array[4] = this.d;
  488. this.array[5] = this.ty;
  489. this.array[6] = 0;
  490. this.array[7] = 0;
  491. this.array[8] = 1;
  492. }
  493. return array;//[this.a, this.b, this.tx, this.c, this.d, this.ty, 0, 0, 1];
  494. };
  495. PIXI.identityMatrix = new PIXI.Matrix();
  496. /**
  497. * @author Mat Groves http://matgroves.com/ @Doormat23
  498. */
  499. /**
  500. * The base class for all objects that are rendered on the screen.
  501. *
  502. * @class DisplayObject
  503. * @constructor
  504. */
  505. PIXI.DisplayObject = function()
  506. {
  507. /**
  508. * The coordinate of the object relative to the local coordinates of the parent.
  509. *
  510. * @property position
  511. * @type Point
  512. */
  513. this.position = new PIXI.Point();
  514. /**
  515. * The scale factor of the object.
  516. *
  517. * @property scale
  518. * @type Point
  519. */
  520. this.scale = new PIXI.Point(1,1);//{x:1, y:1};
  521. /**
  522. * The pivot point of the displayObject that it rotates around
  523. *
  524. * @property pivot
  525. * @type Point
  526. */
  527. this.pivot = new PIXI.Point(0,0);
  528. /**
  529. * The rotation of the object in radians.
  530. *
  531. * @property rotation
  532. * @type Number
  533. */
  534. this.rotation = 0;
  535. /**
  536. * The opacity of the object.
  537. *
  538. * @property alpha
  539. * @type Number
  540. */
  541. this.alpha = 1;
  542. /**
  543. * The visibility of the object.
  544. *
  545. * @property visible
  546. * @type Boolean
  547. */
  548. this.visible = true;
  549. /**
  550. * This is the defined area that will pick up mouse / touch events. It is null by default.
  551. * Setting it is a neat way of optimising the hitTest function that the interactionManager will use (as it will not need to hit test all the children)
  552. *
  553. * @property hitArea
  554. * @type Rectangle|Circle|Ellipse|Polygon
  555. */
  556. this.hitArea = null;
  557. /**
  558. * This is used to indicate if the displayObject should display a mouse hand cursor on rollover
  559. *
  560. * @property buttonMode
  561. * @type Boolean
  562. */
  563. this.buttonMode = false;
  564. /**
  565. * Can this object be rendered
  566. *
  567. * @property renderable
  568. * @type Boolean
  569. */
  570. this.renderable = false;
  571. /**
  572. * [read-only] The display object container that contains this display object.
  573. *
  574. * @property parent
  575. * @type DisplayObjectContainer
  576. * @readOnly
  577. */
  578. this.parent = null;
  579. /**
  580. * [read-only] The stage the display object is connected to, or undefined if it is not connected to the stage.
  581. *
  582. * @property stage
  583. * @type Stage
  584. * @readOnly
  585. */
  586. this.stage = null;
  587. /**
  588. * [read-only] The multiplied alpha of the displayObject
  589. *
  590. * @property worldAlpha
  591. * @type Number
  592. * @readOnly
  593. */
  594. this.worldAlpha = 1;
  595. /**
  596. * [read-only] Whether or not the object is interactive, do not toggle directly! use the `interactive` property
  597. *
  598. * @property _interactive
  599. * @type Boolean
  600. * @readOnly
  601. * @private
  602. */
  603. this._interactive = false;
  604. /**
  605. * This is the cursor that will be used when the mouse is over this object. To enable this the element must have interaction = true and buttonMode = true
  606. *
  607. * @property defaultCursor
  608. * @type String
  609. *
  610. */
  611. this.defaultCursor = 'pointer';
  612. /**
  613. * [read-only] Current transform of the object based on world (parent) factors
  614. *
  615. * @property worldTransform
  616. * @type Mat3
  617. * @readOnly
  618. * @private
  619. */
  620. this.worldTransform = new PIXI.Matrix();
  621. /**
  622. * [NYI] Unknown
  623. *
  624. * @property color
  625. * @type Array<>
  626. * @private
  627. */
  628. this.color = [];
  629. /**
  630. * [NYI] Holds whether or not this object is dynamic, for rendering optimization
  631. *
  632. * @property dynamic
  633. * @type Boolean
  634. * @private
  635. */
  636. this.dynamic = true;
  637. // cached sin rotation and cos rotation
  638. this._sr = 0;
  639. this._cr = 1;
  640. /**
  641. * The area the filter is applied to like the hitArea this is used as more of an optimisation
  642. * rather than figuring out the dimensions of the displayObject each frame you can set this rectangle
  643. *
  644. * @property filterArea
  645. * @type Rectangle
  646. */
  647. this.filterArea = null;//new PIXI.Rectangle(0,0,1,1);
  648. /**
  649. * The original, cached bounds of the object
  650. *
  651. * @property _bounds
  652. * @type Rectangle
  653. * @private
  654. */
  655. this._bounds = new PIXI.Rectangle(0, 0, 1, 1);
  656. /**
  657. * The most up-to-date bounds of the object
  658. *
  659. * @property _currentBounds
  660. * @type Rectangle
  661. * @private
  662. */
  663. this._currentBounds = null;
  664. /**
  665. * The original, cached mask of the object
  666. *
  667. * @property _currentBounds
  668. * @type Rectangle
  669. * @private
  670. */
  671. this._mask = null;
  672. this._cacheAsBitmap = false;
  673. this._cacheIsDirty = false;
  674. /*
  675. * MOUSE Callbacks
  676. */
  677. /**
  678. * A callback that is used when the users clicks on the displayObject with their mouse
  679. * @method click
  680. * @param interactionData {InteractionData}
  681. */
  682. /**
  683. * A callback that is used when the user clicks the mouse down over the sprite
  684. * @method mousedown
  685. * @param interactionData {InteractionData}
  686. */
  687. /**
  688. * A callback that is used when the user releases the mouse that was over the displayObject
  689. * for this callback to be fired the mouse must have been pressed down over the displayObject
  690. * @method mouseup
  691. * @param interactionData {InteractionData}
  692. */
  693. /**
  694. * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject
  695. * for this callback to be fired, The touch must have started over the displayObject
  696. * @method mouseupoutside
  697. * @param interactionData {InteractionData}
  698. */
  699. /**
  700. * A callback that is used when the users mouse rolls over the displayObject
  701. * @method mouseover
  702. * @param interactionData {InteractionData}
  703. */
  704. /**
  705. * A callback that is used when the users mouse leaves the displayObject
  706. * @method mouseout
  707. * @param interactionData {InteractionData}
  708. */
  709. /*
  710. * TOUCH Callbacks
  711. */
  712. /**
  713. * A callback that is used when the users taps on the sprite with their finger
  714. * basically a touch version of click
  715. * @method tap
  716. * @param interactionData {InteractionData}
  717. */
  718. /**
  719. * A callback that is used when the user touches over the displayObject
  720. * @method touchstart
  721. * @param interactionData {InteractionData}
  722. */
  723. /**
  724. * A callback that is used when the user releases a touch over the displayObject
  725. * @method touchend
  726. * @param interactionData {InteractionData}
  727. */
  728. /**
  729. * A callback that is used when the user releases the touch that was over the displayObject
  730. * for this callback to be fired, The touch must have started over the sprite
  731. * @method touchendoutside
  732. * @param interactionData {InteractionData}
  733. */
  734. };
  735. // constructor
  736. PIXI.DisplayObject.prototype.constructor = PIXI.DisplayObject;
  737. /**
  738. * [Deprecated] Indicates if the sprite will have touch and mouse interactivity. It is false by default
  739. * Instead of using this function you can now simply set the interactive property to true or false
  740. *
  741. * @method setInteractive
  742. * @param interactive {Boolean}
  743. * @deprecated Simply set the `interactive` property directly
  744. */
  745. PIXI.DisplayObject.prototype.setInteractive = function(interactive)
  746. {
  747. this.interactive = interactive;
  748. };
  749. /**
  750. * Indicates if the sprite will have touch and mouse interactivity. It is false by default
  751. *
  752. * @property interactive
  753. * @type Boolean
  754. * @default false
  755. */
  756. Object.defineProperty(PIXI.DisplayObject.prototype, 'interactive', {
  757. get: function() {
  758. return this._interactive;
  759. },
  760. set: function(value) {
  761. this._interactive = value;
  762. // TODO more to be done here..
  763. // need to sort out a re-crawl!
  764. if(this.stage)this.stage.dirty = true;
  765. }
  766. });
  767. /**
  768. * [read-only] Indicates if the sprite is globaly visible.
  769. *
  770. * @property worldVisible
  771. * @type Boolean
  772. */
  773. Object.defineProperty(PIXI.DisplayObject.prototype, 'worldVisible', {
  774. get: function() {
  775. var item = this;
  776. do
  777. {
  778. if(!item.visible)return false;
  779. item = item.parent;
  780. }
  781. while(item);
  782. return true;
  783. }
  784. });
  785. /**
  786. * Sets a mask for the displayObject. A mask is an object that limits the visibility of an object to the shape of the mask applied to it.
  787. * In PIXI a regular mask must be a PIXI.Graphics object. This allows for much faster masking in canvas as it utilises shape clipping.
  788. * To remove a mask, set this property to null.
  789. *
  790. * @property mask
  791. * @type Graphics
  792. */
  793. Object.defineProperty(PIXI.DisplayObject.prototype, 'mask', {
  794. get: function() {
  795. return this._mask;
  796. },
  797. set: function(value) {
  798. if(this._mask)this._mask.isMask = false;
  799. this._mask = value;
  800. if(this._mask)this._mask.isMask = true;
  801. }
  802. });
  803. /**
  804. * Sets the filters for the displayObject.
  805. * * IMPORTANT: This is a webGL only feature and will be ignored by the canvas renderer.
  806. * To remove filters simply set this property to 'null'
  807. * @property filters
  808. * @type Array An array of filters
  809. */
  810. Object.defineProperty(PIXI.DisplayObject.prototype, 'filters', {
  811. get: function() {
  812. return this._filters;
  813. },
  814. set: function(value) {
  815. if(value)
  816. {
  817. // now put all the passes in one place..
  818. var passes = [];
  819. for (var i = 0; i < value.length; i++)
  820. {
  821. var filterPasses = value[i].passes;
  822. for (var j = 0; j < filterPasses.length; j++)
  823. {
  824. passes.push(filterPasses[j]);
  825. }
  826. }
  827. // TODO change this as it is legacy
  828. this._filterBlock = {target:this, filterPasses:passes};
  829. }
  830. this._filters = value;
  831. }
  832. });
  833. /**
  834. * Set weather or not a the display objects is cached as a bitmap.
  835. * This basically takes a snap shot of the display object as it is at that moment. It can provide a performance benefit for complex static displayObjects
  836. * To remove filters simply set this property to 'null'
  837. * @property cacheAsBitmap
  838. * @type Boolean
  839. */
  840. Object.defineProperty(PIXI.DisplayObject.prototype, 'cacheAsBitmap', {
  841. get: function() {
  842. return this._cacheAsBitmap;
  843. },
  844. set: function(value) {
  845. if(this._cacheAsBitmap === value)return;
  846. if(value)
  847. {
  848. //this._cacheIsDirty = true;
  849. this._generateCachedSprite();
  850. }
  851. else
  852. {
  853. this._destroyCachedSprite();
  854. }
  855. this._cacheAsBitmap = value;
  856. }
  857. });
  858. /*
  859. * Updates the object transform for rendering
  860. *
  861. * @method updateTransform
  862. * @private
  863. */
  864. PIXI.DisplayObject.prototype.updateTransform = function()
  865. {
  866. // TODO OPTIMIZE THIS!! with dirty
  867. if(this.rotation !== this.rotationCache)
  868. {
  869. this.rotationCache = this.rotation;
  870. this._sr = Math.sin(this.rotation);
  871. this._cr = Math.cos(this.rotation);
  872. }
  873. // var localTransform = this.localTransform//.toArray();
  874. var parentTransform = this.parent.worldTransform;//.toArray();
  875. var worldTransform = this.worldTransform;//.toArray();
  876. var px = this.pivot.x;
  877. var py = this.pivot.y;
  878. var a00 = this._cr * this.scale.x,
  879. a01 = -this._sr * this.scale.y,
  880. a10 = this._sr * this.scale.x,
  881. a11 = this._cr * this.scale.y,
  882. a02 = this.position.x - a00 * px - py * a01,
  883. a12 = this.position.y - a11 * py - px * a10,
  884. b00 = parentTransform.a, b01 = parentTransform.b,
  885. b10 = parentTransform.c, b11 = parentTransform.d;
  886. worldTransform.a = b00 * a00 + b01 * a10;
  887. worldTransform.b = b00 * a01 + b01 * a11;
  888. worldTransform.tx = b00 * a02 + b01 * a12 + parentTransform.tx;
  889. worldTransform.c = b10 * a00 + b11 * a10;
  890. worldTransform.d = b10 * a01 + b11 * a11;
  891. worldTransform.ty = b10 * a02 + b11 * a12 + parentTransform.ty;
  892. this.worldAlpha = this.alpha * this.parent.worldAlpha;
  893. };
  894. /**
  895. * Retrieves the bounds of the displayObject as a rectangle object
  896. *
  897. * @method getBounds
  898. * @return {Rectangle} the rectangular bounding area
  899. */
  900. PIXI.DisplayObject.prototype.getBounds = function( matrix )
  901. {
  902. matrix = matrix;//just to get passed js hinting (and preserve inheritance)
  903. return PIXI.EmptyRectangle;
  904. };
  905. /**
  906. * Retrieves the local bounds of the displayObject as a rectangle object
  907. *
  908. * @method getLocalBounds
  909. * @return {Rectangle} the rectangular bounding area
  910. */
  911. PIXI.DisplayObject.prototype.getLocalBounds = function()
  912. {
  913. return this.getBounds(PIXI.identityMatrix);///PIXI.EmptyRectangle();
  914. };
  915. /**
  916. * Sets the object's stage reference, the stage this object is connected to
  917. *
  918. * @method setStageReference
  919. * @param stage {Stage} the stage that the object will have as its current stage reference
  920. */
  921. PIXI.DisplayObject.prototype.setStageReference = function(stage)
  922. {
  923. this.stage = stage;
  924. if(this._interactive)this.stage.dirty = true;
  925. };
  926. PIXI.DisplayObject.prototype.generateTexture = function(renderer)
  927. {
  928. var bounds = this.getLocalBounds();
  929. var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer);
  930. renderTexture.render(this);
  931. return renderTexture;
  932. };
  933. PIXI.DisplayObject.prototype.updateCache = function()
  934. {
  935. this._generateCachedSprite();
  936. };
  937. PIXI.DisplayObject.prototype._renderCachedSprite = function(renderSession)
  938. {
  939. if(renderSession.gl)
  940. {
  941. PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession);
  942. }
  943. else
  944. {
  945. PIXI.Sprite.prototype._renderCanvas.call(this._cachedSprite, renderSession);
  946. }
  947. };
  948. PIXI.DisplayObject.prototype._generateCachedSprite = function()//renderSession)
  949. {
  950. this._cacheAsBitmap = false;
  951. var bounds = this.getLocalBounds();
  952. if(!this._cachedSprite)
  953. {
  954. var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0);//, renderSession.renderer);
  955. this._cachedSprite = new PIXI.Sprite(renderTexture);
  956. this._cachedSprite.worldTransform = this.worldTransform;
  957. }
  958. else
  959. {
  960. this._cachedSprite.texture.resize(bounds.width | 0, bounds.height | 0);
  961. }
  962. //REMOVE filter!
  963. var tempFilters = this._filters;
  964. this._filters = null;
  965. this._cachedSprite.filters = tempFilters;
  966. this._cachedSprite.texture.render(this);
  967. this._filters = tempFilters;
  968. this._cacheAsBitmap = true;
  969. };
  970. /**
  971. * Renders the object using the WebGL renderer
  972. *
  973. * @method _renderWebGL
  974. * @param renderSession {RenderSession}
  975. * @private
  976. */
  977. PIXI.DisplayObject.prototype._destroyCachedSprite = function()
  978. {
  979. if(!this._cachedSprite)return;
  980. this._cachedSprite.texture.destroy(true);
  981. // console.log("DESTROY")
  982. // let the gc collect the unused sprite
  983. // TODO could be object pooled!
  984. this._cachedSprite = null;
  985. };
  986. PIXI.DisplayObject.prototype._renderWebGL = function(renderSession)
  987. {
  988. // OVERWRITE;
  989. // this line is just here to pass jshinting :)
  990. renderSession = renderSession;
  991. };
  992. /**
  993. * Renders the object using the Canvas renderer
  994. *
  995. * @method _renderCanvas
  996. * @param renderSession {RenderSession}
  997. * @private
  998. */
  999. PIXI.DisplayObject.prototype._renderCanvas = function(renderSession)
  1000. {
  1001. // OVERWRITE;
  1002. // this line is just here to pass jshinting :)
  1003. renderSession = renderSession;
  1004. };
  1005. /**
  1006. * The position of the displayObject on the x axis relative to the local coordinates of the parent.
  1007. *
  1008. * @property x
  1009. * @type Number
  1010. */
  1011. Object.defineProperty(PIXI.DisplayObject.prototype, 'x', {
  1012. get: function() {
  1013. return this.position.x;
  1014. },
  1015. set: function(value) {
  1016. this.position.x = value;
  1017. }
  1018. });
  1019. /**
  1020. * The position of the displayObject on the y axis relative to the local coordinates of the parent.
  1021. *
  1022. * @property y
  1023. * @type Number
  1024. */
  1025. Object.defineProperty(PIXI.DisplayObject.prototype, 'y', {
  1026. get: function() {
  1027. return this.position.y;
  1028. },
  1029. set: function(value) {
  1030. this.position.y = value;
  1031. }
  1032. });
  1033. /**
  1034. * @author Mat Groves http://matgroves.com/ @Doormat23
  1035. */
  1036. /**
  1037. * A DisplayObjectContainer represents a collection of display objects.
  1038. * It is the base class of all display objects that act as a container for other objects.
  1039. *
  1040. * @class DisplayObjectContainer
  1041. * @extends DisplayObject
  1042. * @constructor
  1043. */
  1044. PIXI.DisplayObjectContainer = function()
  1045. {
  1046. PIXI.DisplayObject.call( this );
  1047. /**
  1048. * [read-only] The array of children of this container.
  1049. *
  1050. * @property children
  1051. * @type Array<DisplayObject>
  1052. * @readOnly
  1053. */
  1054. this.children = [];
  1055. };
  1056. // constructor
  1057. PIXI.DisplayObjectContainer.prototype = Object.create( PIXI.DisplayObject.prototype );
  1058. PIXI.DisplayObjectContainer.prototype.constructor = PIXI.DisplayObjectContainer;
  1059. /**
  1060. * The width of the displayObjectContainer, setting this will actually modify the scale to achieve the value set
  1061. *
  1062. * @property width
  1063. * @type Number
  1064. */
  1065. /*
  1066. Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'width', {
  1067. get: function() {
  1068. return this.scale.x * this.getLocalBounds().width;
  1069. },
  1070. set: function(value) {
  1071. this.scale.x = value / (this.getLocalBounds().width/this.scale.x);
  1072. this._width = value;
  1073. }
  1074. });
  1075. */
  1076. /**
  1077. * The height of the displayObjectContainer, setting this will actually modify the scale to achieve the value set
  1078. *
  1079. * @property height
  1080. * @type Number
  1081. */
  1082. /*
  1083. Object.defineProperty(PIXI.DisplayObjectContainer.prototype, 'height', {
  1084. get: function() {
  1085. return this.scale.y * this.getLocalBounds().height;
  1086. },
  1087. set: function(value) {
  1088. this.scale.y = value / (this.getLocalBounds().height/this.scale.y);
  1089. this._height = value;
  1090. }
  1091. });
  1092. */
  1093. /**
  1094. * Adds a child to the container.
  1095. *
  1096. * @method addChild
  1097. * @param child {DisplayObject} The DisplayObject to add to the container
  1098. */
  1099. PIXI.DisplayObjectContainer.prototype.addChild = function(child)
  1100. {
  1101. this.addChildAt(child, this.children.length);
  1102. };
  1103. /**
  1104. * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown
  1105. *
  1106. * @method addChildAt
  1107. * @param child {DisplayObject} The child to add
  1108. * @param index {Number} The index to place the child in
  1109. */
  1110. PIXI.DisplayObjectContainer.prototype.addChildAt = function(child, index)
  1111. {
  1112. if(index >= 0 && index <= this.children.length)
  1113. {
  1114. if(child.parent)
  1115. {
  1116. child.parent.removeChild(child);
  1117. }
  1118. child.parent = this;
  1119. this.children.splice(index, 0, child);
  1120. if(this.stage)child.setStageReference(this.stage);
  1121. }
  1122. else
  1123. {
  1124. throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length);
  1125. }
  1126. };
  1127. /**
  1128. * [NYI] Swaps the depth of 2 displayObjects
  1129. *
  1130. * @method swapChildren
  1131. * @param child {DisplayObject}
  1132. * @param child2 {DisplayObject}
  1133. * @private
  1134. */
  1135. PIXI.DisplayObjectContainer.prototype.swapChildren = function(child, child2)
  1136. {
  1137. if(child === child2) {
  1138. return;
  1139. }
  1140. var index1 = this.children.indexOf(child);
  1141. var index2 = this.children.indexOf(child2);
  1142. if(index1 < 0 || index2 < 0) {
  1143. throw new Error('swapChildren: Both the supplied DisplayObjects must be a child of the caller.');
  1144. }
  1145. this.children[index1] = child2;
  1146. this.children[index2] = child;
  1147. };
  1148. /**
  1149. * Returns the child at the specified index
  1150. *
  1151. * @method getChildAt
  1152. * @param index {Number} The index to get the child from
  1153. */
  1154. PIXI.DisplayObjectContainer.prototype.getChildAt = function(index)
  1155. {
  1156. if(index >= 0 && index < this.children.length)
  1157. {
  1158. return this.children[index];
  1159. }
  1160. else
  1161. {
  1162. throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller');
  1163. }
  1164. };
  1165. /**
  1166. * Removes a child from the container.
  1167. *
  1168. * @method removeChild
  1169. * @param child {DisplayObject} The DisplayObject to remove
  1170. */
  1171. PIXI.DisplayObjectContainer.prototype.removeChild = function(child)
  1172. {
  1173. return this.removeChildAt( this.children.indexOf( child ) );
  1174. };
  1175. /**
  1176. * Removes a child from the specified index position in the child list of the container.
  1177. *
  1178. * @method removeChildAt
  1179. * @param index {Number} The index to get the child from
  1180. */
  1181. PIXI.DisplayObjectContainer.prototype.removeChildAt = function(index)
  1182. {
  1183. var child = this.getChildAt( index );
  1184. if(this.stage)
  1185. child.removeStageReference();
  1186. child.parent = undefined;
  1187. this.children.splice( index, 1 );
  1188. return child;
  1189. };
  1190. /**
  1191. * Removes all child instances from the child list of the container.
  1192. *
  1193. * @method removeChildren
  1194. * @param beginIndex {Number} The beginning position. Predefined value is 0.
  1195. * @param endIndex {Number} The ending position. Predefined value is children's array length.
  1196. */
  1197. PIXI.DisplayObjectContainer.prototype.removeChildren = function(beginIndex, endIndex)
  1198. {
  1199. var begin = beginIndex || 0;
  1200. var end = typeof endIndex === 'number' ? endIndex : this.children.length;
  1201. var range = end - begin;
  1202. if (range > 0 && range <= end)
  1203. {
  1204. var removed = this.children.splice(begin, range);
  1205. for (var i = 0; i < removed.length; i++) {
  1206. var child = removed[i];
  1207. if(this.stage)
  1208. child.removeStageReference();
  1209. child.parent = undefined;
  1210. }
  1211. return removed;
  1212. }
  1213. else
  1214. {
  1215. throw new Error( 'Range Error, numeric values are outside the acceptable range' );
  1216. }
  1217. };
  1218. /*
  1219. * Updates the container's childrens transform for rendering
  1220. *
  1221. * @method updateTransform
  1222. * @private
  1223. */
  1224. PIXI.DisplayObjectContainer.prototype.updateTransform = function()
  1225. {
  1226. //this._currentBounds = null;
  1227. if(!this.visible)return;
  1228. PIXI.DisplayObject.prototype.updateTransform.call( this );
  1229. if(this._cacheAsBitmap)return;
  1230. for(var i=0,j=this.children.length; i<j; i++)
  1231. {
  1232. this.children[i].updateTransform();
  1233. }
  1234. };
  1235. /**
  1236. * Retrieves the bounds of the displayObjectContainer as a rectangle object
  1237. *
  1238. * @method getBounds
  1239. * @return {Rectangle} the rectangular bounding area
  1240. */
  1241. PIXI.DisplayObjectContainer.prototype.getBounds = function(matrix)
  1242. {
  1243. if(this.children.length === 0)return PIXI.EmptyRectangle;
  1244. // TODO the bounds have already been calculated this render session so return what we have
  1245. if(matrix)
  1246. {
  1247. var matrixCache = this.worldTransform;
  1248. this.worldTransform = matrix;
  1249. this.updateTransform();
  1250. this.worldTransform = matrixCache;
  1251. }
  1252. var minX = Infinity;
  1253. var minY = Infinity;
  1254. var maxX = -Infinity;
  1255. var maxY = -Infinity;
  1256. var childBounds;
  1257. var childMaxX;
  1258. var childMaxY;
  1259. var childVisible = false;
  1260. for(var i=0,j=this.children.length; i<j; i++)
  1261. {
  1262. var child = this.children[i];
  1263. if(!child.visible)continue;
  1264. childVisible = true;
  1265. childBounds = this.children[i].getBounds( matrix );
  1266. minX = minX < childBounds.x ? minX : childBounds.x;
  1267. minY = minY < childBounds.y ? minY : childBounds.y;
  1268. childMaxX = childBounds.width + childBounds.x;
  1269. childMaxY = childBounds.height + childBounds.y;
  1270. maxX = maxX > childMaxX ? maxX : childMaxX;
  1271. maxY = maxY > childMaxY ? maxY : childMaxY;
  1272. }
  1273. if(!childVisible)
  1274. return PIXI.EmptyRectangle;
  1275. var bounds = this._bounds;
  1276. bounds.x = minX;
  1277. bounds.y = minY;
  1278. bounds.width = maxX - minX;
  1279. bounds.height = maxY - minY;
  1280. // TODO: store a reference so that if this function gets called again in the render cycle we do not have to recalculate
  1281. //this._currentBounds = bounds;
  1282. return bounds;
  1283. };
  1284. PIXI.DisplayObjectContainer.prototype.getLocalBounds = function()
  1285. {
  1286. var matrixCache = this.worldTransform;
  1287. this.worldTransform = PIXI.identityMatrix;
  1288. for(var i=0,j=this.children.length; i<j; i++)
  1289. {
  1290. this.children[i].updateTransform();
  1291. }
  1292. var bounds = this.getBounds();
  1293. this.worldTransform = matrixCache;
  1294. return bounds;
  1295. };
  1296. /**
  1297. * Sets the container's stage reference, the stage this object is connected to
  1298. *
  1299. * @method setStageReference
  1300. * @param stage {Stage} the stage that the container will have as its current stage reference
  1301. */
  1302. PIXI.DisplayObjectContainer.prototype.setStageReference = function(stage)
  1303. {
  1304. this.stage = stage;
  1305. if(this._interactive)this.stage.dirty = true;
  1306. for(var i=0,j=this.children.length; i<j; i++)
  1307. {
  1308. var child = this.children[i];
  1309. child.setStageReference(stage);
  1310. }
  1311. };
  1312. /**
  1313. * removes the current stage reference of the container
  1314. *
  1315. * @method removeStageReference
  1316. */
  1317. PIXI.DisplayObjectContainer.prototype.removeStageReference = function()
  1318. {
  1319. for(var i=0,j=this.children.length; i<j; i++)
  1320. {
  1321. var child = this.children[i];
  1322. child.removeStageReference();
  1323. }
  1324. if(this._interactive)this.stage.dirty = true;
  1325. this.stage = null;
  1326. };
  1327. /**
  1328. * Renders the object using the WebGL renderer
  1329. *
  1330. * @method _renderWebGL
  1331. * @param renderSession {RenderSession}
  1332. * @private
  1333. */
  1334. PIXI.DisplayObjectContainer.prototype._renderWebGL = function(renderSession)
  1335. {
  1336. if(!this.visible || this.alpha <= 0)return;
  1337. if(this._cacheAsBitmap)
  1338. {
  1339. this._renderCachedSprite(renderSession);
  1340. return;
  1341. }
  1342. var i,j;
  1343. if(this._mask || this._filters)
  1344. {
  1345. if(this._mask)
  1346. {
  1347. renderSession.spriteBatch.stop();
  1348. renderSession.maskManager.pushMask(this.mask, renderSession);
  1349. renderSession.spriteBatch.start();
  1350. }
  1351. if(this._filters)
  1352. {
  1353. renderSession.spriteBatch.flush();
  1354. renderSession.filterManager.pushFilter(this._filterBlock);
  1355. }
  1356. // simple render children!
  1357. for(i=0,j=this.children.length; i<j; i++)
  1358. {
  1359. this.children[i]._renderWebGL(renderSession);
  1360. }
  1361. renderSession.spriteBatch.stop();
  1362. if(this._filters)renderSession.filterManager.popFilter();
  1363. if(this._mask)renderSession.maskManager.popMask(renderSession);
  1364. renderSession.spriteBatch.start();
  1365. }
  1366. else
  1367. {
  1368. // simple render children!
  1369. for(i=0,j=this.children.length; i<j; i++)
  1370. {
  1371. this.children[i]._renderWebGL(renderSession);
  1372. }
  1373. }
  1374. };
  1375. /**
  1376. * Renders the object using the Canvas renderer
  1377. *
  1378. * @method _renderCanvas
  1379. * @param renderSession {RenderSession}
  1380. * @private
  1381. */
  1382. PIXI.DisplayObjectContainer.prototype._renderCanvas = function(renderSession)
  1383. {
  1384. if(this.visible === false || this.alpha === 0)return;
  1385. if(this._cacheAsBitmap)
  1386. {
  1387. this._renderCachedSprite(renderSession);
  1388. return;
  1389. }
  1390. if(this._mask)
  1391. {
  1392. renderSession.maskManager.pushMask(this._mask, renderSession.context);
  1393. }
  1394. for(var i=0,j=this.children.length; i<j; i++)
  1395. {
  1396. var child = this.children[i];
  1397. child._renderCanvas(renderSession);
  1398. }
  1399. if(this._mask)
  1400. {
  1401. renderSession.maskManager.popMask(renderSession.context);
  1402. }
  1403. };
  1404. /**
  1405. * @author Mat Groves http://matgroves.com/ @Doormat23
  1406. */
  1407. /**
  1408. * The Sprite object is the base for all textured objects that are rendered to the screen
  1409. *
  1410. * @class Sprite
  1411. * @extends DisplayObjectContainer
  1412. * @constructor
  1413. * @param texture {Texture} The texture for this sprite
  1414. *
  1415. * A sprite can be created directly from an image like this :
  1416. * var sprite = nex PIXI.Sprite.FromImage('assets/image.png');
  1417. * yourStage.addChild(sprite);
  1418. * then obviously don't forget to add it to the stage you have already created
  1419. */
  1420. PIXI.Sprite = function(texture)
  1421. {
  1422. PIXI.DisplayObjectContainer.call( this );
  1423. /**
  1424. * The anchor sets the origin point of the texture.
  1425. * The default is 0,0 this means the texture's origin is the top left
  1426. * Setting than anchor to 0.5,0.5 means the textures origin is centred
  1427. * Setting the anchor to 1,1 would mean the textures origin points will be the bottom right corner
  1428. *
  1429. * @property anchor
  1430. * @type Point
  1431. */
  1432. this.anchor = new PIXI.Point();
  1433. /**
  1434. * The texture that the sprite is using
  1435. *
  1436. * @property texture
  1437. * @type Texture
  1438. */
  1439. this.texture = texture;
  1440. /**
  1441. * The width of the sprite (this is initially set by the texture)
  1442. *
  1443. * @property _width
  1444. * @type Number
  1445. * @private
  1446. */
  1447. this._width = 0;
  1448. /**
  1449. * The height of the sprite (this is initially set by the texture)
  1450. *
  1451. * @property _height
  1452. * @type Number
  1453. * @private
  1454. */
  1455. this._height = 0;
  1456. /**
  1457. * The tint applied to the sprite. This is a hex value
  1458. *
  1459. * @property tint
  1460. * @type Number
  1461. * @default 0xFFFFFF
  1462. */
  1463. this.tint = 0xFFFFFF;// * Math.random();
  1464. /**
  1465. * The blend mode to be applied to the sprite
  1466. *
  1467. * @property blendMode
  1468. * @type Number
  1469. * @default PIXI.blendModes.NORMAL;
  1470. */
  1471. this.blendMode = PIXI.blendModes.NORMAL;
  1472. if(texture.baseTexture.hasLoaded)
  1473. {
  1474. this.onTextureUpdate();
  1475. }
  1476. else
  1477. {
  1478. this.onTextureUpdateBind = this.onTextureUpdate.bind(this);
  1479. this.texture.addEventListener( 'update', this.onTextureUpdateBind );
  1480. }
  1481. this.renderable = true;
  1482. };
  1483. // constructor
  1484. PIXI.Sprite.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
  1485. PIXI.Sprite.prototype.constructor = PIXI.Sprite;
  1486. /**
  1487. * The width of the sprite, setting this will actually modify the scale to achieve the value set
  1488. *
  1489. * @property width
  1490. * @type Number
  1491. */
  1492. Object.defineProperty(PIXI.Sprite.prototype, 'width', {
  1493. get: function() {
  1494. return this.scale.x * this.texture.frame.width;
  1495. },
  1496. set: function(value) {
  1497. this.scale.x = value / this.texture.frame.width;
  1498. this._width = value;
  1499. }
  1500. });
  1501. /**
  1502. * The height of the sprite, setting this will actually modify the scale to achieve the value set
  1503. *
  1504. * @property height
  1505. * @type Number
  1506. */
  1507. Object.defineProperty(PIXI.Sprite.prototype, 'height', {
  1508. get: function() {
  1509. return this.scale.y * this.texture.frame.height;
  1510. },
  1511. set: function(value) {
  1512. this.scale.y = value / this.texture.frame.height;
  1513. this._height = value;
  1514. }
  1515. });
  1516. /**
  1517. * Sets the texture of the sprite
  1518. *
  1519. * @method setTexture
  1520. * @param texture {Texture} The PIXI texture that is displayed by the sprite
  1521. */
  1522. PIXI.Sprite.prototype.setTexture = function(texture)
  1523. {
  1524. // stop current texture;
  1525. if(this.texture.baseTexture !== texture.baseTexture)
  1526. {
  1527. this.textureChange = true;
  1528. this.texture = texture;
  1529. }
  1530. else
  1531. {
  1532. this.texture = texture;
  1533. }
  1534. this.cachedTint = 0xFFFFFF;
  1535. this.updateFrame = true;
  1536. };
  1537. /**
  1538. * When the texture is updated, this event will fire to update the scale and frame
  1539. *
  1540. * @method onTextureUpdate
  1541. * @param event
  1542. * @private
  1543. */
  1544. PIXI.Sprite.prototype.onTextureUpdate = function()
  1545. {
  1546. // so if _width is 0 then width was not set..
  1547. if(this._width)this.scale.x = this._width / this.texture.frame.width;
  1548. if(this._height)this.scale.y = this._height / this.texture.frame.height;
  1549. this.updateFrame = true;
  1550. };
  1551. /**
  1552. * Returns the framing rectangle of the sprite as a PIXI.Rectangle object
  1553. *
  1554. * @method getBounds
  1555. * @param matrix {Matrix} the transformation matrix of the sprite
  1556. * @return {Rectangle} the framing rectangle
  1557. */
  1558. PIXI.Sprite.prototype.getBounds = function(matrix)
  1559. {
  1560. var width = this.texture.frame.width;
  1561. var height = this.texture.frame.height;
  1562. var w0 = width * (1-this.anchor.x);
  1563. var w1 = width * -this.anchor.x;
  1564. var h0 = height * (1-this.anchor.y);
  1565. var h1 = height * -this.anchor.y;
  1566. var worldTransform = matrix || this.worldTransform ;
  1567. var a = worldTransform.a;
  1568. var b = worldTransform.c;
  1569. var c = worldTransform.b;
  1570. var d = worldTransform.d;
  1571. var tx = worldTransform.tx;
  1572. var ty = worldTransform.ty;
  1573. var x1 = a * w1 + c * h1 + tx;
  1574. var y1 = d * h1 + b * w1 + ty;
  1575. var x2 = a * w0 + c * h1 + tx;
  1576. var y2 = d * h1 + b * w0 + ty;
  1577. var x3 = a * w0 + c * h0 + tx;
  1578. var y3 = d * h0 + b * w0 + ty;
  1579. var x4 = a * w1 + c * h0 + tx;
  1580. var y4 = d * h0 + b * w1 + ty;
  1581. var maxX = -Infinity;
  1582. var maxY = -Infinity;
  1583. var minX = Infinity;
  1584. var minY = Infinity;
  1585. minX = x1 < minX ? x1 : minX;
  1586. minX = x2 < minX ? x2 : minX;
  1587. minX = x3 < minX ? x3 : minX;
  1588. minX = x4 < minX ? x4 : minX;
  1589. minY = y1 < minY ? y1 : minY;
  1590. minY = y2 < minY ? y2 : minY;
  1591. minY = y3 < minY ? y3 : minY;
  1592. minY = y4 < minY ? y4 : minY;
  1593. maxX = x1 > maxX ? x1 : maxX;
  1594. maxX = x2 > maxX ? x2 : maxX;
  1595. maxX = x3 > maxX ? x3 : maxX;
  1596. maxX = x4 > maxX ? x4 : maxX;
  1597. maxY = y1 > maxY ? y1 : maxY;
  1598. maxY = y2 > maxY ? y2 : maxY;
  1599. maxY = y3 > maxY ? y3 : maxY;
  1600. maxY = y4 > maxY ? y4 : maxY;
  1601. var bounds = this._bounds;
  1602. bounds.x = minX;
  1603. bounds.width = maxX - minX;
  1604. bounds.y = minY;
  1605. bounds.height = maxY - minY;
  1606. // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
  1607. this._currentBounds = bounds;
  1608. return bounds;
  1609. };
  1610. /**
  1611. * Renders the object using the WebGL renderer
  1612. *
  1613. * @method _renderWebGL
  1614. * @param renderSession {RenderSession}
  1615. * @private
  1616. */
  1617. PIXI.Sprite.prototype._renderWebGL = function(renderSession)
  1618. {
  1619. // if the sprite is not visible or the alpha is 0 then no need to render this element
  1620. if(!this.visible || this.alpha <= 0)return;
  1621. var i,j;
  1622. // do a quick check to see if this element has a mask or a filter.
  1623. if(this._mask || this._filters)
  1624. {
  1625. var spriteBatch = renderSession.spriteBatch;
  1626. if(this._mask)
  1627. {
  1628. spriteBatch.stop();
  1629. renderSession.maskManager.pushMask(this.mask, renderSession);
  1630. spriteBatch.start();
  1631. }
  1632. if(this._filters)
  1633. {
  1634. spriteBatch.flush();
  1635. renderSession.filterManager.pushFilter(this._filterBlock);
  1636. }
  1637. // add this sprite to the batch
  1638. spriteBatch.render(this);
  1639. // now loop through the children and make sure they get rendered
  1640. for(i=0,j=this.children.length; i<j; i++)
  1641. {
  1642. this.children[i]._renderWebGL(renderSession);
  1643. }
  1644. // time to stop the sprite batch as either a mask element or a filter draw will happen next
  1645. spriteBatch.stop();
  1646. if(this._filters)renderSession.filterManager.popFilter();
  1647. if(this._mask)renderSession.maskManager.popMask(renderSession);
  1648. spriteBatch.start();
  1649. }
  1650. else
  1651. {
  1652. renderSession.spriteBatch.render(this);
  1653. // simple render children!
  1654. for(i=0,j=this.children.length; i<j; i++)
  1655. {
  1656. this.children[i]._renderWebGL(renderSession);
  1657. }
  1658. }
  1659. //TODO check culling
  1660. };
  1661. /**
  1662. * Renders the object using the Canvas renderer
  1663. *
  1664. * @method _renderCanvas
  1665. * @param renderSession {RenderSession}
  1666. * @private
  1667. */
  1668. PIXI.Sprite.prototype._renderCanvas = function(renderSession)
  1669. {
  1670. // if the sprite is not visible or the alpha is 0 then no need to render this element
  1671. if(this.visible === false || this.alpha === 0)return;
  1672. var frame = this.texture.frame;
  1673. var context = renderSession.context;
  1674. var texture = this.texture;
  1675. if(this.blendMode !== renderSession.currentBlendMode)
  1676. {
  1677. renderSession.currentBlendMode = this.blendMode;
  1678. context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
  1679. }
  1680. if(this._mask)
  1681. {
  1682. renderSession.maskManager.pushMask(this._mask, renderSession.context);
  1683. }
  1684. //ignore null sources
  1685. if(frame && frame.width && frame.height && texture.baseTexture.source)
  1686. {
  1687. context.globalAlpha = this.worldAlpha;
  1688. var transform = this.worldTransform;
  1689. // allow for trimming
  1690. if (renderSession.roundPixels)
  1691. {
  1692. context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx | 0, transform.ty | 0);
  1693. }
  1694. else
  1695. {
  1696. context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
  1697. }
  1698. //if smoothingEnabled is supported and we need to change the smoothing property for this texture
  1699. if(renderSession.smoothProperty && renderSession.scaleMode !== this.texture.baseTexture.scaleMode) {
  1700. renderSession.scaleMode = this.texture.baseTexture.scaleMode;
  1701. context[renderSession.smoothProperty] = (renderSession.scaleMode === PIXI.scaleModes.LINEAR);
  1702. }
  1703. if(this.tint !== 0xFFFFFF)
  1704. {
  1705. if(this.cachedTint !== this.tint)
  1706. {
  1707. // no point tinting an image that has not loaded yet!
  1708. if(!texture.baseTexture.hasLoaded)return;
  1709. this.cachedTint = this.tint;
  1710. //TODO clean up caching - how to clean up the caches?
  1711. this.tintedTexture = PIXI.CanvasTinter.getTintedTexture(this, this.tint);
  1712. }
  1713. context.drawImage(this.tintedTexture,
  1714. 0,
  1715. 0,
  1716. frame.width,
  1717. frame.height,
  1718. (this.anchor.x) * -frame.width,
  1719. (this.anchor.y) * -frame.height,
  1720. frame.width,
  1721. frame.height);
  1722. }
  1723. else
  1724. {
  1725. if(texture.trim)
  1726. {
  1727. var trim = texture.trim;
  1728. context.drawImage(this.texture.baseTexture.source,
  1729. frame.x,
  1730. frame.y,
  1731. frame.width,
  1732. frame.height,
  1733. trim.x - this.anchor.x * trim.width,
  1734. trim.y - this.anchor.y * trim.height,
  1735. frame.width,
  1736. frame.height);
  1737. }
  1738. else
  1739. {
  1740. context.drawImage(this.texture.baseTexture.source,
  1741. frame.x,
  1742. frame.y,
  1743. frame.width,
  1744. frame.height,
  1745. (this.anchor.x) * -frame.width,
  1746. (this.anchor.y) * -frame.height,
  1747. frame.width,
  1748. frame.height);
  1749. }
  1750. }
  1751. }
  1752. // OVERWRITE
  1753. for(var i=0,j=this.children.length; i<j; i++)
  1754. {
  1755. var child = this.children[i];
  1756. child._renderCanvas(renderSession);
  1757. }
  1758. if(this._mask)
  1759. {
  1760. renderSession.maskManager.popMask(renderSession.context);
  1761. }
  1762. };
  1763. // some helper functions..
  1764. /**
  1765. *
  1766. * Helper function that creates a sprite that will contain a texture from the TextureCache based on the frameId
  1767. * The frame ids are created when a Texture packer file has been loaded
  1768. *
  1769. * @method fromFrame
  1770. * @static
  1771. * @param frameId {String} The frame Id of the texture in the cache
  1772. * @return {Sprite} A new Sprite using a texture from the texture cache matching the frameId
  1773. */
  1774. PIXI.Sprite.fromFrame = function(frameId)
  1775. {
  1776. var texture = PIXI.TextureCache[frameId];
  1777. if(!texture) throw new Error('The frameId "' + frameId + '" does not exist in the texture cache' + this);
  1778. return new PIXI.Sprite(texture);
  1779. };
  1780. /**
  1781. *
  1782. * Helper function that creates a sprite that will contain a texture based on an image url
  1783. * If the image is not in the texture cache it will be loaded
  1784. *
  1785. * @method fromImage
  1786. * @static
  1787. * @param imageId {String} The image url of the texture
  1788. * @return {Sprite} A new Sprite using a texture from the texture cache matching the image id
  1789. */
  1790. PIXI.Sprite.fromImage = function(imageId, crossorigin, scaleMode)
  1791. {
  1792. var texture = PIXI.Texture.fromImage(imageId, crossorigin, scaleMode);
  1793. return new PIXI.Sprite(texture);
  1794. };
  1795. /**
  1796. * @author Mat Groves http://matgroves.com/
  1797. */
  1798. /**
  1799. * The SpriteBatch class is a really fast version of the DisplayObjectContainer
  1800. * built solely for speed, so use when you need a lot of sprites or particles.
  1801. * And it's extremely easy to use :
  1802. var container = new PIXI.SpriteBatch();
  1803. stage.addChild(container);
  1804. for(var i = 0; i < 100; i++)
  1805. {
  1806. var sprite = new PIXI.Sprite.fromImage("myImage.png");
  1807. container.addChild(sprite);
  1808. }
  1809. * And here you have a hundred sprites that will be renderer at the speed of light
  1810. *
  1811. * @class SpriteBatch
  1812. * @constructor
  1813. * @param texture {Texture}
  1814. */
  1815. PIXI.SpriteBatch = function(texture)
  1816. {
  1817. PIXI.DisplayObjectContainer.call( this);
  1818. this.textureThing = texture;
  1819. this.ready = false;
  1820. };
  1821. PIXI.SpriteBatch.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
  1822. PIXI.SpriteBatch.constructor = PIXI.SpriteBatch;
  1823. /*
  1824. * Initialises the spriteBatch
  1825. *
  1826. * @method initWebGL
  1827. * @param gl {WebGLContext} the current WebGL drawing context
  1828. */
  1829. PIXI.SpriteBatch.prototype.initWebGL = function(gl)
  1830. {
  1831. // TODO only one needed for the whole engine really?
  1832. this.fastSpriteBatch = new PIXI.WebGLFastSpriteBatch(gl);
  1833. this.ready = true;
  1834. };
  1835. /*
  1836. * Updates the object transform for rendering
  1837. *
  1838. * @method updateTransform
  1839. * @private
  1840. */
  1841. PIXI.SpriteBatch.prototype.updateTransform = function()
  1842. {
  1843. // TODO dont need to!
  1844. PIXI.DisplayObject.prototype.updateTransform.call( this );
  1845. // PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
  1846. };
  1847. /**
  1848. * Renders the object using the WebGL renderer
  1849. *
  1850. * @method _renderWebGL
  1851. * @param renderSession {RenderSession}
  1852. * @private
  1853. */
  1854. PIXI.SpriteBatch.prototype._renderWebGL = function(renderSession)
  1855. {
  1856. if(!this.visible || this.alpha <= 0 || !this.children.length)return;
  1857. if(!this.ready)this.initWebGL( renderSession.gl );
  1858. renderSession.spriteBatch.stop();
  1859. renderSession.shaderManager.activateShader(renderSession.shaderManager.fastShader);
  1860. this.fastSpriteBatch.begin(this, renderSession);
  1861. this.fastSpriteBatch.render(this);
  1862. renderSession.shaderManager.activateShader(renderSession.shaderManager.defaultShader);
  1863. renderSession.spriteBatch.start();
  1864. };
  1865. /**
  1866. * Renders the object using the Canvas renderer
  1867. *
  1868. * @method _renderCanvas
  1869. * @param renderSession {RenderSession}
  1870. * @private
  1871. */
  1872. PIXI.SpriteBatch.prototype._renderCanvas = function(renderSession)
  1873. {
  1874. var context = renderSession.context;
  1875. context.globalAlpha = this.worldAlpha;
  1876. PIXI.DisplayObject.prototype.updateTransform.call(this);
  1877. var transform = this.worldTransform;
  1878. // alow for trimming
  1879. var isRotated = true;
  1880. for (var i = 0; i < this.children.length; i++) {
  1881. var child = this.children[i];
  1882. if(!child.visible)continue;
  1883. var texture = child.texture;
  1884. var frame = texture.frame;
  1885. context.globalAlpha = this.worldAlpha * child.alpha;
  1886. if(child.rotation % (Math.PI * 2) === 0)
  1887. {
  1888. if(isRotated)
  1889. {
  1890. context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
  1891. isRotated = false;
  1892. }
  1893. // this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call
  1894. context.drawImage(texture.baseTexture.source,
  1895. frame.x,
  1896. frame.y,
  1897. frame.width,
  1898. frame.height,
  1899. ((child.anchor.x) * (-frame.width * child.scale.x) + child.position.x + 0.5) | 0,
  1900. ((child.anchor.y) * (-frame.height * child.scale.y) + child.position.y + 0.5) | 0,
  1901. frame.width * child.scale.x,
  1902. frame.height * child.scale.y);
  1903. }
  1904. else
  1905. {
  1906. if(!isRotated)isRotated = true;
  1907. PIXI.DisplayObject.prototype.updateTransform.call(child);
  1908. var childTransform = child.worldTransform;
  1909. // allow for trimming
  1910. if (renderSession.roundPixels)
  1911. {
  1912. context.setTransform(childTransform.a, childTransform.c, childTransform.b, childTransform.d, childTransform.tx | 0, childTransform.ty | 0);
  1913. }
  1914. else
  1915. {
  1916. context.setTransform(childTransform.a, childTransform.c, childTransform.b, childTransform.d, childTransform.tx, childTransform.ty);
  1917. }
  1918. context.drawImage(texture.baseTexture.source,
  1919. frame.x,
  1920. frame.y,
  1921. frame.width,
  1922. frame.height,
  1923. ((child.anchor.x) * (-frame.width) + 0.5) | 0,
  1924. ((child.anchor.y) * (-frame.height) + 0.5) | 0,
  1925. frame.width,
  1926. frame.height);
  1927. }
  1928. // context.restore();
  1929. }
  1930. // context.restore();
  1931. };
  1932. /**
  1933. * @author Mat Groves http://matgroves.com/ @Doormat23
  1934. */
  1935. PIXI.FilterBlock = function()
  1936. {
  1937. this.visible = true;
  1938. this.renderable = true;
  1939. };
  1940. /**
  1941. * @author Mat Groves http://matgroves.com/ @Doormat23
  1942. * - Modified by Tom Slezakowski http://www.tomslezakowski.com @TomSlezakowski (24/03/2014) - Added dropShadowColor.
  1943. */
  1944. /**
  1945. * A Text Object will create a line(s) of text. To split a line you can use '\n'
  1946. * or add a wordWrap property set to true and and wordWrapWidth property with a value
  1947. * in the style object
  1948. *
  1949. * @class Text
  1950. * @extends Sprite
  1951. * @constructor
  1952. * @param text {String} The copy that you would like the text to display
  1953. * @param [style] {Object} The style parameters
  1954. * @param [style.font] {String} default 'bold 20px Arial' The style and size of the font
  1955. * @param [style.fill='black'] {String|Number} A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'
  1956. * @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  1957. * @param [style.stroke] {String|Number} A canvas fillstyle that will be used on the text stroke e.g 'blue', '#FCFF00'
  1958. * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
  1959. * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
  1960. * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap, it needs wordWrap to be set to true
  1961. * @param [style.dropShadow=false] {Boolean} Set a drop shadow for the text
  1962. * @param [style.dropShadowColor='#000000'] {String} A fill style to be used on the dropshadow e.g 'red', '#00FF00'
  1963. * @param [style.dropShadowAngle=Math.PI/4] {Number} Set a angle of the drop shadow
  1964. * @param [style.dropShadowDistance=5] {Number} Set a distance of the drop shadow
  1965. */
  1966. PIXI.Text = function(text, style)
  1967. {
  1968. /**
  1969. * The canvas element that everything is drawn to
  1970. *
  1971. * @property canvas
  1972. * @type HTMLCanvasElement
  1973. */
  1974. this.canvas = document.createElement('canvas');
  1975. /**
  1976. * The canvas 2d context that everything is drawn with
  1977. * @property context
  1978. * @type HTMLCanvasElement 2d Context
  1979. */
  1980. this.context = this.canvas.getContext('2d');
  1981. PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas));
  1982. this.setText(text);
  1983. this.setStyle(style);
  1984. this.updateText();
  1985. this.dirty = false;
  1986. };
  1987. // constructor
  1988. PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype);
  1989. PIXI.Text.prototype.constructor = PIXI.Text;
  1990. /**
  1991. * Set the style of the text
  1992. *
  1993. * @method setStyle
  1994. * @param [style] {Object} The style parameters
  1995. * @param [style.font='bold 20pt Arial'] {String} The style and size of the font
  1996. * @param [style.fill='black'] {Object} A canvas fillstyle that will be used on the text eg 'red', '#00FF00'
  1997. * @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  1998. * @param [style.stroke='black'] {String} A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'
  1999. * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
  2000. * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
  2001. * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap
  2002. * @param [style.dropShadow=false] {Boolean} Set a drop shadow for the text
  2003. * @param [style.dropShadowColor='#000000'] {String} A fill style to be used on the dropshadow e.g 'red', '#00FF00'
  2004. * @param [style.dropShadowAngle=Math.PI/4] {Number} Set a angle of the drop shadow
  2005. * @param [style.dropShadowDistance=5] {Number} Set a distance of the drop shadow
  2006. */
  2007. PIXI.Text.prototype.setStyle = function(style)
  2008. {
  2009. style = style || {};
  2010. style.font = style.font || 'bold 20pt Arial';
  2011. style.fill = style.fill || 'black';
  2012. style.align = style.align || 'left';
  2013. style.stroke = style.stroke || 'black'; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136
  2014. style.strokeThickness = style.strokeThickness || 0;
  2015. style.wordWrap = style.wordWrap || false;
  2016. style.wordWrapWidth = style.wordWrapWidth || 100;
  2017. style.wordWrapWidth = style.wordWrapWidth || 100;
  2018. style.dropShadow = style.dropShadow || false;
  2019. style.dropShadowAngle = style.dropShadowAngle || Math.PI / 6;
  2020. style.dropShadowDistance = style.dropShadowDistance || 4;
  2021. style.dropShadowColor = style.dropShadowColor || 'black';
  2022. this.style = style;
  2023. this.dirty = true;
  2024. };
  2025. /**
  2026. * Set the copy for the text object. To split a line you can use '\n'
  2027. *
  2028. * @method setText
  2029. * @param {String} text The copy that you would like the text to display
  2030. */
  2031. PIXI.Text.prototype.setText = function(text)
  2032. {
  2033. this.text = text.toString() || ' ';
  2034. this.dirty = true;
  2035. };
  2036. /**
  2037. * Renders text and updates it when needed
  2038. *
  2039. * @method updateText
  2040. * @private
  2041. */
  2042. PIXI.Text.prototype.updateText = function()
  2043. {
  2044. this.context.font = this.style.font;
  2045. var outputText = this.text;
  2046. // word wrap
  2047. // preserve original text
  2048. if(this.style.wordWrap)outputText = this.wordWrap(this.text);
  2049. //split text into lines
  2050. var lines = outputText.split(/(?:\r\n|\r|\n)/);
  2051. //calculate text width
  2052. var lineWidths = [];
  2053. var maxLineWidth = 0;
  2054. for (var i = 0; i < lines.length; i++)
  2055. {
  2056. var lineWidth = this.context.measureText(lines[i]).width;
  2057. lineWidths[i] = lineWidth;
  2058. maxLineWidth = Math.max(maxLineWidth, lineWidth);
  2059. }
  2060. var width = maxLineWidth + this.style.strokeThickness;
  2061. if(this.style.dropShadow)width += this.style.dropShadowDistance;
  2062. this.canvas.width = width;
  2063. //calculate text height
  2064. var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness;
  2065. var height = lineHeight * lines.length;
  2066. if(this.style.dropShadow)height += this.style.dropShadowDistance;
  2067. this.canvas.height = height;
  2068. if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
  2069. this.context.font = this.style.font;
  2070. this.context.strokeStyle = this.style.stroke;
  2071. this.context.lineWidth = this.style.strokeThickness;
  2072. this.context.textBaseline = 'top';
  2073. var linePositionX;
  2074. var linePositionY;
  2075. if(this.style.dropShadow)
  2076. {
  2077. this.context.fillStyle = this.style.dropShadowColor;
  2078. var xShadowOffset = Math.sin(this.style.dropShadowAngle) * this.style.dropShadowDistance;
  2079. var yShadowOffset = Math.cos(this.style.dropShadowAngle) * this.style.dropShadowDistance;
  2080. for (i = 0; i < lines.length; i++)
  2081. {
  2082. linePositionX = this.style.strokeThickness / 2;
  2083. linePositionY = this.style.strokeThickness / 2 + i * lineHeight;
  2084. if(this.style.align === 'right')
  2085. {
  2086. linePositionX += maxLineWidth - lineWidths[i];
  2087. }
  2088. else if(this.style.align === 'center')
  2089. {
  2090. linePositionX += (maxLineWidth - lineWidths[i]) / 2;
  2091. }
  2092. if(this.style.fill)
  2093. {
  2094. this.context.fillText(lines[i], linePositionX + xShadowOffset, linePositionY + yShadowOffset);
  2095. }
  2096. // if(dropShadow)
  2097. }
  2098. }
  2099. //set canvas text styles
  2100. this.context.fillStyle = this.style.fill;
  2101. //draw lines line by line
  2102. for (i = 0; i < lines.length; i++)
  2103. {
  2104. linePositionX = this.style.strokeThickness / 2;
  2105. linePositionY = this.style.strokeThickness / 2 + i * lineHeight;
  2106. if(this.style.align === 'right')
  2107. {
  2108. linePositionX += maxLineWidth - lineWidths[i];
  2109. }
  2110. else if(this.style.align === 'center')
  2111. {
  2112. linePositionX += (maxLineWidth - lineWidths[i]) / 2;
  2113. }
  2114. if(this.style.stroke && this.style.strokeThickness)
  2115. {
  2116. this.context.strokeText(lines[i], linePositionX, linePositionY);
  2117. }
  2118. if(this.style.fill)
  2119. {
  2120. this.context.fillText(lines[i], linePositionX, linePositionY);
  2121. }
  2122. // if(dropShadow)
  2123. }
  2124. this.updateTexture();
  2125. };
  2126. /**
  2127. * Updates texture size based on canvas size
  2128. *
  2129. * @method updateTexture
  2130. * @private
  2131. */
  2132. PIXI.Text.prototype.updateTexture = function()
  2133. {
  2134. this.texture.baseTexture.width = this.canvas.width;
  2135. this.texture.baseTexture.height = this.canvas.height;
  2136. this.texture.frame.width = this.canvas.width;
  2137. this.texture.frame.height = this.canvas.height;
  2138. this._width = this.canvas.width;
  2139. this._height = this.canvas.height;
  2140. this.requiresUpdate = true;
  2141. };
  2142. /**
  2143. * Renders the object using the WebGL renderer
  2144. *
  2145. * @method _renderWebGL
  2146. * @param renderSession {RenderSession}
  2147. * @private
  2148. */
  2149. PIXI.Text.prototype._renderWebGL = function(renderSession)
  2150. {
  2151. if(this.requiresUpdate)
  2152. {
  2153. this.requiresUpdate = false;
  2154. PIXI.updateWebGLTexture(this.texture.baseTexture, renderSession.gl);
  2155. }
  2156. PIXI.Sprite.prototype._renderWebGL.call(this, renderSession);
  2157. };
  2158. /**
  2159. * Updates the transform of this object
  2160. *
  2161. * @method updateTransform
  2162. * @private
  2163. */
  2164. PIXI.Text.prototype.updateTransform = function()
  2165. {
  2166. if(this.dirty)
  2167. {
  2168. this.updateText();
  2169. this.dirty = false;
  2170. }
  2171. PIXI.Sprite.prototype.updateTransform.call(this);
  2172. };
  2173. /*
  2174. * http://stackoverflow.com/users/34441/ellisbben
  2175. * great solution to the problem!
  2176. * returns the height of the given font
  2177. *
  2178. * @method determineFontHeight
  2179. * @param fontStyle {Object}
  2180. * @private
  2181. */
  2182. PIXI.Text.prototype.determineFontHeight = function(fontStyle)
  2183. {
  2184. // build a little reference dictionary so if the font style has been used return a
  2185. // cached version...
  2186. var result = PIXI.Text.heightCache[fontStyle];
  2187. if(!result)
  2188. {
  2189. var body = document.getElementsByTagName('body')[0];
  2190. var dummy = document.createElement('div');
  2191. var dummyText = document.createTextNode('M');
  2192. dummy.appendChild(dummyText);
  2193. dummy.setAttribute('style', fontStyle + ';position:absolute;top:0;left:0');
  2194. body.appendChild(dummy);
  2195. result = dummy.offsetHeight;
  2196. PIXI.Text.heightCache[fontStyle] = result;
  2197. body.removeChild(dummy);
  2198. }
  2199. return result;
  2200. };
  2201. /**
  2202. * Applies newlines to a string to have it optimally fit into the horizontal
  2203. * bounds set by the Text object's wordWrapWidth property.
  2204. *
  2205. * @method wordWrap
  2206. * @param text {String}
  2207. * @private
  2208. */
  2209. PIXI.Text.prototype.wordWrap = function(text)
  2210. {
  2211. // Greedy wrapping algorithm that will wrap words as the line grows longer
  2212. // than its horizontal bounds.
  2213. var result = '';
  2214. var lines = text.split('\n');
  2215. for (var i = 0; i < lines.length; i++)
  2216. {
  2217. var spaceLeft = this.style.wordWrapWidth;
  2218. var words = lines[i].split(' ');
  2219. for (var j = 0; j < words.length; j++)
  2220. {
  2221. var wordWidth = this.context.measureText(words[j]).width;
  2222. var wordWidthWithSpace = wordWidth + this.context.measureText(' ').width;
  2223. if(wordWidthWithSpace > spaceLeft)
  2224. {
  2225. // Skip printing the newline if it's the first word of the line that is
  2226. // greater than the word wrap width.
  2227. if(j > 0)
  2228. {
  2229. result += '\n';
  2230. }
  2231. result += words[j] + ' ';
  2232. spaceLeft = this.style.wordWrapWidth - wordWidth;
  2233. }
  2234. else
  2235. {
  2236. spaceLeft -= wordWidthWithSpace;
  2237. result += words[j] + ' ';
  2238. }
  2239. }
  2240. if (i < lines.length-1)
  2241. {
  2242. result += '\n';
  2243. }
  2244. }
  2245. return result;
  2246. };
  2247. /**
  2248. * Destroys this text object
  2249. *
  2250. * @method destroy
  2251. * @param destroyTexture {Boolean}
  2252. */
  2253. PIXI.Text.prototype.destroy = function(destroyTexture)
  2254. {
  2255. if(destroyTexture)
  2256. {
  2257. this.texture.destroy();
  2258. }
  2259. };
  2260. PIXI.Text.heightCache = {};
  2261. /**
  2262. * @author Mat Groves http://matgroves.com/ @Doormat23
  2263. */
  2264. /**
  2265. * A Text Object will create a line(s) of text using bitmap font. To split a line you can use '\n', '\r' or '\r\n'
  2266. * You can generate the fnt files using
  2267. * http://www.angelcode.com/products/bmfont/ for windows or
  2268. * http://www.bmglyph.com/ for mac.
  2269. *
  2270. * @class BitmapText
  2271. * @extends DisplayObjectContainer
  2272. * @constructor
  2273. * @param text {String} The copy that you would like the text to display
  2274. * @param style {Object} The style parameters
  2275. * @param style.font {String} The size (optional) and bitmap font id (required) eq 'Arial' or '20px Arial' (must have loaded previously)
  2276. * @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  2277. */
  2278. PIXI.BitmapText = function(text, style)
  2279. {
  2280. PIXI.DisplayObjectContainer.call(this);
  2281. this._pool = [];
  2282. this.setText(text);
  2283. this.setStyle(style);
  2284. this.updateText();
  2285. this.dirty = false;
  2286. };
  2287. // constructor
  2288. PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
  2289. PIXI.BitmapText.prototype.constructor = PIXI.BitmapText;
  2290. /**
  2291. * Set the copy for the text object
  2292. *
  2293. * @method setText
  2294. * @param text {String} The copy that you would like the text to display
  2295. */
  2296. PIXI.BitmapText.prototype.setText = function(text)
  2297. {
  2298. this.text = text || ' ';
  2299. this.dirty = true;
  2300. };
  2301. /**
  2302. * Set the style of the text
  2303. * style.font {String} The size (optional) and bitmap font id (required) eq 'Arial' or '20px Arial' (must have loaded previously)
  2304. * [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  2305. *
  2306. * @method setStyle
  2307. * @param style {Object} The style parameters, contained as properties of an object
  2308. */
  2309. PIXI.BitmapText.prototype.setStyle = function(style)
  2310. {
  2311. style = style || {};
  2312. style.align = style.align || 'left';
  2313. this.style = style;
  2314. var font = style.font.split(' ');
  2315. this.fontName = font[font.length - 1];
  2316. this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size;
  2317. this.dirty = true;
  2318. this.tint = style.tint;
  2319. };
  2320. /**
  2321. * Renders text and updates it when needed
  2322. *
  2323. * @method updateText
  2324. * @private
  2325. */
  2326. PIXI.BitmapText.prototype.updateText = function()
  2327. {
  2328. var data = PIXI.BitmapText.fonts[this.fontName];
  2329. var pos = new PIXI.Point();
  2330. var prevCharCode = null;
  2331. var chars = [];
  2332. var maxLineWidth = 0;
  2333. var lineWidths = [];
  2334. var line = 0;
  2335. var scale = this.fontSize / data.size;
  2336. for(var i = 0; i < this.text.length; i++)
  2337. {
  2338. var charCode = this.text.charCodeAt(i);
  2339. if(/(?:\r\n|\r|\n)/.test(this.text.charAt(i)))
  2340. {
  2341. lineWidths.push(pos.x);
  2342. maxLineWidth = Math.max(maxLineWidth, pos.x);
  2343. line++;
  2344. pos.x = 0;
  2345. pos.y += data.lineHeight;
  2346. prevCharCode = null;
  2347. continue;
  2348. }
  2349. var charData = data.chars[charCode];
  2350. if(!charData) continue;
  2351. if(prevCharCode && charData[prevCharCode])
  2352. {
  2353. pos.x += charData.kerning[prevCharCode];
  2354. }
  2355. chars.push({texture:charData.texture, line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)});
  2356. pos.x += charData.xAdvance;
  2357. prevCharCode = charCode;
  2358. }
  2359. lineWidths.push(pos.x);
  2360. maxLineWidth = Math.max(maxLineWidth, pos.x);
  2361. var lineAlignOffsets = [];
  2362. for(i = 0; i <= line; i++)
  2363. {
  2364. var alignOffset = 0;
  2365. if(this.style.align === 'right')
  2366. {
  2367. alignOffset = maxLineWidth - lineWidths[i];
  2368. }
  2369. else if(this.style.align === 'center')
  2370. {
  2371. alignOffset = (maxLineWidth - lineWidths[i]) / 2;
  2372. }
  2373. lineAlignOffsets.push(alignOffset);
  2374. }
  2375. var lenChildren = this.children.length;
  2376. var lenChars = chars.length;
  2377. var tint = this.tint || 0xFFFFFF;
  2378. for(i = 0; i < lenChars; i++)
  2379. {
  2380. var c = i < lenChildren ? this.children[i] : this._pool.pop(); // get old child if have. if not - take from pool.
  2381. if (c) c.setTexture(chars[i].texture); // check if got one before.
  2382. else c = new PIXI.Sprite(chars[i].texture); // if no create new one.
  2383. c.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale;
  2384. c.position.y = chars[i].position.y * scale;
  2385. c.scale.x = c.scale.y = scale;
  2386. c.tint = tint;
  2387. if (!c.parent) this.addChild(c);
  2388. }
  2389. // remove unnecessary children.
  2390. // and put their into the pool.
  2391. while(this.children.length > lenChars)
  2392. {
  2393. var child = this.getChildAt(this.children.length - 1);
  2394. this._pool.push(child);
  2395. this.removeChild(child);
  2396. }
  2397. /**
  2398. * [read-only] The width of the overall text, different from fontSize,
  2399. * which is defined in the style object
  2400. *
  2401. * @property textWidth
  2402. * @type Number
  2403. */
  2404. this.textWidth = maxLineWidth * scale;
  2405. /**
  2406. * [read-only] The height of the overall text, different from fontSize,
  2407. * which is defined in the style object
  2408. *
  2409. * @property textHeight
  2410. * @type Number
  2411. */
  2412. this.textHeight = (pos.y + data.lineHeight) * scale;
  2413. };
  2414. /**
  2415. * Updates the transform of this object
  2416. *
  2417. * @method updateTransform
  2418. * @private
  2419. */
  2420. PIXI.BitmapText.prototype.updateTransform = function()
  2421. {
  2422. if(this.dirty)
  2423. {
  2424. this.updateText();
  2425. this.dirty = false;
  2426. }
  2427. PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
  2428. };
  2429. PIXI.BitmapText.fonts = {};
  2430. /**
  2431. * @author Mat Groves http://matgroves.com/ @Doormat23
  2432. */
  2433. /**
  2434. * A Stage represents the root of the display tree. Everything connected to the stage is rendered
  2435. *
  2436. * @class Stage
  2437. * @extends DisplayObjectContainer
  2438. * @constructor
  2439. * @param backgroundColor {Number} the background color of the stage, you have to pass this in is in hex format
  2440. * like: 0xFFFFFF for white
  2441. *
  2442. * Creating a stage is a mandatory process when you use Pixi, which is as simple as this :
  2443. * var stage = new PIXI.Stage(0xFFFFFF);
  2444. * where the parameter given is the background colour of the stage, in hex
  2445. * you will use this stage instance to add your sprites to it and therefore to the renderer
  2446. * Here is how to add a sprite to the stage :
  2447. * stage.addChild(sprite);
  2448. */
  2449. PIXI.Stage = function(backgroundColor)
  2450. {
  2451. PIXI.DisplayObjectContainer.call( this );
  2452. /**
  2453. * [read-only] Current transform of the object based on world (parent) factors
  2454. *
  2455. * @property worldTransform
  2456. * @type Mat3
  2457. * @readOnly
  2458. * @private
  2459. */
  2460. this.worldTransform = new PIXI.Matrix();
  2461. /**
  2462. * Whether or not the stage is interactive
  2463. *
  2464. * @property interactive
  2465. * @type Boolean
  2466. */
  2467. this.interactive = true;
  2468. /**
  2469. * The interaction manage for this stage, manages all interactive activity on the stage
  2470. *
  2471. * @property interactive
  2472. * @type InteractionManager
  2473. */
  2474. this.interactionManager = new PIXI.InteractionManager(this);
  2475. /**
  2476. * Whether the stage is dirty and needs to have interactions updated
  2477. *
  2478. * @property dirty
  2479. * @type Boolean
  2480. * @private
  2481. */
  2482. this.dirty = true;
  2483. //the stage is its own stage
  2484. this.stage = this;
  2485. //optimize hit detection a bit
  2486. this.stage.hitArea = new PIXI.Rectangle(0,0,100000, 100000);
  2487. this.setBackgroundColor(backgroundColor);
  2488. };
  2489. // constructor
  2490. PIXI.Stage.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
  2491. PIXI.Stage.prototype.constructor = PIXI.Stage;
  2492. /**
  2493. * Sets another DOM element which can receive mouse/touch interactions instead of the default Canvas element.
  2494. * This is useful for when you have other DOM elements on top of the Canvas element.
  2495. *
  2496. * @method setInteractionDelegate
  2497. * @param domElement {DOMElement} This new domElement which will receive mouse/touch events
  2498. */
  2499. PIXI.Stage.prototype.setInteractionDelegate = function(domElement)
  2500. {
  2501. this.interactionManager.setTargetDomElement( domElement );
  2502. };
  2503. /*
  2504. * Updates the object transform for rendering
  2505. *
  2506. * @method updateTransform
  2507. * @private
  2508. */
  2509. PIXI.Stage.prototype.updateTransform = function()
  2510. {
  2511. this.worldAlpha = 1;
  2512. for(var i=0,j=this.children.length; i<j; i++)
  2513. {
  2514. this.children[i].updateTransform();
  2515. }
  2516. if(this.dirty)
  2517. {
  2518. this.dirty = false;
  2519. // update interactive!
  2520. this.interactionManager.dirty = true;
  2521. }
  2522. if(this.interactive)this.interactionManager.update();
  2523. };
  2524. /**
  2525. * Sets the background color for the stage
  2526. *
  2527. * @method setBackgroundColor
  2528. * @param backgroundColor {Number} the color of the background, easiest way to pass this in is in hex format
  2529. * like: 0xFFFFFF for white
  2530. */
  2531. PIXI.Stage.prototype.setBackgroundColor = function(backgroundColor)
  2532. {
  2533. this.backgroundColor = backgroundColor || 0x000000;
  2534. this.backgroundColorSplit = PIXI.hex2rgb(this.backgroundColor);
  2535. var hex = this.backgroundColor.toString(16);
  2536. hex = '000000'.substr(0, 6 - hex.length) + hex;
  2537. this.backgroundColorString = '#' + hex;
  2538. };
  2539. /**
  2540. * This will return the point containing global coords of the mouse.
  2541. *
  2542. * @method getMousePosition
  2543. * @return {Point} The point containing the coords of the global InteractionData position.
  2544. */
  2545. PIXI.Stage.prototype.getMousePosition = function()
  2546. {
  2547. return this.interactionManager.mouse.global;
  2548. };
  2549. /**
  2550. * @author Mat Groves http://matgroves.com/ @Doormat23
  2551. */
  2552. // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  2553. // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
  2554. // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
  2555. // MIT license
  2556. /**
  2557. * A polyfill for requestAnimationFrame
  2558. * You can actually use both requestAnimationFrame and requestAnimFrame,
  2559. * you will still benefit from the polyfill
  2560. *
  2561. * @method requestAnimationFrame
  2562. */
  2563. /**
  2564. * A polyfill for cancelAnimationFrame
  2565. *
  2566. * @method cancelAnimationFrame
  2567. */
  2568. var lastTime = 0;
  2569. var vendors = ['ms', 'moz', 'webkit', 'o'];
  2570. for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
  2571. window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
  2572. window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
  2573. window[vendors[x] + 'CancelRequestAnimationFrame'];
  2574. }
  2575. if (!window.requestAnimationFrame) {
  2576. window.requestAnimationFrame = function(callback) {
  2577. var currTime = new Date().getTime();
  2578. var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  2579. var id = window.setTimeout(function() { callback(currTime + timeToCall); },
  2580. timeToCall);
  2581. lastTime = currTime + timeToCall;
  2582. return id;
  2583. };
  2584. }
  2585. if (!window.cancelAnimationFrame) {
  2586. window.cancelAnimationFrame = function(id) {
  2587. clearTimeout(id);
  2588. };
  2589. }
  2590. window.requestAnimFrame = window.requestAnimationFrame;
  2591. /**
  2592. * Converts a hex color number to an [R, G, B] array
  2593. *
  2594. * @method hex2rgb
  2595. * @param hex {Number}
  2596. */
  2597. PIXI.hex2rgb = function(hex) {
  2598. return [(hex >> 16 & 0xFF) / 255, ( hex >> 8 & 0xFF) / 255, (hex & 0xFF)/ 255];
  2599. };
  2600. /**
  2601. * Converts a color as an [R, G, B] array to a hex number
  2602. *
  2603. * @method rgb2hex
  2604. * @param rgb {Array}
  2605. */
  2606. PIXI.rgb2hex = function(rgb) {
  2607. return ((rgb[0]*255 << 16) + (rgb[1]*255 << 8) + rgb[2]*255);
  2608. };
  2609. /**
  2610. * A polyfill for Function.prototype.bind
  2611. *
  2612. * @method bind
  2613. */
  2614. if (typeof Function.prototype.bind !== 'function') {
  2615. Function.prototype.bind = (function () {
  2616. var slice = Array.prototype.slice;
  2617. return function (thisArg) {
  2618. var target = this, boundArgs = slice.call(arguments, 1);
  2619. if (typeof target !== 'function') throw new TypeError();
  2620. function bound() {
  2621. var args = boundArgs.concat(slice.call(arguments));
  2622. target.apply(this instanceof bound ? this : thisArg, args);
  2623. }
  2624. bound.prototype = (function F(proto) {
  2625. if (proto) F.prototype = proto;
  2626. if (!(this instanceof F)) return new F();
  2627. })(target.prototype);
  2628. return bound;
  2629. };
  2630. })();
  2631. }
  2632. /**
  2633. * A wrapper for ajax requests to be handled cross browser
  2634. *
  2635. * @class AjaxRequest
  2636. * @constructor
  2637. */
  2638. PIXI.AjaxRequest = function()
  2639. {
  2640. var activexmodes = ['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0', 'Microsoft.XMLHTTP']; //activeX versions to check for in IE
  2641. if (window.ActiveXObject)
  2642. { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
  2643. for (var i=0; i<activexmodes.length; i++)
  2644. {
  2645. try{
  2646. return new window.ActiveXObject(activexmodes[i]);
  2647. }
  2648. catch(e) {
  2649. //suppress error
  2650. }
  2651. }
  2652. }
  2653. else if (window.XMLHttpRequest) // if Mozilla, Safari etc
  2654. {
  2655. return new window.XMLHttpRequest();
  2656. }
  2657. else
  2658. {
  2659. return false;
  2660. }
  2661. };
  2662. /*
  2663. PIXI.packColorRGBA = function(r, g, b, a)//r, g, b, a)
  2664. {
  2665. // console.log(r, b, c, d)
  2666. return (Math.floor((r)*63) << 18) | (Math.floor((g)*63) << 12) | (Math.floor((b)*63) << 6);// | (Math.floor((a)*63))
  2667. // i = i | (Math.floor((a)*63));
  2668. // return i;
  2669. // var r = (i / 262144.0 ) / 64;
  2670. // var g = (i / 4096.0)%64 / 64;
  2671. // var b = (i / 64.0)%64 / 64;
  2672. // var a = (i)%64 / 64;
  2673. // console.log(r, g, b, a);
  2674. // return i;
  2675. };
  2676. */
  2677. /*
  2678. PIXI.packColorRGB = function(r, g, b)//r, g, b, a)
  2679. {
  2680. return (Math.floor((r)*255) << 16) | (Math.floor((g)*255) << 8) | (Math.floor((b)*255));
  2681. };
  2682. PIXI.unpackColorRGB = function(r, g, b)//r, g, b, a)
  2683. {
  2684. return (Math.floor((r)*255) << 16) | (Math.floor((g)*255) << 8) | (Math.floor((b)*255));
  2685. };
  2686. */
  2687. /**
  2688. * Checks whether the Canvas BlendModes are supported by the current browser
  2689. *
  2690. * @method canUseNewCanvasBlendModes
  2691. * @return {Boolean} whether they are supported
  2692. */
  2693. PIXI.canUseNewCanvasBlendModes = function()
  2694. {
  2695. var canvas = document.createElement('canvas');
  2696. canvas.width = 1;
  2697. canvas.height = 1;
  2698. var context = canvas.getContext('2d');
  2699. context.fillStyle = '#000';
  2700. context.fillRect(0,0,1,1);
  2701. context.globalCompositeOperation = 'multiply';
  2702. context.fillStyle = '#fff';
  2703. context.fillRect(0,0,1,1);
  2704. return context.getImageData(0,0,1,1).data[0] === 0;
  2705. };
  2706. /**
  2707. * Given a number, this function returns the closest number that is a power of two
  2708. * this function is taken from Starling Framework as its pretty neat ;)
  2709. *
  2710. * @method getNextPowerOfTwo
  2711. * @param number {Number}
  2712. * @return {Number} the closest number that is a power of two
  2713. */
  2714. PIXI.getNextPowerOfTwo = function(number)
  2715. {
  2716. if (number > 0 && (number & (number - 1)) === 0) // see: http://goo.gl/D9kPj
  2717. return number;
  2718. else
  2719. {
  2720. var result = 1;
  2721. while (result < number) result <<= 1;
  2722. return result;
  2723. }
  2724. };
  2725. /**
  2726. * @author Mat Groves http://matgroves.com/ @Doormat23
  2727. */
  2728. /**
  2729. * https://github.com/mrdoob/eventtarget.js/
  2730. * THankS mr DOob!
  2731. */
  2732. /**
  2733. * Adds event emitter functionality to a class
  2734. *
  2735. * @class EventTarget
  2736. * @example
  2737. * function MyEmitter() {
  2738. * PIXI.EventTarget.call(this); //mixes in event target stuff
  2739. * }
  2740. *
  2741. * var em = new MyEmitter();
  2742. * em.emit({ type: 'eventName', data: 'some data' });
  2743. */
  2744. PIXI.EventTarget = function () {
  2745. /**
  2746. * Holds all the listeners
  2747. *
  2748. * @property listeners
  2749. * @type Object
  2750. */
  2751. var listeners = {};
  2752. /**
  2753. * Adds a listener for a specific event
  2754. *
  2755. * @method addEventListener
  2756. * @param type {string} A string representing the event type to listen for.
  2757. * @param listener {function} The callback function that will be fired when the event occurs
  2758. */
  2759. this.addEventListener = this.on = function ( type, listener ) {
  2760. if ( listeners[ type ] === undefined ) {
  2761. listeners[ type ] = [];
  2762. }
  2763. if ( listeners[ type ].indexOf( listener ) === - 1 ) {
  2764. listeners[ type ].push( listener );
  2765. }
  2766. };
  2767. /**
  2768. * Fires the event, ie pretends that the event has happened
  2769. *
  2770. * @method dispatchEvent
  2771. * @param event {Event} the event object
  2772. */
  2773. this.dispatchEvent = this.emit = function ( event ) {
  2774. if ( !listeners[ event.type ] || !listeners[ event.type ].length ) {
  2775. return;
  2776. }
  2777. for(var i = 0, l = listeners[ event.type ].length; i < l; i++) {
  2778. listeners[ event.type ][ i ]( event );
  2779. }
  2780. };
  2781. /**
  2782. * Removes the specified listener that was assigned to the specified event type
  2783. *
  2784. * @method removeEventListener
  2785. * @param type {string} A string representing the event type which will have its listener removed
  2786. * @param listener {function} The callback function that was be fired when the event occured
  2787. */
  2788. this.removeEventListener = this.off = function ( type, listener ) {
  2789. var index = listeners[ type ].indexOf( listener );
  2790. if ( index !== - 1 ) {
  2791. listeners[ type ].splice( index, 1 );
  2792. }
  2793. };
  2794. /**
  2795. * Removes all the listeners that were active for the specified event type
  2796. *
  2797. * @method removeAllEventListeners
  2798. * @param type {string} A string representing the event type which will have all its listeners removed
  2799. */
  2800. this.removeAllEventListeners = function( type ) {
  2801. var a = listeners[type];
  2802. if (a)
  2803. a.length = 0;
  2804. };
  2805. };
  2806. /*
  2807. PolyK library
  2808. url: http://polyk.ivank.net
  2809. Released under MIT licence.
  2810. Copyright (c) 2012 Ivan Kuckir
  2811. Permission is hereby granted, free of charge, to any person
  2812. obtaining a copy of this software and associated documentation
  2813. files (the "Software"), to deal in the Software without
  2814. restriction, including without limitation the rights to use,
  2815. copy, modify, merge, publish, distribute, sublicense, and/or sell
  2816. copies of the Software, and to permit persons to whom the
  2817. Software is furnished to do so, subject to the following
  2818. conditions:
  2819. The above copyright notice and this permission notice shall be
  2820. included in all copies or substantial portions of the Software.
  2821. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  2822. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  2823. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  2824. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  2825. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  2826. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  2827. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  2828. OTHER DEALINGS IN THE SOFTWARE.
  2829. This is an amazing lib!
  2830. slightly modified by Mat Groves (matgroves.com);
  2831. */
  2832. /**
  2833. * Based on the Polyk library http://polyk.ivank.net released under MIT licence.
  2834. * This is an amazing lib!
  2835. * slightly modified by Mat Groves (matgroves.com);
  2836. * @class PolyK
  2837. *
  2838. */
  2839. PIXI.PolyK = {};
  2840. /**
  2841. * Triangulates shapes for webGL graphic fills
  2842. *
  2843. * @method Triangulate
  2844. *
  2845. */
  2846. PIXI.PolyK.Triangulate = function(p)
  2847. {
  2848. var sign = true;
  2849. var n = p.length >> 1;
  2850. if(n < 3) return [];
  2851. var tgs = [];
  2852. var avl = [];
  2853. for(var i = 0; i < n; i++) avl.push(i);
  2854. i = 0;
  2855. var al = n;
  2856. while(al > 3)
  2857. {
  2858. var i0 = avl[(i+0)%al];
  2859. var i1 = avl[(i+1)%al];
  2860. var i2 = avl[(i+2)%al];
  2861. var ax = p[2*i0], ay = p[2*i0+1];
  2862. var bx = p[2*i1], by = p[2*i1+1];
  2863. var cx = p[2*i2], cy = p[2*i2+1];
  2864. var earFound = false;
  2865. if(PIXI.PolyK._convex(ax, ay, bx, by, cx, cy, sign))
  2866. {
  2867. earFound = true;
  2868. for(var j = 0; j < al; j++)
  2869. {
  2870. var vi = avl[j];
  2871. if(vi === i0 || vi === i1 || vi === i2) continue;
  2872. if(PIXI.PolyK._PointInTriangle(p[2*vi], p[2*vi+1], ax, ay, bx, by, cx, cy)) {
  2873. earFound = false;
  2874. break;
  2875. }
  2876. }
  2877. }
  2878. if(earFound)
  2879. {
  2880. tgs.push(i0, i1, i2);
  2881. avl.splice((i+1)%al, 1);
  2882. al--;
  2883. i = 0;
  2884. }
  2885. else if(i++ > 3*al)
  2886. {
  2887. // need to flip flip reverse it!
  2888. // reset!
  2889. if(sign)
  2890. {
  2891. tgs = [];
  2892. avl = [];
  2893. for(i = 0; i < n; i++) avl.push(i);
  2894. i = 0;
  2895. al = n;
  2896. sign = false;
  2897. }
  2898. else
  2899. {
  2900. window.console.log("PIXI Warning: shape too complex to fill");
  2901. return [];
  2902. }
  2903. }
  2904. }
  2905. tgs.push(avl[0], avl[1], avl[2]);
  2906. return tgs;
  2907. };
  2908. /**
  2909. * Checks whether a point is within a triangle
  2910. *
  2911. * @method _PointInTriangle
  2912. * @param px {Number} x coordinate of the point to test
  2913. * @param py {Number} y coordinate of the point to test
  2914. * @param ax {Number} x coordinate of the a point of the triangle
  2915. * @param ay {Number} y coordinate of the a point of the triangle
  2916. * @param bx {Number} x coordinate of the b point of the triangle
  2917. * @param by {Number} y coordinate of the b point of the triangle
  2918. * @param cx {Number} x coordinate of the c point of the triangle
  2919. * @param cy {Number} y coordinate of the c point of the triangle
  2920. * @private
  2921. */
  2922. PIXI.PolyK._PointInTriangle = function(px, py, ax, ay, bx, by, cx, cy)
  2923. {
  2924. var v0x = cx-ax;
  2925. var v0y = cy-ay;
  2926. var v1x = bx-ax;
  2927. var v1y = by-ay;
  2928. var v2x = px-ax;
  2929. var v2y = py-ay;
  2930. var dot00 = v0x*v0x+v0y*v0y;
  2931. var dot01 = v0x*v1x+v0y*v1y;
  2932. var dot02 = v0x*v2x+v0y*v2y;
  2933. var dot11 = v1x*v1x+v1y*v1y;
  2934. var dot12 = v1x*v2x+v1y*v2y;
  2935. var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
  2936. var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  2937. var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
  2938. // Check if point is in triangle
  2939. return (u >= 0) && (v >= 0) && (u + v < 1);
  2940. };
  2941. /**
  2942. * Checks whether a shape is convex
  2943. *
  2944. * @method _convex
  2945. *
  2946. * @private
  2947. */
  2948. PIXI.PolyK._convex = function(ax, ay, bx, by, cx, cy, sign)
  2949. {
  2950. return ((ay-by)*(cx-bx) + (bx-ax)*(cy-by) >= 0) === sign;
  2951. };
  2952. /**
  2953. * @author Mat Groves http://matgroves.com/ @Doormat23
  2954. */
  2955. // TODO Alvin and Mat
  2956. // Should we eventually create a Utils class ?
  2957. // Or just move this file to the pixi.js file ?
  2958. PIXI.initDefaultShaders = function()
  2959. {
  2960. // PIXI.stripShader = new PIXI.StripShader();
  2961. // PIXI.stripShader.init();
  2962. };
  2963. PIXI.CompileVertexShader = function(gl, shaderSrc)
  2964. {
  2965. return PIXI._CompileShader(gl, shaderSrc, gl.VERTEX_SHADER);
  2966. };
  2967. PIXI.CompileFragmentShader = function(gl, shaderSrc)
  2968. {
  2969. return PIXI._CompileShader(gl, shaderSrc, gl.FRAGMENT_SHADER);
  2970. };
  2971. PIXI._CompileShader = function(gl, shaderSrc, shaderType)
  2972. {
  2973. var src = shaderSrc.join("\n");
  2974. var shader = gl.createShader(shaderType);
  2975. gl.shaderSource(shader, src);
  2976. gl.compileShader(shader);
  2977. if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
  2978. window.console.log(gl.getShaderInfoLog(shader));
  2979. return null;
  2980. }
  2981. return shader;
  2982. };
  2983. PIXI.compileProgram = function(gl, vertexSrc, fragmentSrc)
  2984. {
  2985. var fragmentShader = PIXI.CompileFragmentShader(gl, fragmentSrc);
  2986. var vertexShader = PIXI.CompileVertexShader(gl, vertexSrc);
  2987. var shaderProgram = gl.createProgram();
  2988. gl.attachShader(shaderProgram, vertexShader);
  2989. gl.attachShader(shaderProgram, fragmentShader);
  2990. gl.linkProgram(shaderProgram);
  2991. if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
  2992. window.console.log("Could not initialise shaders");
  2993. }
  2994. return shaderProgram;
  2995. };
  2996. /**
  2997. * @author Mat Groves http://matgroves.com/ @Doormat23
  2998. * @author Richard Davey http://www.photonstorm.com @photonstorm
  2999. */
  3000. /**
  3001. * @class PixiShader
  3002. * @constructor
  3003. */
  3004. PIXI.PixiShader = function(gl)
  3005. {
  3006. /**
  3007. * @property gl
  3008. * @type WebGLContext
  3009. */
  3010. this.gl = gl;
  3011. /**
  3012. * @property {any} program - The WebGL program.
  3013. */
  3014. this.program = null;
  3015. /**
  3016. * @property {array} fragmentSrc - The fragment shader.
  3017. */
  3018. this.fragmentSrc = [
  3019. 'precision lowp float;',
  3020. 'varying vec2 vTextureCoord;',
  3021. 'varying vec4 vColor;',
  3022. 'uniform sampler2D uSampler;',
  3023. 'void main(void) {',
  3024. ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
  3025. '}'
  3026. ];
  3027. /**
  3028. * @property {number} textureCount - A local texture counter for multi-texture shaders.
  3029. */
  3030. this.textureCount = 0;
  3031. this.attributes = [];
  3032. this.init();
  3033. };
  3034. /**
  3035. * Initialises the shader
  3036. * @method init
  3037. *
  3038. */
  3039. PIXI.PixiShader.prototype.init = function()
  3040. {
  3041. var gl = this.gl;
  3042. var program = PIXI.compileProgram(gl, this.vertexSrc || PIXI.PixiShader.defaultVertexSrc, this.fragmentSrc);
  3043. gl.useProgram(program);
  3044. // get and store the uniforms for the shader
  3045. this.uSampler = gl.getUniformLocation(program, 'uSampler');
  3046. this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
  3047. this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
  3048. this.dimensions = gl.getUniformLocation(program, 'dimensions');
  3049. // get and store the attributes
  3050. this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
  3051. this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
  3052. this.colorAttribute = gl.getAttribLocation(program, 'aColor');
  3053. // Begin worst hack eva //
  3054. // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
  3055. // maybe its something to do with the current state of the gl context.
  3056. // Im convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
  3057. // If theres any webGL people that know why could happen please help :)
  3058. if(this.colorAttribute === -1)
  3059. {
  3060. this.colorAttribute = 2;
  3061. }
  3062. this.attributes = [this.aVertexPosition, this.aTextureCoord, this.colorAttribute];
  3063. // End worst hack eva //
  3064. // add those custom shaders!
  3065. for (var key in this.uniforms)
  3066. {
  3067. // get the uniform locations..
  3068. this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key);
  3069. }
  3070. this.initUniforms();
  3071. this.program = program;
  3072. };
  3073. /**
  3074. * Initialises the shader uniform values.
  3075. * Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/
  3076. * http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf
  3077. *
  3078. * @method initUniforms
  3079. */
  3080. PIXI.PixiShader.prototype.initUniforms = function()
  3081. {
  3082. this.textureCount = 1;
  3083. var gl = this.gl;
  3084. var uniform;
  3085. for (var key in this.uniforms)
  3086. {
  3087. uniform = this.uniforms[key];
  3088. var type = uniform.type;
  3089. if (type === 'sampler2D')
  3090. {
  3091. uniform._init = false;
  3092. if (uniform.value !== null)
  3093. {
  3094. this.initSampler2D(uniform);
  3095. }
  3096. }
  3097. else if (type === 'mat2' || type === 'mat3' || type === 'mat4')
  3098. {
  3099. // These require special handling
  3100. uniform.glMatrix = true;
  3101. uniform.glValueLength = 1;
  3102. if (type === 'mat2')
  3103. {
  3104. uniform.glFunc = gl.uniformMatrix2fv;
  3105. }
  3106. else if (type === 'mat3')
  3107. {
  3108. uniform.glFunc = gl.uniformMatrix3fv;
  3109. }
  3110. else if (type === 'mat4')
  3111. {
  3112. uniform.glFunc = gl.uniformMatrix4fv;
  3113. }
  3114. }
  3115. else
  3116. {
  3117. // GL function reference
  3118. uniform.glFunc = gl['uniform' + type];
  3119. if (type === '2f' || type === '2i')
  3120. {
  3121. uniform.glValueLength = 2;
  3122. }
  3123. else if (type === '3f' || type === '3i')
  3124. {
  3125. uniform.glValueLength = 3;
  3126. }
  3127. else if (type === '4f' || type === '4i')
  3128. {
  3129. uniform.glValueLength = 4;
  3130. }
  3131. else
  3132. {
  3133. uniform.glValueLength = 1;
  3134. }
  3135. }
  3136. }
  3137. };
  3138. /**
  3139. * Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture has loaded)
  3140. *
  3141. * @method initSampler2D
  3142. */
  3143. PIXI.PixiShader.prototype.initSampler2D = function(uniform)
  3144. {
  3145. if (!uniform.value || !uniform.value.baseTexture || !uniform.value.baseTexture.hasLoaded)
  3146. {
  3147. return;
  3148. }
  3149. var gl = this.gl;
  3150. gl.activeTexture(gl['TEXTURE' + this.textureCount]);
  3151. gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id]);
  3152. // Extended texture data
  3153. if (uniform.textureData)
  3154. {
  3155. var data = uniform.textureData;
  3156. // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D);
  3157. // GLTextureLinear = mag/min linear, wrap clamp
  3158. // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat
  3159. // GLTextureNearest = mag/min nearest, wrap clamp
  3160. // AudioTexture = whatever + luminance + width 512, height 2, border 0
  3161. // KeyTexture = whatever + luminance + width 256, height 2, border 0
  3162. // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST
  3163. // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT
  3164. var magFilter = (data.magFilter) ? data.magFilter : gl.LINEAR;
  3165. var minFilter = (data.minFilter) ? data.minFilter : gl.LINEAR;
  3166. var wrapS = (data.wrapS) ? data.wrapS : gl.CLAMP_TO_EDGE;
  3167. var wrapT = (data.wrapT) ? data.wrapT : gl.CLAMP_TO_EDGE;
  3168. var format = (data.luminance) ? gl.LUMINANCE : gl.RGBA;
  3169. if (data.repeat)
  3170. {
  3171. wrapS = gl.REPEAT;
  3172. wrapT = gl.REPEAT;
  3173. }
  3174. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, !!data.flipY);
  3175. if (data.width)
  3176. {
  3177. var width = (data.width) ? data.width : 512;
  3178. var height = (data.height) ? data.height : 2;
  3179. var border = (data.border) ? data.border : 0;
  3180. // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels);
  3181. gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, border, format, gl.UNSIGNED_BYTE, null);
  3182. }
  3183. else
  3184. {
  3185. // void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, ImageData? pixels);
  3186. gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, uniform.value.baseTexture.source);
  3187. }
  3188. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
  3189. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
  3190. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
  3191. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
  3192. }
  3193. gl.uniform1i(uniform.uniformLocation, this.textureCount);
  3194. uniform._init = true;
  3195. this.textureCount++;
  3196. };
  3197. /**
  3198. * Updates the shader uniform values.
  3199. *
  3200. * @method syncUniforms
  3201. */
  3202. PIXI.PixiShader.prototype.syncUniforms = function()
  3203. {
  3204. this.textureCount = 1;
  3205. var uniform;
  3206. var gl = this.gl;
  3207. // This would probably be faster in an array and it would guarantee key order
  3208. for (var key in this.uniforms)
  3209. {
  3210. uniform = this.uniforms[key];
  3211. if (uniform.glValueLength === 1)
  3212. {
  3213. if (uniform.glMatrix === true)
  3214. {
  3215. uniform.glFunc.call(gl, uniform.uniformLocation, uniform.transpose, uniform.value);
  3216. }
  3217. else
  3218. {
  3219. uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value);
  3220. }
  3221. }
  3222. else if (uniform.glValueLength === 2)
  3223. {
  3224. uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y);
  3225. }
  3226. else if (uniform.glValueLength === 3)
  3227. {
  3228. uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z);
  3229. }
  3230. else if (uniform.glValueLength === 4)
  3231. {
  3232. uniform.glFunc.call(gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w);
  3233. }
  3234. else if (uniform.type === 'sampler2D')
  3235. {
  3236. if (uniform._init)
  3237. {
  3238. gl.activeTexture(gl['TEXTURE' + this.textureCount]);
  3239. gl.bindTexture(gl.TEXTURE_2D, uniform.value.baseTexture._glTextures[gl.id] || PIXI.createWebGLTexture( uniform.value.baseTexture, gl));
  3240. gl.uniform1i(uniform.uniformLocation, this.textureCount);
  3241. this.textureCount++;
  3242. }
  3243. else
  3244. {
  3245. this.initSampler2D(uniform);
  3246. }
  3247. }
  3248. }
  3249. };
  3250. /**
  3251. * Destroys the shader
  3252. * @method destroy
  3253. */
  3254. PIXI.PixiShader.prototype.destroy = function()
  3255. {
  3256. this.gl.deleteProgram( this.program );
  3257. this.uniforms = null;
  3258. this.gl = null;
  3259. this.attributes = null;
  3260. };
  3261. /**
  3262. * The Default Vertex shader source
  3263. * @property defaultVertexSrc
  3264. * @type String
  3265. */
  3266. PIXI.PixiShader.defaultVertexSrc = [
  3267. 'attribute vec2 aVertexPosition;',
  3268. 'attribute vec2 aTextureCoord;',
  3269. 'attribute vec2 aColor;',
  3270. 'uniform vec2 projectionVector;',
  3271. 'uniform vec2 offsetVector;',
  3272. 'varying vec2 vTextureCoord;',
  3273. 'varying vec4 vColor;',
  3274. 'const vec2 center = vec2(-1.0, 1.0);',
  3275. 'void main(void) {',
  3276. ' gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);',
  3277. ' vTextureCoord = aTextureCoord;',
  3278. ' vec3 color = mod(vec3(aColor.y/65536.0, aColor.y/256.0, aColor.y), 256.0) / 256.0;',
  3279. ' vColor = vec4(color * aColor.x, aColor.x);',
  3280. '}'
  3281. ];
  3282. /**
  3283. * @author Mat Groves http://matgroves.com/ @Doormat23
  3284. * @author Richard Davey http://www.photonstorm.com @photonstorm
  3285. */
  3286. /**
  3287. * @class PixiFastShader
  3288. * @constructor
  3289. * @param gl {WebGLContext} the current WebGL drawing context
  3290. */
  3291. PIXI.PixiFastShader = function(gl)
  3292. {
  3293. /**
  3294. * @property gl
  3295. * @type WebGLContext
  3296. */
  3297. this.gl = gl;
  3298. /**
  3299. * @property {any} program - The WebGL program.
  3300. */
  3301. this.program = null;
  3302. /**
  3303. * @property {array} fragmentSrc - The fragment shader.
  3304. */
  3305. this.fragmentSrc = [
  3306. 'precision lowp float;',
  3307. 'varying vec2 vTextureCoord;',
  3308. 'varying float vColor;',
  3309. 'uniform sampler2D uSampler;',
  3310. 'void main(void) {',
  3311. ' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;',
  3312. '}'
  3313. ];
  3314. /**
  3315. * @property {array} vertexSrc - The vertex shader
  3316. */
  3317. this.vertexSrc = [
  3318. 'attribute vec2 aVertexPosition;',
  3319. 'attribute vec2 aPositionCoord;',
  3320. 'attribute vec2 aScale;',
  3321. 'attribute float aRotation;',
  3322. 'attribute vec2 aTextureCoord;',
  3323. 'attribute float aColor;',
  3324. 'uniform vec2 projectionVector;',
  3325. 'uniform vec2 offsetVector;',
  3326. 'uniform mat3 uMatrix;',
  3327. 'varying vec2 vTextureCoord;',
  3328. 'varying float vColor;',
  3329. 'const vec2 center = vec2(-1.0, 1.0);',
  3330. 'void main(void) {',
  3331. ' vec2 v;',
  3332. ' vec2 sv = aVertexPosition * aScale;',
  3333. ' v.x = (sv.x) * cos(aRotation) - (sv.y) * sin(aRotation);',
  3334. ' v.y = (sv.x) * sin(aRotation) + (sv.y) * cos(aRotation);',
  3335. ' v = ( uMatrix * vec3(v + aPositionCoord , 1.0) ).xy ;',
  3336. ' gl_Position = vec4( ( v / projectionVector) + center , 0.0, 1.0);',
  3337. ' vTextureCoord = aTextureCoord;',
  3338. // ' vec3 color = mod(vec3(aColor.y/65536.0, aColor.y/256.0, aColor.y), 256.0) / 256.0;',
  3339. ' vColor = aColor;',
  3340. '}'
  3341. ];
  3342. /**
  3343. * @property {number} textureCount - A local texture counter for multi-texture shaders.
  3344. */
  3345. this.textureCount = 0;
  3346. this.init();
  3347. };
  3348. /**
  3349. * Initialises the shader
  3350. * @method init
  3351. *
  3352. */
  3353. PIXI.PixiFastShader.prototype.init = function()
  3354. {
  3355. var gl = this.gl;
  3356. var program = PIXI.compileProgram(gl, this.vertexSrc, this.fragmentSrc);
  3357. gl.useProgram(program);
  3358. // get and store the uniforms for the shader
  3359. this.uSampler = gl.getUniformLocation(program, 'uSampler');
  3360. this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
  3361. this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
  3362. this.dimensions = gl.getUniformLocation(program, 'dimensions');
  3363. this.uMatrix = gl.getUniformLocation(program, 'uMatrix');
  3364. // get and store the attributes
  3365. this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
  3366. this.aPositionCoord = gl.getAttribLocation(program, 'aPositionCoord');
  3367. this.aScale = gl.getAttribLocation(program, 'aScale');
  3368. this.aRotation = gl.getAttribLocation(program, 'aRotation');
  3369. this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
  3370. this.colorAttribute = gl.getAttribLocation(program, 'aColor');
  3371. // Begin worst hack eva //
  3372. // WHY??? ONLY on my chrome pixel the line above returns -1 when using filters?
  3373. // maybe its somthing to do with the current state of the gl context.
  3374. // Im convinced this is a bug in the chrome browser as there is NO reason why this should be returning -1 especially as it only manifests on my chrome pixel
  3375. // If theres any webGL people that know why could happen please help :)
  3376. if(this.colorAttribute === -1)
  3377. {
  3378. this.colorAttribute = 2;
  3379. }
  3380. this.attributes = [this.aVertexPosition, this.aPositionCoord, this.aScale, this.aRotation, this.aTextureCoord, this.colorAttribute];
  3381. // End worst hack eva //
  3382. this.program = program;
  3383. };
  3384. /**
  3385. * Destroys the shader
  3386. * @method destroy
  3387. *
  3388. */
  3389. PIXI.PixiFastShader.prototype.destroy = function()
  3390. {
  3391. this.gl.deleteProgram( this.program );
  3392. this.uniforms = null;
  3393. this.gl = null;
  3394. this.attributes = null;
  3395. };
  3396. /**
  3397. * @author Mat Groves http://matgroves.com/ @Doormat23
  3398. */
  3399. PIXI.StripShader = function()
  3400. {
  3401. /**
  3402. * @property {any} program - The WebGL program.
  3403. */
  3404. this.program = null;
  3405. /**
  3406. * @property {array} fragmentSrc - The fragment shader.
  3407. */
  3408. this.fragmentSrc = [
  3409. 'precision mediump float;',
  3410. 'varying vec2 vTextureCoord;',
  3411. 'varying float vColor;',
  3412. 'uniform float alpha;',
  3413. 'uniform sampler2D uSampler;',
  3414. 'void main(void) {',
  3415. ' gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y));',
  3416. ' gl_FragColor = gl_FragColor * alpha;',
  3417. '}'
  3418. ];
  3419. /**
  3420. * @property {array} fragmentSrc - The fragment shader.
  3421. */
  3422. this.vertexSrc = [
  3423. 'attribute vec2 aVertexPosition;',
  3424. 'attribute vec2 aTextureCoord;',
  3425. 'attribute float aColor;',
  3426. 'uniform mat3 translationMatrix;',
  3427. 'uniform vec2 projectionVector;',
  3428. 'varying vec2 vTextureCoord;',
  3429. 'uniform vec2 offsetVector;',
  3430. 'varying float vColor;',
  3431. 'void main(void) {',
  3432. ' vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);',
  3433. ' v -= offsetVector.xyx;',
  3434. ' gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / projectionVector.y + 1.0 , 0.0, 1.0);',
  3435. ' vTextureCoord = aTextureCoord;',
  3436. ' vColor = aColor;',
  3437. '}'
  3438. ];
  3439. };
  3440. /**
  3441. * Initialises the shader
  3442. * @method init
  3443. *
  3444. */
  3445. PIXI.StripShader.prototype.init = function()
  3446. {
  3447. var gl = PIXI.gl;
  3448. var program = PIXI.compileProgram(gl, this.vertexSrc, this.fragmentSrc);
  3449. gl.useProgram(program);
  3450. // get and store the uniforms for the shader
  3451. this.uSampler = gl.getUniformLocation(program, 'uSampler');
  3452. this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
  3453. this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
  3454. this.colorAttribute = gl.getAttribLocation(program, 'aColor');
  3455. //this.dimensions = gl.getUniformLocation(this.program, 'dimensions');
  3456. // get and store the attributes
  3457. this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
  3458. this.aTextureCoord = gl.getAttribLocation(program, 'aTextureCoord');
  3459. this.translationMatrix = gl.getUniformLocation(program, 'translationMatrix');
  3460. this.alpha = gl.getUniformLocation(program, 'alpha');
  3461. this.program = program;
  3462. };
  3463. /**
  3464. * @author Mat Groves http://matgroves.com/ @Doormat23
  3465. */
  3466. /**
  3467. * @class PrimitiveShader
  3468. * @constructor
  3469. * @param gl {WebGLContext} the current WebGL drawing context
  3470. */
  3471. PIXI.PrimitiveShader = function(gl)
  3472. {
  3473. /**
  3474. * @property gl
  3475. * @type WebGLContext
  3476. */
  3477. this.gl = gl;
  3478. /**
  3479. * @property {any} program - The WebGL program.
  3480. */
  3481. this.program = null;
  3482. /**
  3483. * @property fragmentSrc
  3484. * @type Array
  3485. */
  3486. this.fragmentSrc = [
  3487. 'precision mediump float;',
  3488. 'varying vec4 vColor;',
  3489. 'void main(void) {',
  3490. ' gl_FragColor = vColor;',
  3491. '}'
  3492. ];
  3493. /**
  3494. * @property vertexSrc
  3495. * @type Array
  3496. */
  3497. this.vertexSrc = [
  3498. 'attribute vec2 aVertexPosition;',
  3499. 'attribute vec4 aColor;',
  3500. 'uniform mat3 translationMatrix;',
  3501. 'uniform vec2 projectionVector;',
  3502. 'uniform vec2 offsetVector;',
  3503. 'uniform float alpha;',
  3504. 'uniform vec3 tint;',
  3505. 'varying vec4 vColor;',
  3506. 'void main(void) {',
  3507. ' vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);',
  3508. ' v -= offsetVector.xyx;',
  3509. ' gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);',
  3510. ' vColor = aColor * vec4(tint * alpha, alpha);',
  3511. '}'
  3512. ];
  3513. this.init();
  3514. };
  3515. /**
  3516. * Initialises the shader
  3517. * @method init
  3518. *
  3519. */
  3520. PIXI.PrimitiveShader.prototype.init = function()
  3521. {
  3522. var gl = this.gl;
  3523. var program = PIXI.compileProgram(gl, this.vertexSrc, this.fragmentSrc);
  3524. gl.useProgram(program);
  3525. // get and store the uniforms for the shader
  3526. this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
  3527. this.offsetVector = gl.getUniformLocation(program, 'offsetVector');
  3528. this.tintColor = gl.getUniformLocation(program, 'tint');
  3529. // get and store the attributes
  3530. this.aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
  3531. this.colorAttribute = gl.getAttribLocation(program, 'aColor');
  3532. this.attributes = [this.aVertexPosition, this.colorAttribute];
  3533. this.translationMatrix = gl.getUniformLocation(program, 'translationMatrix');
  3534. this.alpha = gl.getUniformLocation(program, 'alpha');
  3535. this.program = program;
  3536. };
  3537. /**
  3538. * Destroys the shader
  3539. * @method destroy
  3540. *
  3541. */
  3542. PIXI.PrimitiveShader.prototype.destroy = function()
  3543. {
  3544. this.gl.deleteProgram( this.program );
  3545. this.uniforms = null;
  3546. this.gl = null;
  3547. this.attribute = null;
  3548. };
  3549. /**
  3550. * @author Mat Groves http://matgroves.com/ @Doormat23
  3551. */
  3552. /**
  3553. * A set of functions used by the webGL renderer to draw the primitive graphics data
  3554. *
  3555. * @class WebGLGraphics
  3556. * @private
  3557. * @static
  3558. */
  3559. PIXI.WebGLGraphics = function()
  3560. {
  3561. };
  3562. /**
  3563. * Renders the graphics object
  3564. *
  3565. * @static
  3566. * @private
  3567. * @method renderGraphics
  3568. * @param graphics {Graphics}
  3569. * @param renderSession {Object}
  3570. */
  3571. PIXI.WebGLGraphics.renderGraphics = function(graphics, renderSession)//projection, offset)
  3572. {
  3573. var gl = renderSession.gl;
  3574. var projection = renderSession.projection,
  3575. offset = renderSession.offset,
  3576. shader = renderSession.shaderManager.primitiveShader;
  3577. if(!graphics._webGL[gl.id])graphics._webGL[gl.id] = {points:[], indices:[], lastIndex:0,
  3578. buffer:gl.createBuffer(),
  3579. indexBuffer:gl.createBuffer()};
  3580. var webGL = graphics._webGL[gl.id];
  3581. if(graphics.dirty)
  3582. {
  3583. graphics.dirty = false;
  3584. if(graphics.clearDirty)
  3585. {
  3586. graphics.clearDirty = false;
  3587. webGL.lastIndex = 0;
  3588. webGL.points = [];
  3589. webGL.indices = [];
  3590. }
  3591. PIXI.WebGLGraphics.updateGraphics(graphics, gl);
  3592. }
  3593. renderSession.shaderManager.activatePrimitiveShader();
  3594. // This could be speeded up for sure!
  3595. // set the matrix transform
  3596. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  3597. gl.uniformMatrix3fv(shader.translationMatrix, false, graphics.worldTransform.toArray(true));
  3598. gl.uniform2f(shader.projectionVector, projection.x, -projection.y);
  3599. gl.uniform2f(shader.offsetVector, -offset.x, -offset.y);
  3600. gl.uniform3fv(shader.tintColor, PIXI.hex2rgb(graphics.tint));
  3601. gl.uniform1f(shader.alpha, graphics.worldAlpha);
  3602. gl.bindBuffer(gl.ARRAY_BUFFER, webGL.buffer);
  3603. gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0);
  3604. gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false,4 * 6, 2 * 4);
  3605. // set the index buffer!
  3606. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGL.indexBuffer);
  3607. gl.drawElements(gl.TRIANGLE_STRIP, webGL.indices.length, gl.UNSIGNED_SHORT, 0 );
  3608. renderSession.shaderManager.deactivatePrimitiveShader();
  3609. // return to default shader...
  3610. // PIXI.activateShader(PIXI.defaultShader);
  3611. };
  3612. /**
  3613. * Updates the graphics object
  3614. *
  3615. * @static
  3616. * @private
  3617. * @method updateGraphics
  3618. * @param graphicsData {Graphics} The graphics object to update
  3619. * @param gl {WebGLContext} the current WebGL drawing context
  3620. */
  3621. PIXI.WebGLGraphics.updateGraphics = function(graphics, gl)
  3622. {
  3623. var webGL = graphics._webGL[gl.id];
  3624. for (var i = webGL.lastIndex; i < graphics.graphicsData.length; i++)
  3625. {
  3626. var data = graphics.graphicsData[i];
  3627. if(data.type === PIXI.Graphics.POLY)
  3628. {
  3629. if(data.fill)
  3630. {
  3631. if(data.points.length>3)
  3632. PIXI.WebGLGraphics.buildPoly(data, webGL);
  3633. }
  3634. if(data.lineWidth > 0)
  3635. {
  3636. PIXI.WebGLGraphics.buildLine(data, webGL);
  3637. }
  3638. }
  3639. else if(data.type === PIXI.Graphics.RECT)
  3640. {
  3641. PIXI.WebGLGraphics.buildRectangle(data, webGL);
  3642. }
  3643. else if(data.type === PIXI.Graphics.CIRC || data.type === PIXI.Graphics.ELIP)
  3644. {
  3645. PIXI.WebGLGraphics.buildCircle(data, webGL);
  3646. }
  3647. }
  3648. webGL.lastIndex = graphics.graphicsData.length;
  3649. webGL.glPoints = new Float32Array(webGL.points);
  3650. gl.bindBuffer(gl.ARRAY_BUFFER, webGL.buffer);
  3651. gl.bufferData(gl.ARRAY_BUFFER, webGL.glPoints, gl.STATIC_DRAW);
  3652. webGL.glIndicies = new Uint16Array(webGL.indices);
  3653. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGL.indexBuffer);
  3654. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, webGL.glIndicies, gl.STATIC_DRAW);
  3655. };
  3656. /**
  3657. * Builds a rectangle to draw
  3658. *
  3659. * @static
  3660. * @private
  3661. * @method buildRectangle
  3662. * @param graphicsData {Graphics} The graphics object containing all the necessary properties
  3663. * @param webGLData {Object}
  3664. */
  3665. PIXI.WebGLGraphics.buildRectangle = function(graphicsData, webGLData)
  3666. {
  3667. // --- //
  3668. // need to convert points to a nice regular data
  3669. //
  3670. var rectData = graphicsData.points;
  3671. var x = rectData[0];
  3672. var y = rectData[1];
  3673. var width = rectData[2];
  3674. var height = rectData[3];
  3675. if(graphicsData.fill)
  3676. {
  3677. var color = PIXI.hex2rgb(graphicsData.fillColor);
  3678. var alpha = graphicsData.fillAlpha;
  3679. var r = color[0] * alpha;
  3680. var g = color[1] * alpha;
  3681. var b = color[2] * alpha;
  3682. var verts = webGLData.points;
  3683. var indices = webGLData.indices;
  3684. var vertPos = verts.length/6;
  3685. // start
  3686. verts.push(x, y);
  3687. verts.push(r, g, b, alpha);
  3688. verts.push(x + width, y);
  3689. verts.push(r, g, b, alpha);
  3690. verts.push(x , y + height);
  3691. verts.push(r, g, b, alpha);
  3692. verts.push(x + width, y + height);
  3693. verts.push(r, g, b, alpha);
  3694. // insert 2 dead triangles..
  3695. indices.push(vertPos, vertPos, vertPos+1, vertPos+2, vertPos+3, vertPos+3);
  3696. }
  3697. if(graphicsData.lineWidth)
  3698. {
  3699. var tempPoints = graphicsData.points;
  3700. graphicsData.points = [x, y,
  3701. x + width, y,
  3702. x + width, y + height,
  3703. x, y + height,
  3704. x, y];
  3705. PIXI.WebGLGraphics.buildLine(graphicsData, webGLData);
  3706. graphicsData.points = tempPoints;
  3707. }
  3708. };
  3709. /**
  3710. * Builds a circle to draw
  3711. *
  3712. * @static
  3713. * @private
  3714. * @method buildCircle
  3715. * @param graphicsData {Graphics} The graphics object to draw
  3716. * @param webGLData {Object}
  3717. */
  3718. PIXI.WebGLGraphics.buildCircle = function(graphicsData, webGLData)
  3719. {
  3720. // need to convert points to a nice regular data
  3721. var rectData = graphicsData.points;
  3722. var x = rectData[0];
  3723. var y = rectData[1];
  3724. var width = rectData[2];
  3725. var height = rectData[3];
  3726. var totalSegs = 40;
  3727. var seg = (Math.PI * 2) / totalSegs ;
  3728. var i = 0;
  3729. if(graphicsData.fill)
  3730. {
  3731. var color = PIXI.hex2rgb(graphicsData.fillColor);
  3732. var alpha = graphicsData.fillAlpha;
  3733. var r = color[0] * alpha;
  3734. var g = color[1] * alpha;
  3735. var b = color[2] * alpha;
  3736. var verts = webGLData.points;
  3737. var indices = webGLData.indices;
  3738. var vecPos = verts.length/6;
  3739. indices.push(vecPos);
  3740. for (i = 0; i < totalSegs + 1 ; i++)
  3741. {
  3742. verts.push(x,y, r, g, b, alpha);
  3743. verts.push(x + Math.sin(seg * i) * width,
  3744. y + Math.cos(seg * i) * height,
  3745. r, g, b, alpha);
  3746. indices.push(vecPos++, vecPos++);
  3747. }
  3748. indices.push(vecPos-1);
  3749. }
  3750. if(graphicsData.lineWidth)
  3751. {
  3752. var tempPoints = graphicsData.points;
  3753. graphicsData.points = [];
  3754. for (i = 0; i < totalSegs + 1; i++)
  3755. {
  3756. graphicsData.points.push(x + Math.sin(seg * i) * width,
  3757. y + Math.cos(seg * i) * height);
  3758. }
  3759. PIXI.WebGLGraphics.buildLine(graphicsData, webGLData);
  3760. graphicsData.points = tempPoints;
  3761. }
  3762. };
  3763. /**
  3764. * Builds a line to draw
  3765. *
  3766. * @static
  3767. * @private
  3768. * @method buildLine
  3769. * @param graphicsData {Graphics} The graphics object containing all the necessary properties
  3770. * @param webGLData {Object}
  3771. */
  3772. PIXI.WebGLGraphics.buildLine = function(graphicsData, webGLData)
  3773. {
  3774. // TODO OPTIMISE!
  3775. var i = 0;
  3776. var points = graphicsData.points;
  3777. if(points.length === 0)return;
  3778. // if the line width is an odd number add 0.5 to align to a whole pixel
  3779. if(graphicsData.lineWidth%2)
  3780. {
  3781. for (i = 0; i < points.length; i++) {
  3782. points[i] += 0.5;
  3783. }
  3784. }
  3785. // get first and last point.. figure out the middle!
  3786. var firstPoint = new PIXI.Point( points[0], points[1] );
  3787. var lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] );
  3788. // if the first point is the last point - gonna have issues :)
  3789. if(firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y)
  3790. {
  3791. points.pop();
  3792. points.pop();
  3793. lastPoint = new PIXI.Point( points[points.length - 2], points[points.length - 1] );
  3794. var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) *0.5;
  3795. var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) *0.5;
  3796. points.unshift(midPointX, midPointY);
  3797. points.push(midPointX, midPointY);
  3798. }
  3799. var verts = webGLData.points;
  3800. var indices = webGLData.indices;
  3801. var length = points.length / 2;
  3802. var indexCount = points.length;
  3803. var indexStart = verts.length/6;
  3804. // DRAW the Line
  3805. var width = graphicsData.lineWidth / 2;
  3806. // sort color
  3807. var color = PIXI.hex2rgb(graphicsData.lineColor);
  3808. var alpha = graphicsData.lineAlpha;
  3809. var r = color[0] * alpha;
  3810. var g = color[1] * alpha;
  3811. var b = color[2] * alpha;
  3812. var px, py, p1x, p1y, p2x, p2y, p3x, p3y;
  3813. var perpx, perpy, perp2x, perp2y, perp3x, perp3y;
  3814. var a1, b1, c1, a2, b2, c2;
  3815. var denom, pdist, dist;
  3816. p1x = points[0];
  3817. p1y = points[1];
  3818. p2x = points[2];
  3819. p2y = points[3];
  3820. perpx = -(p1y - p2y);
  3821. perpy = p1x - p2x;
  3822. dist = Math.sqrt(perpx*perpx + perpy*perpy);
  3823. perpx /= dist;
  3824. perpy /= dist;
  3825. perpx *= width;
  3826. perpy *= width;
  3827. // start
  3828. verts.push(p1x - perpx , p1y - perpy,
  3829. r, g, b, alpha);
  3830. verts.push(p1x + perpx , p1y + perpy,
  3831. r, g, b, alpha);
  3832. for (i = 1; i < length-1; i++)
  3833. {
  3834. p1x = points[(i-1)*2];
  3835. p1y = points[(i-1)*2 + 1];
  3836. p2x = points[(i)*2];
  3837. p2y = points[(i)*2 + 1];
  3838. p3x = points[(i+1)*2];
  3839. p3y = points[(i+1)*2 + 1];
  3840. perpx = -(p1y - p2y);
  3841. perpy = p1x - p2x;
  3842. dist = Math.sqrt(perpx*perpx + perpy*perpy);
  3843. perpx /= dist;
  3844. perpy /= dist;
  3845. perpx *= width;
  3846. perpy *= width;
  3847. perp2x = -(p2y - p3y);
  3848. perp2y = p2x - p3x;
  3849. dist = Math.sqrt(perp2x*perp2x + perp2y*perp2y);
  3850. perp2x /= dist;
  3851. perp2y /= dist;
  3852. perp2x *= width;
  3853. perp2y *= width;
  3854. a1 = (-perpy + p1y) - (-perpy + p2y);
  3855. b1 = (-perpx + p2x) - (-perpx + p1x);
  3856. c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y);
  3857. a2 = (-perp2y + p3y) - (-perp2y + p2y);
  3858. b2 = (-perp2x + p2x) - (-perp2x + p3x);
  3859. c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y);
  3860. denom = a1*b2 - a2*b1;
  3861. if(Math.abs(denom) < 0.1 )
  3862. {
  3863. denom+=10.1;
  3864. verts.push(p2x - perpx , p2y - perpy,
  3865. r, g, b, alpha);
  3866. verts.push(p2x + perpx , p2y + perpy,
  3867. r, g, b, alpha);
  3868. continue;
  3869. }
  3870. px = (b1*c2 - b2*c1)/denom;
  3871. py = (a2*c1 - a1*c2)/denom;
  3872. pdist = (px -p2x) * (px -p2x) + (py -p2y) + (py -p2y);
  3873. if(pdist > 140 * 140)
  3874. {
  3875. perp3x = perpx - perp2x;
  3876. perp3y = perpy - perp2y;
  3877. dist = Math.sqrt(perp3x*perp3x + perp3y*perp3y);
  3878. perp3x /= dist;
  3879. perp3y /= dist;
  3880. perp3x *= width;
  3881. perp3y *= width;
  3882. verts.push(p2x - perp3x, p2y -perp3y);
  3883. verts.push(r, g, b, alpha);
  3884. verts.push(p2x + perp3x, p2y +perp3y);
  3885. verts.push(r, g, b, alpha);
  3886. verts.push(p2x - perp3x, p2y -perp3y);
  3887. verts.push(r, g, b, alpha);
  3888. indexCount++;
  3889. }
  3890. else
  3891. {
  3892. verts.push(px , py);
  3893. verts.push(r, g, b, alpha);
  3894. verts.push(p2x - (px-p2x), p2y - (py - p2y));
  3895. verts.push(r, g, b, alpha);
  3896. }
  3897. }
  3898. p1x = points[(length-2)*2];
  3899. p1y = points[(length-2)*2 + 1];
  3900. p2x = points[(length-1)*2];
  3901. p2y = points[(length-1)*2 + 1];
  3902. perpx = -(p1y - p2y);
  3903. perpy = p1x - p2x;
  3904. dist = Math.sqrt(perpx*perpx + perpy*perpy);
  3905. perpx /= dist;
  3906. perpy /= dist;
  3907. perpx *= width;
  3908. perpy *= width;
  3909. verts.push(p2x - perpx , p2y - perpy);
  3910. verts.push(r, g, b, alpha);
  3911. verts.push(p2x + perpx , p2y + perpy);
  3912. verts.push(r, g, b, alpha);
  3913. indices.push(indexStart);
  3914. for (i = 0; i < indexCount; i++)
  3915. {
  3916. indices.push(indexStart++);
  3917. }
  3918. indices.push(indexStart-1);
  3919. };
  3920. /**
  3921. * Builds a polygon to draw
  3922. *
  3923. * @static
  3924. * @private
  3925. * @method buildPoly
  3926. * @param graphicsData {Graphics} The graphics object containing all the necessary properties
  3927. * @param webGLData {Object}
  3928. */
  3929. PIXI.WebGLGraphics.buildPoly = function(graphicsData, webGLData)
  3930. {
  3931. var points = graphicsData.points;
  3932. if(points.length < 6)return;
  3933. // get first and last point.. figure out the middle!
  3934. var verts = webGLData.points;
  3935. var indices = webGLData.indices;
  3936. var length = points.length / 2;
  3937. // sort color
  3938. var color = PIXI.hex2rgb(graphicsData.fillColor);
  3939. var alpha = graphicsData.fillAlpha;
  3940. var r = color[0] * alpha;
  3941. var g = color[1] * alpha;
  3942. var b = color[2] * alpha;
  3943. var triangles = PIXI.PolyK.Triangulate(points);
  3944. var vertPos = verts.length / 6;
  3945. var i = 0;
  3946. for (i = 0; i < triangles.length; i+=3)
  3947. {
  3948. indices.push(triangles[i] + vertPos);
  3949. indices.push(triangles[i] + vertPos);
  3950. indices.push(triangles[i+1] + vertPos);
  3951. indices.push(triangles[i+2] +vertPos);
  3952. indices.push(triangles[i+2] + vertPos);
  3953. }
  3954. for (i = 0; i < length; i++)
  3955. {
  3956. verts.push(points[i * 2], points[i * 2 + 1],
  3957. r, g, b, alpha);
  3958. }
  3959. };
  3960. /**
  3961. * @author Mat Groves http://matgroves.com/ @Doormat23
  3962. */
  3963. PIXI.glContexts = []; // this is where we store the webGL contexts for easy access.
  3964. /**
  3965. * the WebGLRenderer draws the stage and all its content onto a webGL enabled canvas. This renderer
  3966. * should be used for browsers that support webGL. This Render works by automatically managing webGLBatch's.
  3967. * So no need for Sprite Batch's or Sprite Cloud's
  3968. * Dont forget to add the view to your DOM or you will not see anything :)
  3969. *
  3970. * @class WebGLRenderer
  3971. * @constructor
  3972. * @param width=0 {Number} the width of the canvas view
  3973. * @param height=0 {Number} the height of the canvas view
  3974. * @param view {HTMLCanvasElement} the canvas to use as a view, optional
  3975. * @param transparent=false {Boolean} If the render view is transparent, default false
  3976. * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment)
  3977. *
  3978. */
  3979. PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
  3980. {
  3981. if(!PIXI.defaultRenderer)PIXI.defaultRenderer = this;
  3982. this.type = PIXI.WEBGL_RENDERER;
  3983. // do a catch.. only 1 webGL renderer..
  3984. /**
  3985. * Whether the render view is transparent
  3986. *
  3987. * @property transparent
  3988. * @type Boolean
  3989. */
  3990. this.transparent = !!transparent;
  3991. /**
  3992. * The width of the canvas view
  3993. *
  3994. * @property width
  3995. * @type Number
  3996. * @default 800
  3997. */
  3998. this.width = width || 800;
  3999. /**
  4000. * The height of the canvas view
  4001. *
  4002. * @property height
  4003. * @type Number
  4004. * @default 600
  4005. */
  4006. this.height = height || 600;
  4007. /**
  4008. * The canvas element that everything is drawn to
  4009. *
  4010. * @property view
  4011. * @type HTMLCanvasElement
  4012. */
  4013. this.view = view || document.createElement( 'canvas' );
  4014. this.view.width = this.width;
  4015. this.view.height = this.height;
  4016. // deal with losing context..
  4017. this.contextLost = this.handleContextLost.bind(this);
  4018. this.contextRestoredLost = this.handleContextRestored.bind(this);
  4019. this.view.addEventListener('webglcontextlost', this.contextLost, false);
  4020. this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false);
  4021. this.options = {
  4022. alpha: this.transparent,
  4023. antialias:!!antialias, // SPEED UP??
  4024. premultipliedAlpha:!!transparent,
  4025. stencil:true
  4026. };
  4027. //try 'experimental-webgl'
  4028. try {
  4029. this.gl = this.view.getContext('experimental-webgl', this.options);
  4030. } catch (e) {
  4031. //try 'webgl'
  4032. try {
  4033. this.gl = this.view.getContext('webgl', this.options);
  4034. } catch (e2) {
  4035. // fail, not able to get a context
  4036. throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
  4037. }
  4038. }
  4039. var gl = this.gl;
  4040. this.glContextId = gl.id = PIXI.WebGLRenderer.glContextId ++;
  4041. PIXI.glContexts[this.glContextId] = gl;
  4042. if(!PIXI.blendModesWebGL)
  4043. {
  4044. PIXI.blendModesWebGL = [];
  4045. PIXI.blendModesWebGL[PIXI.blendModes.NORMAL] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4046. PIXI.blendModesWebGL[PIXI.blendModes.ADD] = [gl.SRC_ALPHA, gl.DST_ALPHA];
  4047. PIXI.blendModesWebGL[PIXI.blendModes.MULTIPLY] = [gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA];
  4048. PIXI.blendModesWebGL[PIXI.blendModes.SCREEN] = [gl.SRC_ALPHA, gl.ONE];
  4049. PIXI.blendModesWebGL[PIXI.blendModes.OVERLAY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4050. PIXI.blendModesWebGL[PIXI.blendModes.DARKEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4051. PIXI.blendModesWebGL[PIXI.blendModes.LIGHTEN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4052. PIXI.blendModesWebGL[PIXI.blendModes.COLOR_DODGE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4053. PIXI.blendModesWebGL[PIXI.blendModes.COLOR_BURN] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4054. PIXI.blendModesWebGL[PIXI.blendModes.HARD_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4055. PIXI.blendModesWebGL[PIXI.blendModes.SOFT_LIGHT] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4056. PIXI.blendModesWebGL[PIXI.blendModes.DIFFERENCE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4057. PIXI.blendModesWebGL[PIXI.blendModes.EXCLUSION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4058. PIXI.blendModesWebGL[PIXI.blendModes.HUE] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4059. PIXI.blendModesWebGL[PIXI.blendModes.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4060. PIXI.blendModesWebGL[PIXI.blendModes.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4061. PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA];
  4062. }
  4063. this.projection = new PIXI.Point();
  4064. this.projection.x = this.width/2;
  4065. this.projection.y = -this.height/2;
  4066. this.offset = new PIXI.Point(0, 0);
  4067. this.resize(this.width, this.height);
  4068. this.contextLost = false;
  4069. // time to create the render managers! each one focuses on managine a state in webGL
  4070. this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs
  4071. this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites
  4072. this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer
  4073. this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters
  4074. this.renderSession = {};
  4075. this.renderSession.gl = this.gl;
  4076. this.renderSession.drawCount = 0;
  4077. this.renderSession.shaderManager = this.shaderManager;
  4078. this.renderSession.maskManager = this.maskManager;
  4079. this.renderSession.filterManager = this.filterManager;
  4080. this.renderSession.spriteBatch = this.spriteBatch;
  4081. this.renderSession.renderer = this;
  4082. gl.useProgram(this.shaderManager.defaultShader.program);
  4083. gl.disable(gl.DEPTH_TEST);
  4084. gl.disable(gl.CULL_FACE);
  4085. gl.enable(gl.BLEND);
  4086. gl.colorMask(true, true, true, this.transparent);
  4087. };
  4088. // constructor
  4089. PIXI.WebGLRenderer.prototype.constructor = PIXI.WebGLRenderer;
  4090. /**
  4091. * Renders the stage to its webGL view
  4092. *
  4093. * @method render
  4094. * @param stage {Stage} the Stage element to be rendered
  4095. */
  4096. PIXI.WebGLRenderer.prototype.render = function(stage)
  4097. {
  4098. if(this.contextLost)return;
  4099. // if rendering a new stage clear the batches..
  4100. if(this.__stage !== stage)
  4101. {
  4102. if(stage.interactive)stage.interactionManager.removeEvents();
  4103. // TODO make this work
  4104. // dont think this is needed any more?
  4105. this.__stage = stage;
  4106. }
  4107. // update any textures this includes uvs and uploading them to the gpu
  4108. PIXI.WebGLRenderer.updateTextures();
  4109. // update the scene graph
  4110. stage.updateTransform();
  4111. // interaction
  4112. if(stage._interactive)
  4113. {
  4114. //need to add some events!
  4115. if(!stage._interactiveEventsAdded)
  4116. {
  4117. stage._interactiveEventsAdded = true;
  4118. stage.interactionManager.setTarget(this);
  4119. }
  4120. }
  4121. var gl = this.gl;
  4122. // -- Does this need to be set every frame? -- //
  4123. //gl.colorMask(true, true, true, this.transparent);
  4124. gl.viewport(0, 0, this.width, this.height);
  4125. // make sure we are bound to the main frame buffer
  4126. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  4127. if(this.transparent)
  4128. {
  4129. gl.clearColor(0, 0, 0, 0);
  4130. }
  4131. else
  4132. {
  4133. gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1);
  4134. }
  4135. gl.clear(gl.COLOR_BUFFER_BIT);
  4136. this.renderDisplayObject( stage, this.projection );
  4137. // interaction
  4138. if(stage.interactive)
  4139. {
  4140. //need to add some events!
  4141. if(!stage._interactiveEventsAdded)
  4142. {
  4143. stage._interactiveEventsAdded = true;
  4144. stage.interactionManager.setTarget(this);
  4145. }
  4146. }
  4147. else
  4148. {
  4149. if(stage._interactiveEventsAdded)
  4150. {
  4151. stage._interactiveEventsAdded = false;
  4152. stage.interactionManager.setTarget(this);
  4153. }
  4154. }
  4155. /*
  4156. //can simulate context loss in Chrome like so:
  4157. this.view.onmousedown = function(ev) {
  4158. console.dir(this.gl.getSupportedExtensions());
  4159. var ext = (
  4160. gl.getExtension("WEBGL_scompressed_texture_s3tc")
  4161. // gl.getExtension("WEBGL_compressed_texture_s3tc") ||
  4162. // gl.getExtension("MOZ_WEBGL_compressed_texture_s3tc") ||
  4163. // gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc")
  4164. );
  4165. console.dir(ext);
  4166. var loseCtx = this.gl.getExtension("WEBGL_lose_context");
  4167. console.log("killing context");
  4168. loseCtx.loseContext();
  4169. setTimeout(function() {
  4170. console.log("restoring context...");
  4171. loseCtx.restoreContext();
  4172. }.bind(this), 1000);
  4173. }.bind(this);
  4174. */
  4175. };
  4176. /**
  4177. * Renders a display Object
  4178. *
  4179. * @method renderDIsplayObject
  4180. * @param displayObject {DisplayObject} The DisplayObject to render
  4181. * @param projection {Point} The projection
  4182. * @param buffer {Array} a standard WebGL buffer
  4183. */
  4184. PIXI.WebGLRenderer.prototype.renderDisplayObject = function(displayObject, projection, buffer)
  4185. {
  4186. // reset the render session data..
  4187. this.renderSession.drawCount = 0;
  4188. this.renderSession.currentBlendMode = 9999;
  4189. this.renderSession.projection = projection;
  4190. this.renderSession.offset = this.offset;
  4191. // start the sprite batch
  4192. this.spriteBatch.begin(this.renderSession);
  4193. // start the filter manager
  4194. this.filterManager.begin(this.renderSession, buffer);
  4195. // render the scene!
  4196. displayObject._renderWebGL(this.renderSession);
  4197. // finish the sprite batch
  4198. this.spriteBatch.end();
  4199. };
  4200. /**
  4201. * Updates the textures loaded into this webgl renderer
  4202. *
  4203. * @static
  4204. * @method updateTextures
  4205. * @private
  4206. */
  4207. PIXI.WebGLRenderer.updateTextures = function()
  4208. {
  4209. var i = 0;
  4210. //TODO break this out into a texture manager...
  4211. //for (i = 0; i < PIXI.texturesToUpdate.length; i++)
  4212. // PIXI.WebGLRenderer.updateTexture(PIXI.texturesToUpdate[i]);
  4213. for (i=0; i < PIXI.Texture.frameUpdates.length; i++)
  4214. PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]);
  4215. for (i = 0; i < PIXI.texturesToDestroy.length; i++)
  4216. PIXI.WebGLRenderer.destroyTexture(PIXI.texturesToDestroy[i]);
  4217. PIXI.texturesToUpdate.length = 0;
  4218. PIXI.texturesToDestroy.length = 0;
  4219. PIXI.Texture.frameUpdates.length = 0;
  4220. };
  4221. /**
  4222. * Destroys a loaded webgl texture
  4223. *
  4224. * @method destroyTexture
  4225. * @param texture {Texture} The texture to update
  4226. * @private
  4227. */
  4228. PIXI.WebGLRenderer.destroyTexture = function(texture)
  4229. {
  4230. //TODO break this out into a texture manager...
  4231. for (var i = texture._glTextures.length - 1; i >= 0; i--)
  4232. {
  4233. var glTexture = texture._glTextures[i];
  4234. var gl = PIXI.glContexts[i];
  4235. if(gl && glTexture)
  4236. {
  4237. gl.deleteTexture(glTexture);
  4238. }
  4239. }
  4240. texture._glTextures.length = 0;
  4241. };
  4242. /**
  4243. *
  4244. * @method updateTextureFrame
  4245. * @param texture {Texture} The texture to update the frame from
  4246. * @private
  4247. */
  4248. PIXI.WebGLRenderer.updateTextureFrame = function(texture)
  4249. {
  4250. texture.updateFrame = false;
  4251. // now set the uvs. Figured that the uv data sits with a texture rather than a sprite.
  4252. // so uv data is stored on the texture itself
  4253. texture._updateWebGLuvs();
  4254. };
  4255. /**
  4256. * resizes the webGL view to the specified width and height
  4257. *
  4258. * @method resize
  4259. * @param width {Number} the new width of the webGL view
  4260. * @param height {Number} the new height of the webGL view
  4261. */
  4262. PIXI.WebGLRenderer.prototype.resize = function(width, height)
  4263. {
  4264. this.width = width;
  4265. this.height = height;
  4266. this.view.width = width;
  4267. this.view.height = height;
  4268. this.gl.viewport(0, 0, this.width, this.height);
  4269. this.projection.x = this.width/2;
  4270. this.projection.y = -this.height/2;
  4271. };
  4272. /**
  4273. * Creates a WebGL texture
  4274. *
  4275. * @method createWebGLTexture
  4276. * @param texture {Texture} the texture to render
  4277. * @param gl {webglContext} the WebGL context
  4278. * @static
  4279. */
  4280. PIXI.createWebGLTexture = function(texture, gl)
  4281. {
  4282. if(texture.hasLoaded)
  4283. {
  4284. texture._glTextures[gl.id] = gl.createTexture();
  4285. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  4286. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
  4287. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);
  4288. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
  4289. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
  4290. // reguler...
  4291. if(!texture._powerOf2)
  4292. {
  4293. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  4294. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  4295. }
  4296. else
  4297. {
  4298. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  4299. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  4300. }
  4301. gl.bindTexture(gl.TEXTURE_2D, null);
  4302. }
  4303. return texture._glTextures[gl.id];
  4304. };
  4305. /**
  4306. * Updates a WebGL texture
  4307. *
  4308. * @method updateWebGLTexture
  4309. * @param texture {Texture} the texture to update
  4310. * @param gl {webglContext} the WebGL context
  4311. * @private
  4312. */
  4313. PIXI.updateWebGLTexture = function(texture, gl)
  4314. {
  4315. if( texture._glTextures[gl.id] )
  4316. {
  4317. gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id]);
  4318. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
  4319. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.source);
  4320. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
  4321. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texture.scaleMode === PIXI.scaleModes.LINEAR ? gl.LINEAR : gl.NEAREST);
  4322. // reguler...
  4323. if(!texture._powerOf2)
  4324. {
  4325. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  4326. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  4327. }
  4328. else
  4329. {
  4330. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  4331. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  4332. }
  4333. gl.bindTexture(gl.TEXTURE_2D, null);
  4334. }
  4335. };
  4336. /**
  4337. * Handles a lost webgl context
  4338. *
  4339. * @method handleContextLost
  4340. * @param event {Event}
  4341. * @private
  4342. */
  4343. PIXI.WebGLRenderer.prototype.handleContextLost = function(event)
  4344. {
  4345. event.preventDefault();
  4346. this.contextLost = true;
  4347. };
  4348. /**
  4349. * Handles a restored webgl context
  4350. *
  4351. * @method handleContextRestored
  4352. * @param event {Event}
  4353. * @private
  4354. */
  4355. PIXI.WebGLRenderer.prototype.handleContextRestored = function()
  4356. {
  4357. //try 'experimental-webgl'
  4358. try {
  4359. this.gl = this.view.getContext('experimental-webgl', this.options);
  4360. } catch (e) {
  4361. //try 'webgl'
  4362. try {
  4363. this.gl = this.view.getContext('webgl', this.options);
  4364. } catch (e2) {
  4365. // fail, not able to get a context
  4366. throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this);
  4367. }
  4368. }
  4369. var gl = this.gl;
  4370. gl.id = PIXI.WebGLRenderer.glContextId ++;
  4371. // need to set the context...
  4372. this.shaderManager.setContext(gl);
  4373. this.spriteBatch.setContext(gl);
  4374. this.maskManager.setContext(gl);
  4375. this.filterManager.setContext(gl);
  4376. this.renderSession.gl = this.gl;
  4377. gl.disable(gl.DEPTH_TEST);
  4378. gl.disable(gl.CULL_FACE);
  4379. gl.enable(gl.BLEND);
  4380. gl.colorMask(true, true, true, this.transparent);
  4381. this.gl.viewport(0, 0, this.width, this.height);
  4382. for(var key in PIXI.TextureCache)
  4383. {
  4384. var texture = PIXI.TextureCache[key].baseTexture;
  4385. texture._glTextures = [];
  4386. }
  4387. /**
  4388. * Whether the context was lost
  4389. * @property contextLost
  4390. * @type Boolean
  4391. */
  4392. this.contextLost = false;
  4393. };
  4394. /**
  4395. * Removes everything from the renderer (event listeners, spritebatch, etc...)
  4396. *
  4397. * @method destroy
  4398. */
  4399. PIXI.WebGLRenderer.prototype.destroy = function()
  4400. {
  4401. // deal with losing context..
  4402. // remove listeners
  4403. this.view.removeEventListener('webglcontextlost', this.contextLost);
  4404. this.view.removeEventListener('webglcontextrestored', this.contextRestoredLost);
  4405. PIXI.glContexts[this.glContextId] = null;
  4406. this.projection = null;
  4407. this.offset = null;
  4408. // time to create the render managers! each one focuses on managine a state in webGL
  4409. this.shaderManager.destroy();
  4410. this.spriteBatch.destroy();
  4411. this.maskManager.destroy();
  4412. this.filterManager.destroy();
  4413. this.shaderManager = null;
  4414. this.spriteBatch = null;
  4415. this.maskManager = null;
  4416. this.filterManager = null;
  4417. this.gl = null;
  4418. //
  4419. this.renderSession = null;
  4420. };
  4421. PIXI.WebGLRenderer.glContextId = 0;
  4422. /**
  4423. * @author Mat Groves http://matgroves.com/ @Doormat23
  4424. */
  4425. /**
  4426. * @class WebGLMaskManager
  4427. * @constructor
  4428. * @param gl {WebGLContext} the current WebGL drawing context
  4429. * @private
  4430. */
  4431. PIXI.WebGLMaskManager = function(gl)
  4432. {
  4433. this.maskStack = [];
  4434. this.maskPosition = 0;
  4435. this.setContext(gl);
  4436. };
  4437. /**
  4438. * Sets the drawing context to the one given in parameter
  4439. * @method setContext
  4440. * @param gl {WebGLContext} the current WebGL drawing context
  4441. */
  4442. PIXI.WebGLMaskManager.prototype.setContext = function(gl)
  4443. {
  4444. this.gl = gl;
  4445. };
  4446. /**
  4447. * Applies the Mask and adds it to the current filter stack
  4448. * @method pushMask
  4449. * @param maskData {Array}
  4450. * @param renderSession {RenderSession}
  4451. */
  4452. PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession)
  4453. {
  4454. var gl = this.gl;
  4455. if(this.maskStack.length === 0)
  4456. {
  4457. gl.enable(gl.STENCIL_TEST);
  4458. gl.stencilFunc(gl.ALWAYS,1,1);
  4459. }
  4460. // maskData.visible = false;
  4461. this.maskStack.push(maskData);
  4462. gl.colorMask(false, false, false, true);
  4463. gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
  4464. PIXI.WebGLGraphics.renderGraphics(maskData, renderSession);
  4465. gl.colorMask(true, true, true, true);
  4466. gl.stencilFunc(gl.NOTEQUAL,0, this.maskStack.length);
  4467. gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
  4468. };
  4469. /**
  4470. * Removes the last filter from the filter stack and doesn't return it
  4471. * @method popMask
  4472. *
  4473. * @param renderSession {RenderSession} an object containing all the useful parameters
  4474. */
  4475. PIXI.WebGLMaskManager.prototype.popMask = function(renderSession)
  4476. {
  4477. var gl = this.gl;
  4478. var maskData = this.maskStack.pop();
  4479. if(maskData)
  4480. {
  4481. gl.colorMask(false, false, false, false);
  4482. //gl.stencilFunc(gl.ALWAYS,1,1);
  4483. gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
  4484. PIXI.WebGLGraphics.renderGraphics(maskData, renderSession);
  4485. gl.colorMask(true, true, true, true);
  4486. gl.stencilFunc(gl.NOTEQUAL,0,this.maskStack.length);
  4487. gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
  4488. }
  4489. if(this.maskStack.length === 0)gl.disable(gl.STENCIL_TEST);
  4490. };
  4491. /**
  4492. * Destroys the mask stack
  4493. * @method destroy
  4494. */
  4495. PIXI.WebGLMaskManager.prototype.destroy = function()
  4496. {
  4497. this.maskStack = null;
  4498. this.gl = null;
  4499. };
  4500. /**
  4501. * @author Mat Groves http://matgroves.com/ @Doormat23
  4502. */
  4503. /**
  4504. * @class WebGLShaderManager
  4505. * @constructor
  4506. * @param gl {WebGLContext} the current WebGL drawing context
  4507. * @private
  4508. */
  4509. PIXI.WebGLShaderManager = function(gl)
  4510. {
  4511. this.maxAttibs = 10;
  4512. this.attribState = [];
  4513. this.tempAttribState = [];
  4514. for (var i = 0; i < this.maxAttibs; i++) {
  4515. this.attribState[i] = false;
  4516. }
  4517. this.setContext(gl);
  4518. // the final one is used for the rendering strips
  4519. //this.stripShader = new PIXI.StripShader(gl);
  4520. };
  4521. /**
  4522. * Initialises the context and the properties
  4523. * @method setContext
  4524. * @param gl {WebGLContext} the current WebGL drawing context
  4525. * @param transparent {Boolean} Whether or not the drawing context should be transparent
  4526. */
  4527. PIXI.WebGLShaderManager.prototype.setContext = function(gl)
  4528. {
  4529. this.gl = gl;
  4530. // the next one is used for rendering primatives
  4531. this.primitiveShader = new PIXI.PrimitiveShader(gl);
  4532. // this shader is used for the default sprite rendering
  4533. this.defaultShader = new PIXI.PixiShader(gl);
  4534. // this shader is used for the fast sprite rendering
  4535. this.fastShader = new PIXI.PixiFastShader(gl);
  4536. this.activateShader(this.defaultShader);
  4537. };
  4538. /**
  4539. * Takes the attributes given in parameters
  4540. * @method setAttribs
  4541. * @param attribs {Array} attribs
  4542. */
  4543. PIXI.WebGLShaderManager.prototype.setAttribs = function(attribs)
  4544. {
  4545. // reset temp state
  4546. var i;
  4547. for (i = 0; i < this.tempAttribState.length; i++)
  4548. {
  4549. this.tempAttribState[i] = false;
  4550. }
  4551. // set the new attribs
  4552. for (i = 0; i < attribs.length; i++)
  4553. {
  4554. var attribId = attribs[i];
  4555. this.tempAttribState[attribId] = true;
  4556. }
  4557. var gl = this.gl;
  4558. for (i = 0; i < this.attribState.length; i++)
  4559. {
  4560. if(this.attribState[i] !== this.tempAttribState[i])
  4561. {
  4562. this.attribState[i] = this.tempAttribState[i];
  4563. if(this.tempAttribState[i])
  4564. {
  4565. gl.enableVertexAttribArray(i);
  4566. }
  4567. else
  4568. {
  4569. gl.disableVertexAttribArray(i);
  4570. }
  4571. }
  4572. }
  4573. };
  4574. /**
  4575. * Sets-up the given shader
  4576. *
  4577. * @method activateShader
  4578. * @param shader {Object} the shader that is going to be activated
  4579. */
  4580. PIXI.WebGLShaderManager.prototype.activateShader = function(shader)
  4581. {
  4582. //if(this.currentShader == shader)return;
  4583. this.currentShader = shader;
  4584. this.gl.useProgram(shader.program);
  4585. this.setAttribs(shader.attributes);
  4586. };
  4587. /**
  4588. * Triggers the primitive shader
  4589. * @method activatePrimitiveShader
  4590. */
  4591. PIXI.WebGLShaderManager.prototype.activatePrimitiveShader = function()
  4592. {
  4593. var gl = this.gl;
  4594. gl.useProgram(this.primitiveShader.program);
  4595. this.setAttribs(this.primitiveShader.attributes);
  4596. };
  4597. /**
  4598. * Disable the primitive shader
  4599. * @method deactivatePrimitiveShader
  4600. */
  4601. PIXI.WebGLShaderManager.prototype.deactivatePrimitiveShader = function()
  4602. {
  4603. var gl = this.gl;
  4604. gl.useProgram(this.defaultShader.program);
  4605. this.setAttribs(this.defaultShader.attributes);
  4606. };
  4607. /**
  4608. * Destroys
  4609. * @method destroy
  4610. */
  4611. PIXI.WebGLShaderManager.prototype.destroy = function()
  4612. {
  4613. this.attribState = null;
  4614. this.tempAttribState = null;
  4615. this.primitiveShader.destroy();
  4616. this.defaultShader.destroy();
  4617. this.fastShader.destroy();
  4618. this.gl = null;
  4619. };
  4620. /**
  4621. * @author Mat Groves
  4622. *
  4623. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  4624. * for creating the original pixi version!
  4625. *
  4626. * Heavily inspired by LibGDX's WebGLSpriteBatch:
  4627. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java
  4628. */
  4629. /**
  4630. *
  4631. * @class WebGLSpriteBatch
  4632. * @private
  4633. * @constructor
  4634. * @param gl {WebGLContext} the current WebGL drawing context
  4635. *
  4636. */
  4637. PIXI.WebGLSpriteBatch = function(gl)
  4638. {
  4639. /**
  4640. *
  4641. *
  4642. * @property vertSize
  4643. * @type Number
  4644. */
  4645. this.vertSize = 6;
  4646. /**
  4647. * The number of images in the SpriteBatch before it flushes
  4648. * @property size
  4649. * @type Number
  4650. */
  4651. this.size = 2000;//Math.pow(2, 16) / this.vertSize;
  4652. //the total number of floats in our batch
  4653. var numVerts = this.size * 4 * this.vertSize;
  4654. //the total number of indices in our batch
  4655. var numIndices = this.size * 6;
  4656. //vertex data
  4657. /**
  4658. * Holds the vertices
  4659. *
  4660. * @property vertices
  4661. * @type Float32Array
  4662. */
  4663. this.vertices = new Float32Array(numVerts);
  4664. //index data
  4665. /**
  4666. * Holds the indices
  4667. *
  4668. * @property indices
  4669. * @type Uint16Array
  4670. */
  4671. this.indices = new Uint16Array(numIndices);
  4672. this.lastIndexCount = 0;
  4673. for (var i=0, j=0; i < numIndices; i += 6, j += 4)
  4674. {
  4675. this.indices[i + 0] = j + 0;
  4676. this.indices[i + 1] = j + 1;
  4677. this.indices[i + 2] = j + 2;
  4678. this.indices[i + 3] = j + 0;
  4679. this.indices[i + 4] = j + 2;
  4680. this.indices[i + 5] = j + 3;
  4681. }
  4682. this.drawing = false;
  4683. this.currentBatchSize = 0;
  4684. this.currentBaseTexture = null;
  4685. this.setContext(gl);
  4686. };
  4687. /**
  4688. *
  4689. * @method setContext
  4690. *
  4691. * @param gl {WebGLContext} the current WebGL drawing context
  4692. */
  4693. PIXI.WebGLSpriteBatch.prototype.setContext = function(gl)
  4694. {
  4695. this.gl = gl;
  4696. // create a couple of buffers
  4697. this.vertexBuffer = gl.createBuffer();
  4698. this.indexBuffer = gl.createBuffer();
  4699. // 65535 is max index, so 65535 / 6 = 10922.
  4700. //upload the index data
  4701. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  4702. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
  4703. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  4704. gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
  4705. this.currentBlendMode = 99999;
  4706. };
  4707. /**
  4708. *
  4709. * @method begin
  4710. *
  4711. * @param renderSession {RenderSession} the RenderSession
  4712. */
  4713. PIXI.WebGLSpriteBatch.prototype.begin = function(renderSession)
  4714. {
  4715. this.renderSession = renderSession;
  4716. this.shader = this.renderSession.shaderManager.defaultShader;
  4717. this.start();
  4718. };
  4719. /**
  4720. *
  4721. * @method end
  4722. *
  4723. */
  4724. PIXI.WebGLSpriteBatch.prototype.end = function()
  4725. {
  4726. this.flush();
  4727. };
  4728. /**
  4729. *
  4730. * @method render
  4731. *
  4732. * @param sprite {Sprite} the sprite to render when using this spritebatch
  4733. */
  4734. PIXI.WebGLSpriteBatch.prototype.render = function(sprite)
  4735. {
  4736. var texture = sprite.texture;
  4737. // check texture..
  4738. if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size)
  4739. {
  4740. this.flush();
  4741. this.currentBaseTexture = texture.baseTexture;
  4742. }
  4743. // check blend mode
  4744. if(sprite.blendMode !== this.currentBlendMode)
  4745. {
  4746. this.setBlendMode(sprite.blendMode);
  4747. }
  4748. // get the uvs for the texture
  4749. var uvs = sprite._uvs || sprite.texture._uvs;
  4750. // if the uvs have not updated then no point rendering just yet!
  4751. if(!uvs)return;
  4752. // get the sprites current alpha
  4753. var alpha = sprite.worldAlpha;
  4754. var tint = sprite.tint;
  4755. var verticies = this.vertices;
  4756. // TODO trim??
  4757. var aX = sprite.anchor.x;
  4758. var aY = sprite.anchor.y;
  4759. var w0, w1, h0, h1;
  4760. if (sprite.texture.trim)
  4761. {
  4762. // if the sprite is trimmed then we need to add the extra space before transforming the sprite coords..
  4763. var trim = sprite.texture.trim;
  4764. w1 = trim.x - aX * trim.width;
  4765. w0 = w1 + texture.frame.width;
  4766. h1 = trim.y - aY * trim.height;
  4767. h0 = h1 + texture.frame.height;
  4768. }
  4769. else
  4770. {
  4771. w0 = (texture.frame.width ) * (1-aX);
  4772. w1 = (texture.frame.width ) * -aX;
  4773. h0 = texture.frame.height * (1-aY);
  4774. h1 = texture.frame.height * -aY;
  4775. }
  4776. var index = this.currentBatchSize * 4 * this.vertSize;
  4777. var worldTransform = sprite.worldTransform;//.toArray();
  4778. var a = worldTransform.a;//[0];
  4779. var b = worldTransform.c;//[3];
  4780. var c = worldTransform.b;//[1];
  4781. var d = worldTransform.d;//[4];
  4782. var tx = worldTransform.tx;//[2];
  4783. var ty = worldTransform.ty;///[5];
  4784. // xy
  4785. verticies[index++] = a * w1 + c * h1 + tx;
  4786. verticies[index++] = d * h1 + b * w1 + ty;
  4787. // uv
  4788. verticies[index++] = uvs.x0;
  4789. verticies[index++] = uvs.y0;
  4790. // color
  4791. verticies[index++] = alpha;
  4792. verticies[index++] = tint;
  4793. // xy
  4794. verticies[index++] = a * w0 + c * h1 + tx;
  4795. verticies[index++] = d * h1 + b * w0 + ty;
  4796. // uv
  4797. verticies[index++] = uvs.x1;
  4798. verticies[index++] = uvs.y1;
  4799. // color
  4800. verticies[index++] = alpha;
  4801. verticies[index++] = tint;
  4802. // xy
  4803. verticies[index++] = a * w0 + c * h0 + tx;
  4804. verticies[index++] = d * h0 + b * w0 + ty;
  4805. // uv
  4806. verticies[index++] = uvs.x2;
  4807. verticies[index++] = uvs.y2;
  4808. // color
  4809. verticies[index++] = alpha;
  4810. verticies[index++] = tint;
  4811. // xy
  4812. verticies[index++] = a * w1 + c * h0 + tx;
  4813. verticies[index++] = d * h0 + b * w1 + ty;
  4814. // uv
  4815. verticies[index++] = uvs.x3;
  4816. verticies[index++] = uvs.y3;
  4817. // color
  4818. verticies[index++] = alpha;
  4819. verticies[index++] = tint;
  4820. // increment the batchsize
  4821. this.currentBatchSize++;
  4822. };
  4823. /**
  4824. * Renders a tilingSprite using the spriteBatch
  4825. * @method renderTilingSprite
  4826. *
  4827. * @param sprite {TilingSprite} the tilingSprite to render
  4828. */
  4829. PIXI.WebGLSpriteBatch.prototype.renderTilingSprite = function(tilingSprite)
  4830. {
  4831. var texture = tilingSprite.tilingTexture;
  4832. if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size)
  4833. {
  4834. this.flush();
  4835. this.currentBaseTexture = texture.baseTexture;
  4836. }
  4837. // check blend mode
  4838. if(tilingSprite.blendMode !== this.currentBlendMode)
  4839. {
  4840. this.setBlendMode(tilingSprite.blendMode);
  4841. }
  4842. // set the textures uvs temporarily
  4843. // TODO create a separate texture so that we can tile part of a texture
  4844. if(!tilingSprite._uvs)tilingSprite._uvs = new PIXI.TextureUvs();
  4845. var uvs = tilingSprite._uvs;
  4846. tilingSprite.tilePosition.x %= texture.baseTexture.width * tilingSprite.tileScaleOffset.x;
  4847. tilingSprite.tilePosition.y %= texture.baseTexture.height * tilingSprite.tileScaleOffset.y;
  4848. var offsetX = tilingSprite.tilePosition.x/(texture.baseTexture.width*tilingSprite.tileScaleOffset.x);
  4849. var offsetY = tilingSprite.tilePosition.y/(texture.baseTexture.height*tilingSprite.tileScaleOffset.y);
  4850. var scaleX = (tilingSprite.width / texture.baseTexture.width) / (tilingSprite.tileScale.x * tilingSprite.tileScaleOffset.x);
  4851. var scaleY = (tilingSprite.height / texture.baseTexture.height) / (tilingSprite.tileScale.y * tilingSprite.tileScaleOffset.y);
  4852. uvs.x0 = 0 - offsetX;
  4853. uvs.y0 = 0 - offsetY;
  4854. uvs.x1 = (1 * scaleX) - offsetX;
  4855. uvs.y1 = 0 - offsetY;
  4856. uvs.x2 = (1 * scaleX) - offsetX;
  4857. uvs.y2 = (1 * scaleY) - offsetY;
  4858. uvs.x3 = 0 - offsetX;
  4859. uvs.y3 = (1 *scaleY) - offsetY;
  4860. // get the tilingSprites current alpha
  4861. var alpha = tilingSprite.worldAlpha;
  4862. var tint = tilingSprite.tint;
  4863. var verticies = this.vertices;
  4864. var width = tilingSprite.width;
  4865. var height = tilingSprite.height;
  4866. // TODO trim??
  4867. var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x
  4868. var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y
  4869. var w0 = width * (1-aX);
  4870. var w1 = width * -aX;
  4871. var h0 = height * (1-aY);
  4872. var h1 = height * -aY;
  4873. var index = this.currentBatchSize * 4 * this.vertSize;
  4874. var worldTransform = tilingSprite.worldTransform;
  4875. var a = worldTransform.a;//[0];
  4876. var b = worldTransform.c;//[3];
  4877. var c = worldTransform.b;//[1];
  4878. var d = worldTransform.d;//[4];
  4879. var tx = worldTransform.tx;//[2];
  4880. var ty = worldTransform.ty;///[5];
  4881. // xy
  4882. verticies[index++] = a * w1 + c * h1 + tx;
  4883. verticies[index++] = d * h1 + b * w1 + ty;
  4884. // uv
  4885. verticies[index++] = uvs.x0;
  4886. verticies[index++] = uvs.y0;
  4887. // color
  4888. verticies[index++] = alpha;
  4889. verticies[index++] = tint;
  4890. // xy
  4891. verticies[index++] = a * w0 + c * h1 + tx;
  4892. verticies[index++] = d * h1 + b * w0 + ty;
  4893. // uv
  4894. verticies[index++] = uvs.x1;
  4895. verticies[index++] = uvs.y1;
  4896. // color
  4897. verticies[index++] = alpha;
  4898. verticies[index++] = tint;
  4899. // xy
  4900. verticies[index++] = a * w0 + c * h0 + tx;
  4901. verticies[index++] = d * h0 + b * w0 + ty;
  4902. // uv
  4903. verticies[index++] = uvs.x2;
  4904. verticies[index++] = uvs.y2;
  4905. // color
  4906. verticies[index++] = alpha;
  4907. verticies[index++] = tint;
  4908. // xy
  4909. verticies[index++] = a * w1 + c * h0 + tx;
  4910. verticies[index++] = d * h0 + b * w1 + ty;
  4911. // uv
  4912. verticies[index++] = uvs.x3;
  4913. verticies[index++] = uvs.y3;
  4914. // color
  4915. verticies[index++] = alpha;
  4916. verticies[index++] = tint;
  4917. // increment the batchs
  4918. this.currentBatchSize++;
  4919. };
  4920. /**
  4921. * Renders the content and empties the current batch
  4922. *
  4923. * @method flush
  4924. *
  4925. */
  4926. PIXI.WebGLSpriteBatch.prototype.flush = function()
  4927. {
  4928. // If the batch is length 0 then return as there is nothing to draw
  4929. if (this.currentBatchSize===0)return;
  4930. var gl = this.gl;
  4931. // bind the current texture
  4932. gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl));
  4933. // upload the verts to the buffer
  4934. if(this.currentBatchSize > ( this.size * 0.5 ) )
  4935. {
  4936. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
  4937. }
  4938. else
  4939. {
  4940. var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize);
  4941. gl.bufferSubData(gl.ARRAY_BUFFER, 0, view);
  4942. }
  4943. // var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize);
  4944. //gl.bufferSubData(gl.ARRAY_BUFFER, 0, view);
  4945. // now draw those suckas!
  4946. gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0);
  4947. // then reset the batch!
  4948. this.currentBatchSize = 0;
  4949. // increment the draw count
  4950. this.renderSession.drawCount++;
  4951. };
  4952. /**
  4953. *
  4954. * @method stop
  4955. *
  4956. */
  4957. PIXI.WebGLSpriteBatch.prototype.stop = function()
  4958. {
  4959. this.flush();
  4960. };
  4961. /**
  4962. *
  4963. * @method start
  4964. *
  4965. */
  4966. PIXI.WebGLSpriteBatch.prototype.start = function()
  4967. {
  4968. var gl = this.gl;
  4969. // bind the main texture
  4970. gl.activeTexture(gl.TEXTURE0);
  4971. // bind the buffers
  4972. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  4973. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  4974. // set the projection
  4975. var projection = this.renderSession.projection;
  4976. gl.uniform2f(this.shader.projectionVector, projection.x, projection.y);
  4977. // set the pointers
  4978. var stride = this.vertSize * 4;
  4979. gl.vertexAttribPointer(this.shader.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
  4980. gl.vertexAttribPointer(this.shader.aTextureCoord, 2, gl.FLOAT, false, stride, 2 * 4);
  4981. gl.vertexAttribPointer(this.shader.colorAttribute, 2, gl.FLOAT, false, stride, 4 * 4);
  4982. // set the blend mode..
  4983. if(this.currentBlendMode !== PIXI.blendModes.NORMAL)
  4984. {
  4985. this.setBlendMode(PIXI.blendModes.NORMAL);
  4986. }
  4987. };
  4988. /**
  4989. * Sets-up the given blendMode from WebGL's point of view
  4990. * @method setBlendMode
  4991. *
  4992. * @param blendMode {Number} the blendMode, should be a Pixi const, such as PIXI.BlendModes.ADD
  4993. */
  4994. PIXI.WebGLSpriteBatch.prototype.setBlendMode = function(blendMode)
  4995. {
  4996. this.flush();
  4997. this.currentBlendMode = blendMode;
  4998. var blendModeWebGL = PIXI.blendModesWebGL[this.currentBlendMode];
  4999. this.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
  5000. };
  5001. /**
  5002. * Destroys the SpriteBatch
  5003. * @method destroy
  5004. */
  5005. PIXI.WebGLSpriteBatch.prototype.destroy = function()
  5006. {
  5007. this.vertices = null;
  5008. this.indices = null;
  5009. this.gl.deleteBuffer( this.vertexBuffer );
  5010. this.gl.deleteBuffer( this.indexBuffer );
  5011. this.currentBaseTexture = null;
  5012. this.gl = null;
  5013. };
  5014. /**
  5015. * @author Mat Groves
  5016. *
  5017. * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
  5018. * for creating the original pixi version!
  5019. *
  5020. * Heavily inspired by LibGDX's WebGLSpriteBatch:
  5021. * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/WebGLSpriteBatch.java
  5022. */
  5023. PIXI.WebGLFastSpriteBatch = function(gl)
  5024. {
  5025. this.vertSize = 10;
  5026. this.maxSize = 6000;//Math.pow(2, 16) / this.vertSize;
  5027. this.size = this.maxSize;
  5028. //the total number of floats in our batch
  5029. var numVerts = this.size * 4 * this.vertSize;
  5030. //the total number of indices in our batch
  5031. var numIndices = this.maxSize * 6;
  5032. //vertex data
  5033. this.vertices = new Float32Array(numVerts);
  5034. //index data
  5035. this.indices = new Uint16Array(numIndices);
  5036. this.vertexBuffer = null;
  5037. this.indexBuffer = null;
  5038. this.lastIndexCount = 0;
  5039. for (var i=0, j=0; i < numIndices; i += 6, j += 4)
  5040. {
  5041. this.indices[i + 0] = j + 0;
  5042. this.indices[i + 1] = j + 1;
  5043. this.indices[i + 2] = j + 2;
  5044. this.indices[i + 3] = j + 0;
  5045. this.indices[i + 4] = j + 2;
  5046. this.indices[i + 5] = j + 3;
  5047. }
  5048. this.drawing = false;
  5049. this.currentBatchSize = 0;
  5050. this.currentBaseTexture = null;
  5051. this.currentBlendMode = 0;
  5052. this.renderSession = null;
  5053. this.shader = null;
  5054. this.matrix = null;
  5055. this.setContext(gl);
  5056. };
  5057. PIXI.WebGLFastSpriteBatch.prototype.setContext = function(gl)
  5058. {
  5059. this.gl = gl;
  5060. // create a couple of buffers
  5061. this.vertexBuffer = gl.createBuffer();
  5062. this.indexBuffer = gl.createBuffer();
  5063. // 65535 is max index, so 65535 / 6 = 10922.
  5064. //upload the index data
  5065. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  5066. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
  5067. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  5068. gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
  5069. this.currentBlendMode = 99999;
  5070. };
  5071. PIXI.WebGLFastSpriteBatch.prototype.begin = function(spriteBatch, renderSession)
  5072. {
  5073. this.renderSession = renderSession;
  5074. this.shader = this.renderSession.shaderManager.fastShader;
  5075. this.matrix = spriteBatch.worldTransform.toArray(true);
  5076. this.start();
  5077. };
  5078. PIXI.WebGLFastSpriteBatch.prototype.end = function()
  5079. {
  5080. this.flush();
  5081. };
  5082. PIXI.WebGLFastSpriteBatch.prototype.render = function(spriteBatch)
  5083. {
  5084. var children = spriteBatch.children;
  5085. var sprite = children[0];
  5086. // if the uvs have not updated then no point rendering just yet!
  5087. // check texture.
  5088. if(!sprite.texture._uvs)return;
  5089. this.currentBaseTexture = sprite.texture.baseTexture;
  5090. // check blend mode
  5091. if(sprite.blendMode !== this.currentBlendMode)
  5092. {
  5093. this.setBlendMode(sprite.blendMode);
  5094. }
  5095. for(var i=0,j= children.length; i<j; i++)
  5096. {
  5097. this.renderSprite(children[i]);
  5098. }
  5099. this.flush();
  5100. };
  5101. PIXI.WebGLFastSpriteBatch.prototype.renderSprite = function(sprite)
  5102. {
  5103. //sprite = children[i];
  5104. if(!sprite.visible)return;
  5105. // TODO trim??
  5106. if(sprite.texture.baseTexture !== this.currentBaseTexture)
  5107. {
  5108. this.flush();
  5109. this.currentBaseTexture = sprite.texture.baseTexture;
  5110. if(!sprite.texture._uvs)return;
  5111. }
  5112. var uvs, verticies = this.vertices, width, height, w0, w1, h0, h1, index;
  5113. uvs = sprite.texture._uvs;
  5114. width = sprite.texture.frame.width;
  5115. height = sprite.texture.frame.height;
  5116. if (sprite.texture.trim)
  5117. {
  5118. // if the sprite is trimmed then we need to add the extra space before transforming the sprite coords..
  5119. var trim = sprite.texture.trim;
  5120. w1 = trim.x - sprite.anchor.x * trim.width;
  5121. w0 = w1 + sprite.texture.frame.width;
  5122. h1 = trim.y - sprite.anchor.y * trim.height;
  5123. h0 = h1 + sprite.texture.frame.height;
  5124. }
  5125. else
  5126. {
  5127. w0 = (sprite.texture.frame.width ) * (1-sprite.anchor.x);
  5128. w1 = (sprite.texture.frame.width ) * -sprite.anchor.x;
  5129. h0 = sprite.texture.frame.height * (1-sprite.anchor.y);
  5130. h1 = sprite.texture.frame.height * -sprite.anchor.y;
  5131. }
  5132. index = this.currentBatchSize * 4 * this.vertSize;
  5133. // xy
  5134. verticies[index++] = w1;
  5135. verticies[index++] = h1;
  5136. verticies[index++] = sprite.position.x;
  5137. verticies[index++] = sprite.position.y;
  5138. //scale
  5139. verticies[index++] = sprite.scale.x;
  5140. verticies[index++] = sprite.scale.y;
  5141. //rotation
  5142. verticies[index++] = sprite.rotation;
  5143. // uv
  5144. verticies[index++] = uvs.x0;
  5145. verticies[index++] = uvs.y1;
  5146. // color
  5147. verticies[index++] = sprite.alpha;
  5148. // xy
  5149. verticies[index++] = w0;
  5150. verticies[index++] = h1;
  5151. verticies[index++] = sprite.position.x;
  5152. verticies[index++] = sprite.position.y;
  5153. //scale
  5154. verticies[index++] = sprite.scale.x;
  5155. verticies[index++] = sprite.scale.y;
  5156. //rotation
  5157. verticies[index++] = sprite.rotation;
  5158. // uv
  5159. verticies[index++] = uvs.x1;
  5160. verticies[index++] = uvs.y1;
  5161. // color
  5162. verticies[index++] = sprite.alpha;
  5163. // xy
  5164. verticies[index++] = w0;
  5165. verticies[index++] = h0;
  5166. verticies[index++] = sprite.position.x;
  5167. verticies[index++] = sprite.position.y;
  5168. //scale
  5169. verticies[index++] = sprite.scale.x;
  5170. verticies[index++] = sprite.scale.y;
  5171. //rotation
  5172. verticies[index++] = sprite.rotation;
  5173. // uv
  5174. verticies[index++] = uvs.x2;
  5175. verticies[index++] = uvs.y2;
  5176. // color
  5177. verticies[index++] = sprite.alpha;
  5178. // xy
  5179. verticies[index++] = w1;
  5180. verticies[index++] = h0;
  5181. verticies[index++] = sprite.position.x;
  5182. verticies[index++] = sprite.position.y;
  5183. //scale
  5184. verticies[index++] = sprite.scale.x;
  5185. verticies[index++] = sprite.scale.y;
  5186. //rotation
  5187. verticies[index++] = sprite.rotation;
  5188. // uv
  5189. verticies[index++] = uvs.x3;
  5190. verticies[index++] = uvs.y3;
  5191. // color
  5192. verticies[index++] = sprite.alpha;
  5193. // increment the batchs
  5194. this.currentBatchSize++;
  5195. if(this.currentBatchSize >= this.size)
  5196. {
  5197. this.flush();
  5198. }
  5199. };
  5200. PIXI.WebGLFastSpriteBatch.prototype.flush = function()
  5201. {
  5202. // If the batch is length 0 then return as there is nothing to draw
  5203. if (this.currentBatchSize===0)return;
  5204. var gl = this.gl;
  5205. // bind the current texture
  5206. if(!this.currentBaseTexture._glTextures[gl.id])PIXI.createWebGLTexture(this.currentBaseTexture, gl);
  5207. gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id]);// || PIXI.createWebGLTexture(this.currentBaseTexture, gl));
  5208. // upload the verts to the buffer
  5209. if(this.currentBatchSize > ( this.size * 0.5 ) )
  5210. {
  5211. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
  5212. }
  5213. else
  5214. {
  5215. var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize);
  5216. gl.bufferSubData(gl.ARRAY_BUFFER, 0, view);
  5217. }
  5218. // now draw those suckas!
  5219. gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0);
  5220. // then reset the batch!
  5221. this.currentBatchSize = 0;
  5222. // increment the draw count
  5223. this.renderSession.drawCount++;
  5224. };
  5225. PIXI.WebGLFastSpriteBatch.prototype.stop = function()
  5226. {
  5227. this.flush();
  5228. };
  5229. PIXI.WebGLFastSpriteBatch.prototype.start = function()
  5230. {
  5231. var gl = this.gl;
  5232. // bind the main texture
  5233. gl.activeTexture(gl.TEXTURE0);
  5234. // bind the buffers
  5235. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  5236. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  5237. // set the projection
  5238. var projection = this.renderSession.projection;
  5239. gl.uniform2f(this.shader.projectionVector, projection.x, projection.y);
  5240. // set the matrix
  5241. gl.uniformMatrix3fv(this.shader.uMatrix, false, this.matrix);
  5242. // set the pointers
  5243. var stride = this.vertSize * 4;
  5244. gl.vertexAttribPointer(this.shader.aVertexPosition, 2, gl.FLOAT, false, stride, 0);
  5245. gl.vertexAttribPointer(this.shader.aPositionCoord, 2, gl.FLOAT, false, stride, 2 * 4);
  5246. gl.vertexAttribPointer(this.shader.aScale, 2, gl.FLOAT, false, stride, 4 * 4);
  5247. gl.vertexAttribPointer(this.shader.aRotation, 1, gl.FLOAT, false, stride, 6 * 4);
  5248. gl.vertexAttribPointer(this.shader.aTextureCoord, 2, gl.FLOAT, false, stride, 7 * 4);
  5249. gl.vertexAttribPointer(this.shader.colorAttribute, 1, gl.FLOAT, false, stride, 9 * 4);
  5250. // set the blend mode..
  5251. if(this.currentBlendMode !== PIXI.blendModes.NORMAL)
  5252. {
  5253. this.setBlendMode(PIXI.blendModes.NORMAL);
  5254. }
  5255. };
  5256. PIXI.WebGLFastSpriteBatch.prototype.setBlendMode = function(blendMode)
  5257. {
  5258. this.flush();
  5259. this.currentBlendMode = blendMode;
  5260. var blendModeWebGL = PIXI.blendModesWebGL[this.currentBlendMode];
  5261. this.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
  5262. };
  5263. /**
  5264. * @author Mat Groves http://matgroves.com/ @Doormat23
  5265. */
  5266. /**
  5267. * @class WebGLFilterManager
  5268. * @constructor
  5269. * @param gl {WebGLContext} the current WebGL drawing context
  5270. * @param transparent {Boolean} Whether or not the drawing context should be transparent
  5271. * @private
  5272. */
  5273. PIXI.WebGLFilterManager = function(gl, transparent)
  5274. {
  5275. this.transparent = transparent;
  5276. this.filterStack = [];
  5277. this.offsetX = 0;
  5278. this.offsetY = 0;
  5279. this.setContext(gl);
  5280. };
  5281. // API
  5282. /**
  5283. * Initialises the context and the properties
  5284. * @method setContext
  5285. * @param gl {WebGLContext} the current WebGL drawing context
  5286. */
  5287. PIXI.WebGLFilterManager.prototype.setContext = function(gl)
  5288. {
  5289. this.gl = gl;
  5290. this.texturePool = [];
  5291. this.initShaderBuffers();
  5292. };
  5293. /**
  5294. *
  5295. * @method begin
  5296. * @param renderSession {RenderSession}
  5297. * @param buffer {ArrayBuffer}
  5298. */
  5299. PIXI.WebGLFilterManager.prototype.begin = function(renderSession, buffer)
  5300. {
  5301. this.renderSession = renderSession;
  5302. this.defaultShader = renderSession.shaderManager.defaultShader;
  5303. var projection = this.renderSession.projection;
  5304. // console.log(this.width)
  5305. this.width = projection.x * 2;
  5306. this.height = -projection.y * 2;
  5307. this.buffer = buffer;
  5308. };
  5309. /**
  5310. * Applies the filter and adds it to the current filter stack
  5311. * @method pushFilter
  5312. * @param filterBlock {Object} the filter that will be pushed to the current filter stack
  5313. */
  5314. PIXI.WebGLFilterManager.prototype.pushFilter = function(filterBlock)
  5315. {
  5316. var gl = this.gl;
  5317. var projection = this.renderSession.projection;
  5318. var offset = this.renderSession.offset;
  5319. filterBlock._filterArea = filterBlock.target.filterArea || filterBlock.target.getBounds();
  5320. // filter program
  5321. // OPTIMISATION - the first filter is free if its a simple color change?
  5322. this.filterStack.push(filterBlock);
  5323. var filter = filterBlock.filterPasses[0];
  5324. this.offsetX += filterBlock._filterArea.x;
  5325. this.offsetY += filterBlock._filterArea.y;
  5326. var texture = this.texturePool.pop();
  5327. if(!texture)
  5328. {
  5329. texture = new PIXI.FilterTexture(this.gl, this.width, this.height);
  5330. }
  5331. else
  5332. {
  5333. texture.resize(this.width, this.height);
  5334. }
  5335. gl.bindTexture(gl.TEXTURE_2D, texture.texture);
  5336. var filterArea = filterBlock._filterArea;// filterBlock.target.getBounds();///filterBlock.target.filterArea;
  5337. var padidng = filter.padding;
  5338. filterArea.x -= padidng;
  5339. filterArea.y -= padidng;
  5340. filterArea.width += padidng * 2;
  5341. filterArea.height += padidng * 2;
  5342. // cap filter to screen size..
  5343. if(filterArea.x < 0)filterArea.x = 0;
  5344. if(filterArea.width > this.width)filterArea.width = this.width;
  5345. if(filterArea.y < 0)filterArea.y = 0;
  5346. if(filterArea.height > this.height)filterArea.height = this.height;
  5347. //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  5348. gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer);
  5349. // set view port
  5350. gl.viewport(0, 0, filterArea.width, filterArea.height);
  5351. projection.x = filterArea.width/2;
  5352. projection.y = -filterArea.height/2;
  5353. offset.x = -filterArea.x;
  5354. offset.y = -filterArea.y;
  5355. // update projection
  5356. gl.uniform2f(this.defaultShader.projectionVector, filterArea.width/2, -filterArea.height/2);
  5357. gl.uniform2f(this.defaultShader.offsetVector, -filterArea.x, -filterArea.y);
  5358. gl.colorMask(true, true, true, true);
  5359. gl.clearColor(0,0,0, 0);
  5360. gl.clear(gl.COLOR_BUFFER_BIT);
  5361. filterBlock._glFilterTexture = texture;
  5362. };
  5363. /**
  5364. * Removes the last filter from the filter stack and doesn't return it
  5365. * @method popFilter
  5366. */
  5367. PIXI.WebGLFilterManager.prototype.popFilter = function()
  5368. {
  5369. var gl = this.gl;
  5370. var filterBlock = this.filterStack.pop();
  5371. var filterArea = filterBlock._filterArea;
  5372. var texture = filterBlock._glFilterTexture;
  5373. var projection = this.renderSession.projection;
  5374. var offset = this.renderSession.offset;
  5375. if(filterBlock.filterPasses.length > 1)
  5376. {
  5377. gl.viewport(0, 0, filterArea.width, filterArea.height);
  5378. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  5379. this.vertexArray[0] = 0;
  5380. this.vertexArray[1] = filterArea.height;
  5381. this.vertexArray[2] = filterArea.width;
  5382. this.vertexArray[3] = filterArea.height;
  5383. this.vertexArray[4] = 0;
  5384. this.vertexArray[5] = 0;
  5385. this.vertexArray[6] = filterArea.width;
  5386. this.vertexArray[7] = 0;
  5387. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray);
  5388. gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
  5389. // now set the uvs..
  5390. this.uvArray[2] = filterArea.width/this.width;
  5391. this.uvArray[5] = filterArea.height/this.height;
  5392. this.uvArray[6] = filterArea.width/this.width;
  5393. this.uvArray[7] = filterArea.height/this.height;
  5394. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray);
  5395. var inputTexture = texture;
  5396. var outputTexture = this.texturePool.pop();
  5397. if(!outputTexture)outputTexture = new PIXI.FilterTexture(this.gl, this.width, this.height);
  5398. outputTexture.resize(this.width, this.height);
  5399. // need to clear this FBO as it may have some left over elements from a previous filter.
  5400. gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer );
  5401. gl.clear(gl.COLOR_BUFFER_BIT);
  5402. gl.disable(gl.BLEND);
  5403. for (var i = 0; i < filterBlock.filterPasses.length-1; i++)
  5404. {
  5405. var filterPass = filterBlock.filterPasses[i];
  5406. gl.bindFramebuffer(gl.FRAMEBUFFER, outputTexture.frameBuffer );
  5407. // set texture
  5408. gl.activeTexture(gl.TEXTURE0);
  5409. gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture);
  5410. // draw texture..
  5411. //filterPass.applyFilterPass(filterArea.width, filterArea.height);
  5412. this.applyFilterPass(filterPass, filterArea, filterArea.width, filterArea.height);
  5413. // swap the textures..
  5414. var temp = inputTexture;
  5415. inputTexture = outputTexture;
  5416. outputTexture = temp;
  5417. }
  5418. gl.enable(gl.BLEND);
  5419. texture = inputTexture;
  5420. this.texturePool.push(outputTexture);
  5421. }
  5422. var filter = filterBlock.filterPasses[filterBlock.filterPasses.length-1];
  5423. this.offsetX -= filterArea.x;
  5424. this.offsetY -= filterArea.y;
  5425. var sizeX = this.width;
  5426. var sizeY = this.height;
  5427. var offsetX = 0;
  5428. var offsetY = 0;
  5429. var buffer = this.buffer;
  5430. // time to render the filters texture to the previous scene
  5431. if(this.filterStack.length === 0)
  5432. {
  5433. gl.colorMask(true, true, true, true);//this.transparent);
  5434. }
  5435. else
  5436. {
  5437. var currentFilter = this.filterStack[this.filterStack.length-1];
  5438. filterArea = currentFilter._filterArea;
  5439. sizeX = filterArea.width;
  5440. sizeY = filterArea.height;
  5441. offsetX = filterArea.x;
  5442. offsetY = filterArea.y;
  5443. buffer = currentFilter._glFilterTexture.frameBuffer;
  5444. }
  5445. // TODO need toremove thease global elements..
  5446. projection.x = sizeX/2;
  5447. projection.y = -sizeY/2;
  5448. offset.x = offsetX;
  5449. offset.y = offsetY;
  5450. filterArea = filterBlock._filterArea;
  5451. var x = filterArea.x-offsetX;
  5452. var y = filterArea.y-offsetY;
  5453. // update the buffers..
  5454. // make sure to flip the y!
  5455. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  5456. this.vertexArray[0] = x;
  5457. this.vertexArray[1] = y + filterArea.height;
  5458. this.vertexArray[2] = x + filterArea.width;
  5459. this.vertexArray[3] = y + filterArea.height;
  5460. this.vertexArray[4] = x;
  5461. this.vertexArray[5] = y;
  5462. this.vertexArray[6] = x + filterArea.width;
  5463. this.vertexArray[7] = y;
  5464. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray);
  5465. gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
  5466. this.uvArray[2] = filterArea.width/this.width;
  5467. this.uvArray[5] = filterArea.height/this.height;
  5468. this.uvArray[6] = filterArea.width/this.width;
  5469. this.uvArray[7] = filterArea.height/this.height;
  5470. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.uvArray);
  5471. //console.log(this.vertexArray)
  5472. //console.log(this.uvArray)
  5473. //console.log(sizeX + " : " + sizeY)
  5474. gl.viewport(0, 0, sizeX, sizeY);
  5475. // bind the buffer
  5476. gl.bindFramebuffer(gl.FRAMEBUFFER, buffer );
  5477. // set the blend mode!
  5478. //gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
  5479. // set texture
  5480. gl.activeTexture(gl.TEXTURE0);
  5481. gl.bindTexture(gl.TEXTURE_2D, texture.texture);
  5482. // apply!
  5483. this.applyFilterPass(filter, filterArea, sizeX, sizeY);
  5484. // now restore the regular shader..
  5485. gl.useProgram(this.defaultShader.program);
  5486. gl.uniform2f(this.defaultShader.projectionVector, sizeX/2, -sizeY/2);
  5487. gl.uniform2f(this.defaultShader.offsetVector, -offsetX, -offsetY);
  5488. // return the texture to the pool
  5489. this.texturePool.push(texture);
  5490. filterBlock._glFilterTexture = null;
  5491. };
  5492. /**
  5493. * Applies the filter to the specified area
  5494. * @method applyFilterPass
  5495. * @param filter {AbstractFilter} the filter that needs to be applied
  5496. * @param filterArea {texture} TODO - might need an update
  5497. * @param width {Number} the horizontal range of the filter
  5498. * @param height {Number} the vertical range of the filter
  5499. */
  5500. PIXI.WebGLFilterManager.prototype.applyFilterPass = function(filter, filterArea, width, height)
  5501. {
  5502. // use program
  5503. var gl = this.gl;
  5504. var shader = filter.shaders[gl.id];
  5505. if(!shader)
  5506. {
  5507. shader = new PIXI.PixiShader(gl);
  5508. shader.fragmentSrc = filter.fragmentSrc;
  5509. shader.uniforms = filter.uniforms;
  5510. shader.init();
  5511. filter.shaders[gl.id] = shader;
  5512. }
  5513. // set the shader
  5514. gl.useProgram(shader.program);
  5515. gl.uniform2f(shader.projectionVector, width/2, -height/2);
  5516. gl.uniform2f(shader.offsetVector, 0,0);
  5517. if(filter.uniforms.dimensions)
  5518. {
  5519. filter.uniforms.dimensions.value[0] = this.width;//width;
  5520. filter.uniforms.dimensions.value[1] = this.height;//height;
  5521. filter.uniforms.dimensions.value[2] = this.vertexArray[0];
  5522. filter.uniforms.dimensions.value[3] = this.vertexArray[5];//filterArea.height;
  5523. }
  5524. // console.log(this.uvArray )
  5525. shader.syncUniforms();
  5526. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  5527. gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
  5528. gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
  5529. gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
  5530. gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
  5531. gl.vertexAttribPointer(shader.colorAttribute, 2, gl.FLOAT, false, 0, 0);
  5532. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  5533. // draw the filter...
  5534. gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
  5535. this.renderSession.drawCount++;
  5536. };
  5537. /**
  5538. * Initialises the shader buffers
  5539. * @method initShaderBuffers
  5540. */
  5541. PIXI.WebGLFilterManager.prototype.initShaderBuffers = function()
  5542. {
  5543. var gl = this.gl;
  5544. // create some buffers
  5545. this.vertexBuffer = gl.createBuffer();
  5546. this.uvBuffer = gl.createBuffer();
  5547. this.colorBuffer = gl.createBuffer();
  5548. this.indexBuffer = gl.createBuffer();
  5549. // bind and upload the vertexs..
  5550. // keep a reference to the vertexFloatData..
  5551. this.vertexArray = new Float32Array([0.0, 0.0,
  5552. 1.0, 0.0,
  5553. 0.0, 1.0,
  5554. 1.0, 1.0]);
  5555. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
  5556. gl.bufferData(
  5557. gl.ARRAY_BUFFER,
  5558. this.vertexArray,
  5559. gl.STATIC_DRAW);
  5560. // bind and upload the uv buffer
  5561. this.uvArray = new Float32Array([0.0, 0.0,
  5562. 1.0, 0.0,
  5563. 0.0, 1.0,
  5564. 1.0, 1.0]);
  5565. gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
  5566. gl.bufferData(
  5567. gl.ARRAY_BUFFER,
  5568. this.uvArray,
  5569. gl.STATIC_DRAW);
  5570. this.colorArray = new Float32Array([1.0, 0xFFFFFF,
  5571. 1.0, 0xFFFFFF,
  5572. 1.0, 0xFFFFFF,
  5573. 1.0, 0xFFFFFF]);
  5574. gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
  5575. gl.bufferData(
  5576. gl.ARRAY_BUFFER,
  5577. this.colorArray,
  5578. gl.STATIC_DRAW);
  5579. // bind and upload the index
  5580. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  5581. gl.bufferData(
  5582. gl.ELEMENT_ARRAY_BUFFER,
  5583. new Uint16Array([0, 1, 2, 1, 3, 2]),
  5584. gl.STATIC_DRAW);
  5585. };
  5586. /**
  5587. * Destroys the filter and removes it from the filter stack
  5588. * @method destroy
  5589. */
  5590. PIXI.WebGLFilterManager.prototype.destroy = function()
  5591. {
  5592. var gl = this.gl;
  5593. this.filterStack = null;
  5594. this.offsetX = 0;
  5595. this.offsetY = 0;
  5596. // destroy textures
  5597. for (var i = 0; i < this.texturePool.length; i++) {
  5598. this.texturePool.destroy();
  5599. }
  5600. this.texturePool = null;
  5601. //destroy buffers..
  5602. gl.deleteBuffer(this.vertexBuffer);
  5603. gl.deleteBuffer(this.uvBuffer);
  5604. gl.deleteBuffer(this.colorBuffer);
  5605. gl.deleteBuffer(this.indexBuffer);
  5606. };
  5607. /**
  5608. * @author Mat Groves http://matgroves.com/ @Doormat23
  5609. */
  5610. /**
  5611. * @class FilterTexture
  5612. * @constructor
  5613. * @param gl {WebGLContext} the current WebGL drawing context
  5614. * @param width {Number} the horizontal range of the filter
  5615. * @param height {Number} the vertical range of the filter
  5616. * @private
  5617. */
  5618. PIXI.FilterTexture = function(gl, width, height)
  5619. {
  5620. /**
  5621. * @property gl
  5622. * @type WebGLContext
  5623. */
  5624. this.gl = gl;
  5625. // next time to create a frame buffer and texture
  5626. this.frameBuffer = gl.createFramebuffer();
  5627. this.texture = gl.createTexture();
  5628. gl.bindTexture(gl.TEXTURE_2D, this.texture);
  5629. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  5630. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  5631. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  5632. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  5633. gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer );
  5634. gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer );
  5635. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
  5636. this.resize(width, height);
  5637. };
  5638. /**
  5639. * Clears the filter texture
  5640. * @method clear
  5641. */
  5642. PIXI.FilterTexture.prototype.clear = function()
  5643. {
  5644. var gl = this.gl;
  5645. gl.clearColor(0,0,0, 0);
  5646. gl.clear(gl.COLOR_BUFFER_BIT);
  5647. };
  5648. /**
  5649. * Resizes the texture to the specified width and height
  5650. *
  5651. * @method resize
  5652. * @param width {Number} the new width of the texture
  5653. * @param height {Number} the new height of the texture
  5654. */
  5655. PIXI.FilterTexture.prototype.resize = function(width, height)
  5656. {
  5657. if(this.width === width && this.height === height) return;
  5658. this.width = width;
  5659. this.height = height;
  5660. var gl = this.gl;
  5661. gl.bindTexture(gl.TEXTURE_2D, this.texture);
  5662. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  5663. };
  5664. /**
  5665. * Destroys the filter texture
  5666. * @method destroy
  5667. */
  5668. PIXI.FilterTexture.prototype.destroy = function()
  5669. {
  5670. var gl = this.gl;
  5671. gl.deleteFramebuffer( this.frameBuffer );
  5672. gl.deleteTexture( this.texture );
  5673. this.frameBuffer = null;
  5674. this.texture = null;
  5675. };
  5676. /**
  5677. * @author Mat Groves
  5678. *
  5679. *
  5680. */
  5681. /**
  5682. * A set of functions used to handle masking
  5683. *
  5684. * @class CanvasMaskManager
  5685. */
  5686. PIXI.CanvasMaskManager = function()
  5687. {
  5688. };
  5689. /**
  5690. * This method adds it to the current stack of masks
  5691. *
  5692. * @method pushMask
  5693. * @param maskData the maskData that will be pushed
  5694. * @param context {Context2D} the 2d drawing method of the canvas
  5695. */
  5696. PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context)
  5697. {
  5698. context.save();
  5699. var cacheAlpha = maskData.alpha;
  5700. var transform = maskData.worldTransform;
  5701. context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
  5702. PIXI.CanvasGraphics.renderGraphicsMask(maskData, context);
  5703. context.clip();
  5704. maskData.worldAlpha = cacheAlpha;
  5705. };
  5706. /**
  5707. * Restores the current drawing context to the state it was before the mask was applied
  5708. *
  5709. * @method popMask
  5710. * @param context {Context2D} the 2d drawing method of the canvas
  5711. */
  5712. PIXI.CanvasMaskManager.prototype.popMask = function(context)
  5713. {
  5714. context.restore();
  5715. };
  5716. /**
  5717. * @author Mat Groves
  5718. *
  5719. *
  5720. */
  5721. /**
  5722. * @class CanvasTinter
  5723. * @constructor
  5724. * @static
  5725. */
  5726. PIXI.CanvasTinter = function()
  5727. {
  5728. /// this.textureCach
  5729. };
  5730. //PIXI.CanvasTinter.cachTint = true;
  5731. /**
  5732. * Basically this method just needs a sprite and a color and tints the sprite
  5733. * with the given color
  5734. *
  5735. * @method getTintedTexture
  5736. * @param sprite {Sprite} the sprite to tint
  5737. * @param color {Number} the color to use to tint the sprite with
  5738. */
  5739. PIXI.CanvasTinter.getTintedTexture = function(sprite, color)
  5740. {
  5741. var texture = sprite.texture;
  5742. color = PIXI.CanvasTinter.roundColor(color);
  5743. var stringColor = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
  5744. texture.tintCache = texture.tintCache || {};
  5745. if(texture.tintCache[stringColor]) return texture.tintCache[stringColor];
  5746. // clone texture..
  5747. var canvas = PIXI.CanvasTinter.canvas || document.createElement("canvas");
  5748. //PIXI.CanvasTinter.tintWithPerPixel(texture, stringColor, canvas);
  5749. PIXI.CanvasTinter.tintMethod(texture, color, canvas);
  5750. if(PIXI.CanvasTinter.convertTintToImage)
  5751. {
  5752. // is this better?
  5753. var tintImage = new Image();
  5754. tintImage.src = canvas.toDataURL();
  5755. texture.tintCache[stringColor] = tintImage;
  5756. }
  5757. else
  5758. {
  5759. texture.tintCache[stringColor] = canvas;
  5760. // if we are not converting the texture to an image then we need to lose the reference to the canvas
  5761. PIXI.CanvasTinter.canvas = null;
  5762. }
  5763. return canvas;
  5764. };
  5765. /**
  5766. * Tint a texture using the "multiply" operation
  5767. * @method tintWithMultiply
  5768. * @param texture {texture} the texture to tint
  5769. * @param color {Number} the color to use to tint the sprite with
  5770. * @param canvas {HTMLCanvasElement} the current canvas
  5771. */
  5772. PIXI.CanvasTinter.tintWithMultiply = function(texture, color, canvas)
  5773. {
  5774. var context = canvas.getContext( "2d" );
  5775. var frame = texture.frame;
  5776. canvas.width = frame.width;
  5777. canvas.height = frame.height;
  5778. context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
  5779. context.fillRect(0, 0, frame.width, frame.height);
  5780. context.globalCompositeOperation = "multiply";
  5781. context.drawImage(texture.baseTexture.source,
  5782. frame.x,
  5783. frame.y,
  5784. frame.width,
  5785. frame.height,
  5786. 0,
  5787. 0,
  5788. frame.width,
  5789. frame.height);
  5790. context.globalCompositeOperation = "destination-atop";
  5791. context.drawImage(texture.baseTexture.source,
  5792. frame.x,
  5793. frame.y,
  5794. frame.width,
  5795. frame.height,
  5796. 0,
  5797. 0,
  5798. frame.width,
  5799. frame.height);
  5800. };
  5801. /**
  5802. * Tint a texture using the "overlay" operation
  5803. * @method tintWithOverlay
  5804. * @param texture {texture} the texture to tint
  5805. * @param color {Number} the color to use to tint the sprite with
  5806. * @param canvas {HTMLCanvasElement} the current canvas
  5807. */
  5808. PIXI.CanvasTinter.tintWithOverlay = function(texture, color, canvas)
  5809. {
  5810. var context = canvas.getContext( "2d" );
  5811. var frame = texture.frame;
  5812. canvas.width = frame.width;
  5813. canvas.height = frame.height;
  5814. context.globalCompositeOperation = "copy";
  5815. context.fillStyle = "#" + ("00000" + ( color | 0).toString(16)).substr(-6);
  5816. context.fillRect(0, 0, frame.width, frame.height);
  5817. context.globalCompositeOperation = "destination-atop";
  5818. context.drawImage(texture.baseTexture.source,
  5819. frame.x,
  5820. frame.y,
  5821. frame.width,
  5822. frame.height,
  5823. 0,
  5824. 0,
  5825. frame.width,
  5826. frame.height);
  5827. //context.globalCompositeOperation = "copy";
  5828. };
  5829. /**
  5830. * Tint a texture pixel per pixel
  5831. * @method tintPerPixel
  5832. * @param texture {texture} the texture to tint
  5833. * @param color {Number} the color to use to tint the sprite with
  5834. * @param canvas {HTMLCanvasElement} the current canvas
  5835. */
  5836. PIXI.CanvasTinter.tintWithPerPixel = function(texture, color, canvas)
  5837. {
  5838. var context = canvas.getContext( "2d" );
  5839. var frame = texture.frame;
  5840. canvas.width = frame.width;
  5841. canvas.height = frame.height;
  5842. context.globalCompositeOperation = "copy";
  5843. context.drawImage(texture.baseTexture.source,
  5844. frame.x,
  5845. frame.y,
  5846. frame.width,
  5847. frame.height,
  5848. 0,
  5849. 0,
  5850. frame.width,
  5851. frame.height);
  5852. var rgbValues = PIXI.hex2rgb(color);
  5853. var r = rgbValues[0], g = rgbValues[1], b = rgbValues[2];
  5854. var pixelData = context.getImageData(0, 0, frame.width, frame.height);
  5855. var pixels = pixelData.data;
  5856. for (var i = 0; i < pixels.length; i += 4)
  5857. {
  5858. pixels[i+0] *= r;
  5859. pixels[i+1] *= g;
  5860. pixels[i+2] *= b;
  5861. }
  5862. context.putImageData(pixelData, 0, 0);
  5863. };
  5864. /**
  5865. * Rounds the specified color according to the PIXI.CanvasTinter.cacheStepsPerColorChannel
  5866. * @method roundColor
  5867. * @param color {number} the color to round, should be a hex color
  5868. */
  5869. PIXI.CanvasTinter.roundColor = function(color)
  5870. {
  5871. var step = PIXI.CanvasTinter.cacheStepsPerColorChannel;
  5872. var rgbValues = PIXI.hex2rgb(color);
  5873. rgbValues[0] = Math.min(255, (rgbValues[0] / step) * step);
  5874. rgbValues[1] = Math.min(255, (rgbValues[1] / step) * step);
  5875. rgbValues[2] = Math.min(255, (rgbValues[2] / step) * step);
  5876. return PIXI.rgb2hex(rgbValues);
  5877. };
  5878. /**
  5879. *
  5880. * Number of steps which will be used as a cap when rounding colors
  5881. *
  5882. * @property cacheStepsPerColorChannel
  5883. * @type Number
  5884. */
  5885. PIXI.CanvasTinter.cacheStepsPerColorChannel = 8;
  5886. /**
  5887. *
  5888. * Number of steps which will be used as a cap when rounding colors
  5889. *
  5890. * @property convertTintToImage
  5891. * @type Boolean
  5892. */
  5893. PIXI.CanvasTinter.convertTintToImage = false;
  5894. /**
  5895. * Whether or not the Canvas BlendModes are supported, consequently the ability to tint using the multiply method
  5896. *
  5897. * @property canUseMultiply
  5898. * @type Boolean
  5899. */
  5900. PIXI.CanvasTinter.canUseMultiply = PIXI.canUseNewCanvasBlendModes();
  5901. PIXI.CanvasTinter.tintMethod = PIXI.CanvasTinter.canUseMultiply ? PIXI.CanvasTinter.tintWithMultiply : PIXI.CanvasTinter.tintWithPerPixel;
  5902. /**
  5903. * @author Mat Groves http://matgroves.com/ @Doormat23
  5904. */
  5905. /**
  5906. * the CanvasRenderer draws the stage and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL.
  5907. * Dont forget to add the view to your DOM or you will not see anything :)
  5908. *
  5909. * @class CanvasRenderer
  5910. * @constructor
  5911. * @param width=800 {Number} the width of the canvas view
  5912. * @param height=600 {Number} the height of the canvas view
  5913. * @param [view] {HTMLCanvasElement} the canvas to use as a view, optional
  5914. * @param [transparent=false] {Boolean} the transparency of the render view, default false
  5915. */
  5916. PIXI.CanvasRenderer = function(width, height, view, transparent)
  5917. {
  5918. PIXI.defaultRenderer = PIXI.defaultRenderer || this;
  5919. this.type = PIXI.CANVAS_RENDERER;
  5920. /**
  5921. * This sets if the CanvasRenderer will clear the canvas or not before the new render pass.
  5922. * If the Stage is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color.
  5923. * If the Stage is transparent Pixi will use clearRect to clear the canvas every frame.
  5924. * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set.
  5925. *
  5926. * @property clearBeforeRender
  5927. * @type Boolean
  5928. * @default
  5929. */
  5930. this.clearBeforeRender = true;
  5931. /**
  5932. * If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation.
  5933. * Handy for crisp pixel art and speed on legacy devices.
  5934. *
  5935. * @property roundPixels
  5936. * @type Boolean
  5937. * @default
  5938. */
  5939. this.roundPixels = false;
  5940. /**
  5941. * Whether the render view is transparent
  5942. *
  5943. * @property transparent
  5944. * @type Boolean
  5945. */
  5946. this.transparent = !!transparent;
  5947. if(!PIXI.blendModesCanvas)
  5948. {
  5949. PIXI.blendModesCanvas = [];
  5950. if(PIXI.canUseNewCanvasBlendModes())
  5951. {
  5952. PIXI.blendModesCanvas[PIXI.blendModes.NORMAL] = "source-over";
  5953. PIXI.blendModesCanvas[PIXI.blendModes.ADD] = "lighter"; //IS THIS OK???
  5954. PIXI.blendModesCanvas[PIXI.blendModes.MULTIPLY] = "multiply";
  5955. PIXI.blendModesCanvas[PIXI.blendModes.SCREEN] = "screen";
  5956. PIXI.blendModesCanvas[PIXI.blendModes.OVERLAY] = "overlay";
  5957. PIXI.blendModesCanvas[PIXI.blendModes.DARKEN] = "darken";
  5958. PIXI.blendModesCanvas[PIXI.blendModes.LIGHTEN] = "lighten";
  5959. PIXI.blendModesCanvas[PIXI.blendModes.COLOR_DODGE] = "color-dodge";
  5960. PIXI.blendModesCanvas[PIXI.blendModes.COLOR_BURN] = "color-burn";
  5961. PIXI.blendModesCanvas[PIXI.blendModes.HARD_LIGHT] = "hard-light";
  5962. PIXI.blendModesCanvas[PIXI.blendModes.SOFT_LIGHT] = "soft-light";
  5963. PIXI.blendModesCanvas[PIXI.blendModes.DIFFERENCE] = "difference";
  5964. PIXI.blendModesCanvas[PIXI.blendModes.EXCLUSION] = "exclusion";
  5965. PIXI.blendModesCanvas[PIXI.blendModes.HUE] = "hue";
  5966. PIXI.blendModesCanvas[PIXI.blendModes.SATURATION] = "saturation";
  5967. PIXI.blendModesCanvas[PIXI.blendModes.COLOR] = "color";
  5968. PIXI.blendModesCanvas[PIXI.blendModes.LUMINOSITY] = "luminosity";
  5969. }
  5970. else
  5971. {
  5972. // this means that the browser does not support the cool new blend modes in canvas "cough" ie "cough"
  5973. PIXI.blendModesCanvas[PIXI.blendModes.NORMAL] = "source-over";
  5974. PIXI.blendModesCanvas[PIXI.blendModes.ADD] = "lighter"; //IS THIS OK???
  5975. PIXI.blendModesCanvas[PIXI.blendModes.MULTIPLY] = "source-over";
  5976. PIXI.blendModesCanvas[PIXI.blendModes.SCREEN] = "source-over";
  5977. PIXI.blendModesCanvas[PIXI.blendModes.OVERLAY] = "source-over";
  5978. PIXI.blendModesCanvas[PIXI.blendModes.DARKEN] = "source-over";
  5979. PIXI.blendModesCanvas[PIXI.blendModes.LIGHTEN] = "source-over";
  5980. PIXI.blendModesCanvas[PIXI.blendModes.COLOR_DODGE] = "source-over";
  5981. PIXI.blendModesCanvas[PIXI.blendModes.COLOR_BURN] = "source-over";
  5982. PIXI.blendModesCanvas[PIXI.blendModes.HARD_LIGHT] = "source-over";
  5983. PIXI.blendModesCanvas[PIXI.blendModes.SOFT_LIGHT] = "source-over";
  5984. PIXI.blendModesCanvas[PIXI.blendModes.DIFFERENCE] = "source-over";
  5985. PIXI.blendModesCanvas[PIXI.blendModes.EXCLUSION] = "source-over";
  5986. PIXI.blendModesCanvas[PIXI.blendModes.HUE] = "source-over";
  5987. PIXI.blendModesCanvas[PIXI.blendModes.SATURATION] = "source-over";
  5988. PIXI.blendModesCanvas[PIXI.blendModes.COLOR] = "source-over";
  5989. PIXI.blendModesCanvas[PIXI.blendModes.LUMINOSITY] = "source-over";
  5990. }
  5991. }
  5992. /**
  5993. * The width of the canvas view
  5994. *
  5995. * @property width
  5996. * @type Number
  5997. * @default 800
  5998. */
  5999. this.width = width || 800;
  6000. /**
  6001. * The height of the canvas view
  6002. *
  6003. * @property height
  6004. * @type Number
  6005. * @default 600
  6006. */
  6007. this.height = height || 600;
  6008. /**
  6009. * The canvas element that everything is drawn to
  6010. *
  6011. * @property view
  6012. * @type HTMLCanvasElement
  6013. */
  6014. this.view = view || document.createElement( "canvas" );
  6015. /**
  6016. * The canvas 2d context that everything is drawn with
  6017. * @property context
  6018. * @type HTMLCanvasElement 2d Context
  6019. */
  6020. this.context = this.view.getContext( "2d", { alpha: this.transparent } );
  6021. this.refresh = true;
  6022. // hack to enable some hardware acceleration!
  6023. //this.view.style["transform"] = "translatez(0)";
  6024. this.view.width = this.width;
  6025. this.view.height = this.height;
  6026. this.count = 0;
  6027. /**
  6028. * Instance of a PIXI.CanvasMaskManager, handles masking when using the canvas renderer
  6029. * @property CanvasMaskManager
  6030. * @type CanvasMaskManager
  6031. */
  6032. this.maskManager = new PIXI.CanvasMaskManager();
  6033. /**
  6034. * The render session is just a bunch of parameter used for rendering
  6035. * @property renderSession
  6036. * @type Object
  6037. */
  6038. this.renderSession = {
  6039. context: this.context,
  6040. maskManager: this.maskManager,
  6041. scaleMode: null,
  6042. smoothProperty: null
  6043. };
  6044. if("imageSmoothingEnabled" in this.context)
  6045. this.renderSession.smoothProperty = "imageSmoothingEnabled";
  6046. else if("webkitImageSmoothingEnabled" in this.context)
  6047. this.renderSession.smoothProperty = "webkitImageSmoothingEnabled";
  6048. else if("mozImageSmoothingEnabled" in this.context)
  6049. this.renderSession.smoothProperty = "mozImageSmoothingEnabled";
  6050. else if("oImageSmoothingEnabled" in this.context)
  6051. this.renderSession.smoothProperty = "oImageSmoothingEnabled";
  6052. };
  6053. // constructor
  6054. PIXI.CanvasRenderer.prototype.constructor = PIXI.CanvasRenderer;
  6055. /**
  6056. * Renders the stage to its canvas view
  6057. *
  6058. * @method render
  6059. * @param stage {Stage} the Stage element to be rendered
  6060. */
  6061. PIXI.CanvasRenderer.prototype.render = function(stage)
  6062. {
  6063. // update textures if need be
  6064. PIXI.texturesToUpdate.length = 0;
  6065. PIXI.texturesToDestroy.length = 0;
  6066. stage.updateTransform();
  6067. this.context.setTransform(1,0,0,1,0,0);
  6068. this.context.globalAlpha = 1;
  6069. if (!this.transparent && this.clearBeforeRender)
  6070. {
  6071. this.context.fillStyle = stage.backgroundColorString;
  6072. this.context.fillRect(0, 0, this.width, this.height);
  6073. }
  6074. else if (this.transparent && this.clearBeforeRender)
  6075. {
  6076. this.context.clearRect(0, 0, this.width, this.height);
  6077. }
  6078. this.renderDisplayObject(stage);
  6079. // run interaction!
  6080. if(stage.interactive)
  6081. {
  6082. //need to add some events!
  6083. if(!stage._interactiveEventsAdded)
  6084. {
  6085. stage._interactiveEventsAdded = true;
  6086. stage.interactionManager.setTarget(this);
  6087. }
  6088. }
  6089. // remove frame updates..
  6090. if(PIXI.Texture.frameUpdates.length > 0)
  6091. {
  6092. PIXI.Texture.frameUpdates.length = 0;
  6093. }
  6094. };
  6095. /**
  6096. * Resizes the canvas view to the specified width and height
  6097. *
  6098. * @method resize
  6099. * @param width {Number} the new width of the canvas view
  6100. * @param height {Number} the new height of the canvas view
  6101. */
  6102. PIXI.CanvasRenderer.prototype.resize = function(width, height)
  6103. {
  6104. this.width = width;
  6105. this.height = height;
  6106. this.view.width = width;
  6107. this.view.height = height;
  6108. };
  6109. /**
  6110. * Renders a display object
  6111. *
  6112. * @method renderDisplayObject
  6113. * @param displayObject {DisplayObject} The displayObject to render
  6114. * @param context {Context2D} the context 2d method of the canvas
  6115. * @private
  6116. */
  6117. PIXI.CanvasRenderer.prototype.renderDisplayObject = function(displayObject, context)
  6118. {
  6119. // no longer recursive!
  6120. //var transform;
  6121. //var context = this.context;
  6122. this.renderSession.context = context || this.context;
  6123. displayObject._renderCanvas(this.renderSession);
  6124. };
  6125. /**
  6126. * Renders a flat strip
  6127. *
  6128. * @method renderStripFlat
  6129. * @param strip {Strip} The Strip to render
  6130. * @private
  6131. */
  6132. PIXI.CanvasRenderer.prototype.renderStripFlat = function(strip)
  6133. {
  6134. var context = this.context;
  6135. var verticies = strip.verticies;
  6136. var length = verticies.length/2;
  6137. this.count++;
  6138. context.beginPath();
  6139. for (var i=1; i < length-2; i++)
  6140. {
  6141. // draw some triangles!
  6142. var index = i*2;
  6143. var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4];
  6144. var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5];
  6145. context.moveTo(x0, y0);
  6146. context.lineTo(x1, y1);
  6147. context.lineTo(x2, y2);
  6148. }
  6149. context.fillStyle = "#FF0000";
  6150. context.fill();
  6151. context.closePath();
  6152. };
  6153. /**
  6154. * Renders a strip
  6155. *
  6156. * @method renderStrip
  6157. * @param strip {Strip} The Strip to render
  6158. * @private
  6159. */
  6160. PIXI.CanvasRenderer.prototype.renderStrip = function(strip)
  6161. {
  6162. var context = this.context;
  6163. // draw triangles!!
  6164. var verticies = strip.verticies;
  6165. var uvs = strip.uvs;
  6166. var length = verticies.length/2;
  6167. this.count++;
  6168. for (var i = 1; i < length-2; i++)
  6169. {
  6170. // draw some triangles!
  6171. var index = i*2;
  6172. var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4];
  6173. var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5];
  6174. var u0 = uvs[index] * strip.texture.width, u1 = uvs[index+2] * strip.texture.width, u2 = uvs[index+4]* strip.texture.width;
  6175. var v0 = uvs[index+1]* strip.texture.height, v1 = uvs[index+3] * strip.texture.height, v2 = uvs[index+5]* strip.texture.height;
  6176. context.save();
  6177. context.beginPath();
  6178. context.moveTo(x0, y0);
  6179. context.lineTo(x1, y1);
  6180. context.lineTo(x2, y2);
  6181. context.closePath();
  6182. context.clip();
  6183. // Compute matrix transform
  6184. var delta = u0*v1 + v0*u2 + u1*v2 - v1*u2 - v0*u1 - u0*v2;
  6185. var deltaA = x0*v1 + v0*x2 + x1*v2 - v1*x2 - v0*x1 - x0*v2;
  6186. var deltaB = u0*x1 + x0*u2 + u1*x2 - x1*u2 - x0*u1 - u0*x2;
  6187. var deltaC = u0*v1*x2 + v0*x1*u2 + x0*u1*v2 - x0*v1*u2 - v0*u1*x2 - u0*x1*v2;
  6188. var deltaD = y0*v1 + v0*y2 + y1*v2 - v1*y2 - v0*y1 - y0*v2;
  6189. var deltaE = u0*y1 + y0*u2 + u1*y2 - y1*u2 - y0*u1 - u0*y2;
  6190. var deltaF = u0*v1*y2 + v0*y1*u2 + y0*u1*v2 - y0*v1*u2 - v0*u1*y2 - u0*y1*v2;
  6191. context.transform(deltaA / delta, deltaD / delta,
  6192. deltaB / delta, deltaE / delta,
  6193. deltaC / delta, deltaF / delta);
  6194. context.drawImage(strip.texture.baseTexture.source, 0, 0);
  6195. context.restore();
  6196. }
  6197. };
  6198. /**
  6199. * Creates a Canvas element of the given size
  6200. *
  6201. * @method CanvasBuffer
  6202. * @param width {Number} the width for the newly created canvas
  6203. * @param height {Number} the height for the newly created canvas
  6204. * @static
  6205. * @private
  6206. */
  6207. PIXI.CanvasBuffer = function(width, height)
  6208. {
  6209. this.width = width;
  6210. this.height = height;
  6211. this.canvas = document.createElement( "canvas" );
  6212. this.context = this.canvas.getContext( "2d" );
  6213. this.canvas.width = width;
  6214. this.canvas.height = height;
  6215. };
  6216. /**
  6217. * Clears the canvas that was created by the CanvasBuffer class
  6218. *
  6219. * @method clear
  6220. * @private
  6221. */
  6222. PIXI.CanvasBuffer.prototype.clear = function()
  6223. {
  6224. this.context.clearRect(0,0, this.width, this.height);
  6225. };
  6226. /**
  6227. * Resizes the canvas that was created by the CanvasBuffer class to the specified width and height
  6228. *
  6229. * @method resize
  6230. * @param width {Number} the new width of the canvas
  6231. * @param height {Number} the new height of the canvas
  6232. * @private
  6233. */
  6234. PIXI.CanvasBuffer.prototype.resize = function(width, height)
  6235. {
  6236. this.width = this.canvas.width = width;
  6237. this.height = this.canvas.height = height;
  6238. };
  6239. /**
  6240. * @author Mat Groves http://matgroves.com/ @Doormat23
  6241. */
  6242. /**
  6243. * A set of functions used by the canvas renderer to draw the primitive graphics data
  6244. *
  6245. * @class CanvasGraphics
  6246. */
  6247. PIXI.CanvasGraphics = function()
  6248. {
  6249. };
  6250. /*
  6251. * Renders the graphics object
  6252. *
  6253. * @static
  6254. * @private
  6255. * @method renderGraphics
  6256. * @param graphics {Graphics} the actual graphics object to render
  6257. * @param context {Context2D} the 2d drawing method of the canvas
  6258. */
  6259. PIXI.CanvasGraphics.renderGraphics = function(graphics, context)
  6260. {
  6261. var worldAlpha = graphics.worldAlpha;
  6262. var color = '';
  6263. for (var i = 0; i < graphics.graphicsData.length; i++)
  6264. {
  6265. var data = graphics.graphicsData[i];
  6266. var points = data.points;
  6267. context.strokeStyle = color = '#' + ('00000' + ( data.lineColor | 0).toString(16)).substr(-6);
  6268. context.lineWidth = data.lineWidth;
  6269. if(data.type === PIXI.Graphics.POLY)
  6270. {
  6271. context.beginPath();
  6272. context.moveTo(points[0], points[1]);
  6273. for (var j=1; j < points.length/2; j++)
  6274. {
  6275. context.lineTo(points[j * 2], points[j * 2 + 1]);
  6276. }
  6277. // if the first and last point are the same close the path - much neater :)
  6278. if(points[0] === points[points.length-2] && points[1] === points[points.length-1])
  6279. {
  6280. context.closePath();
  6281. }
  6282. if(data.fill)
  6283. {
  6284. context.globalAlpha = data.fillAlpha * worldAlpha;
  6285. context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6);
  6286. context.fill();
  6287. }
  6288. if(data.lineWidth)
  6289. {
  6290. context.globalAlpha = data.lineAlpha * worldAlpha;
  6291. context.stroke();
  6292. }
  6293. }
  6294. else if(data.type === PIXI.Graphics.RECT)
  6295. {
  6296. if(data.fillColor || data.fillColor === 0)
  6297. {
  6298. context.globalAlpha = data.fillAlpha * worldAlpha;
  6299. context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6);
  6300. context.fillRect(points[0], points[1], points[2], points[3]);
  6301. }
  6302. if(data.lineWidth)
  6303. {
  6304. context.globalAlpha = data.lineAlpha * worldAlpha;
  6305. context.strokeRect(points[0], points[1], points[2], points[3]);
  6306. }
  6307. }
  6308. else if(data.type === PIXI.Graphics.CIRC)
  6309. {
  6310. // TODO - need to be Undefined!
  6311. context.beginPath();
  6312. context.arc(points[0], points[1], points[2],0,2*Math.PI);
  6313. context.closePath();
  6314. if(data.fill)
  6315. {
  6316. context.globalAlpha = data.fillAlpha * worldAlpha;
  6317. context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6);
  6318. context.fill();
  6319. }
  6320. if(data.lineWidth)
  6321. {
  6322. context.globalAlpha = data.lineAlpha * worldAlpha;
  6323. context.stroke();
  6324. }
  6325. }
  6326. else if(data.type === PIXI.Graphics.ELIP)
  6327. {
  6328. // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
  6329. var ellipseData = data.points;
  6330. var w = ellipseData[2] * 2;
  6331. var h = ellipseData[3] * 2;
  6332. var x = ellipseData[0] - w/2;
  6333. var y = ellipseData[1] - h/2;
  6334. context.beginPath();
  6335. var kappa = 0.5522848,
  6336. ox = (w / 2) * kappa, // control point offset horizontal
  6337. oy = (h / 2) * kappa, // control point offset vertical
  6338. xe = x + w, // x-end
  6339. ye = y + h, // y-end
  6340. xm = x + w / 2, // x-middle
  6341. ym = y + h / 2; // y-middle
  6342. context.moveTo(x, ym);
  6343. context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  6344. context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  6345. context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  6346. context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  6347. context.closePath();
  6348. if(data.fill)
  6349. {
  6350. context.globalAlpha = data.fillAlpha * worldAlpha;
  6351. context.fillStyle = color = '#' + ('00000' + ( data.fillColor | 0).toString(16)).substr(-6);
  6352. context.fill();
  6353. }
  6354. if(data.lineWidth)
  6355. {
  6356. context.globalAlpha = data.lineAlpha * worldAlpha;
  6357. context.stroke();
  6358. }
  6359. }
  6360. }
  6361. };
  6362. /*
  6363. * Renders a graphics mask
  6364. *
  6365. * @static
  6366. * @private
  6367. * @method renderGraphicsMask
  6368. * @param graphics {Graphics} the graphics which will be used as a mask
  6369. * @param context {Context2D} the context 2d method of the canvas
  6370. */
  6371. PIXI.CanvasGraphics.renderGraphicsMask = function(graphics, context)
  6372. {
  6373. var len = graphics.graphicsData.length;
  6374. if(len === 0) return;
  6375. if(len > 1)
  6376. {
  6377. len = 1;
  6378. window.console.log('Pixi.js warning: masks in canvas can only mask using the first path in the graphics object');
  6379. }
  6380. for (var i = 0; i < 1; i++)
  6381. {
  6382. var data = graphics.graphicsData[i];
  6383. var points = data.points;
  6384. if(data.type === PIXI.Graphics.POLY)
  6385. {
  6386. context.beginPath();
  6387. context.moveTo(points[0], points[1]);
  6388. for (var j=1; j < points.length/2; j++)
  6389. {
  6390. context.lineTo(points[j * 2], points[j * 2 + 1]);
  6391. }
  6392. // if the first and last point are the same close the path - much neater :)
  6393. if(points[0] === points[points.length-2] && points[1] === points[points.length-1])
  6394. {
  6395. context.closePath();
  6396. }
  6397. }
  6398. else if(data.type === PIXI.Graphics.RECT)
  6399. {
  6400. context.beginPath();
  6401. context.rect(points[0], points[1], points[2], points[3]);
  6402. context.closePath();
  6403. }
  6404. else if(data.type === PIXI.Graphics.CIRC)
  6405. {
  6406. // TODO - need to be Undefined!
  6407. context.beginPath();
  6408. context.arc(points[0], points[1], points[2],0,2*Math.PI);
  6409. context.closePath();
  6410. }
  6411. else if(data.type === PIXI.Graphics.ELIP)
  6412. {
  6413. // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
  6414. var ellipseData = data.points;
  6415. var w = ellipseData[2] * 2;
  6416. var h = ellipseData[3] * 2;
  6417. var x = ellipseData[0] - w/2;
  6418. var y = ellipseData[1] - h/2;
  6419. context.beginPath();
  6420. var kappa = 0.5522848,
  6421. ox = (w / 2) * kappa, // control point offset horizontal
  6422. oy = (h / 2) * kappa, // control point offset vertical
  6423. xe = x + w, // x-end
  6424. ye = y + h, // y-end
  6425. xm = x + w / 2, // x-middle
  6426. ym = y + h / 2; // y-middle
  6427. context.moveTo(x, ym);
  6428. context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  6429. context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  6430. context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  6431. context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  6432. context.closePath();
  6433. }
  6434. }
  6435. };
  6436. /**
  6437. * @author Mat Groves http://matgroves.com/ @Doormat23
  6438. */
  6439. /**
  6440. * The Graphics class contains a set of methods that you can use to create primitive shapes and lines.
  6441. * It is important to know that with the webGL renderer only simple polygons can be filled at this stage
  6442. * Complex polygons will not be filled. Heres an example of a complex polygon: http://www.goodboydigital.com/wp-content/uploads/2013/06/complexPolygon.png
  6443. *
  6444. * @class Graphics
  6445. * @extends DisplayObjectContainer
  6446. * @constructor
  6447. */
  6448. PIXI.Graphics = function()
  6449. {
  6450. PIXI.DisplayObjectContainer.call( this );
  6451. this.renderable = true;
  6452. /**
  6453. * The alpha of the fill of this graphics object
  6454. *
  6455. * @property fillAlpha
  6456. * @type Number
  6457. */
  6458. this.fillAlpha = 1;
  6459. /**
  6460. * The width of any lines drawn
  6461. *
  6462. * @property lineWidth
  6463. * @type Number
  6464. */
  6465. this.lineWidth = 0;
  6466. /**
  6467. * The color of any lines drawn
  6468. *
  6469. * @property lineColor
  6470. * @type String
  6471. */
  6472. this.lineColor = "black";
  6473. /**
  6474. * Graphics data
  6475. *
  6476. * @property graphicsData
  6477. * @type Array
  6478. * @private
  6479. */
  6480. this.graphicsData = [];
  6481. /**
  6482. * The tint applied to the graphic shape. This is a hex value
  6483. *
  6484. * @property tint
  6485. * @type Number
  6486. * @default 0xFFFFFF
  6487. */
  6488. this.tint = 0xFFFFFF;// * Math.random();
  6489. /**
  6490. * The blend mode to be applied to the graphic shape
  6491. *
  6492. * @property blendMode
  6493. * @type Number
  6494. * @default PIXI.blendModes.NORMAL;
  6495. */
  6496. this.blendMode = PIXI.blendModes.NORMAL;
  6497. /**
  6498. * Current path
  6499. *
  6500. * @property currentPath
  6501. * @type Object
  6502. * @private
  6503. */
  6504. this.currentPath = {points:[]};
  6505. /**
  6506. * Array containing some WebGL-related properties used by the WebGL renderer
  6507. *
  6508. * @property _webGL
  6509. * @type Array
  6510. * @private
  6511. */
  6512. this._webGL = [];
  6513. /**
  6514. * Whether this shape is being used as a mask
  6515. *
  6516. * @property isMask
  6517. * @type isMask
  6518. */
  6519. this.isMask = false;
  6520. /**
  6521. * The bounds of the graphic shape as rectangle object
  6522. *
  6523. * @property bounds
  6524. * @type Rectangle
  6525. */
  6526. this.bounds = null;
  6527. /**
  6528. * the bounds' padding used for bounds calculation
  6529. *
  6530. * @property bounds
  6531. * @type Number
  6532. */
  6533. this.boundsPadding = 10;
  6534. };
  6535. // constructor
  6536. PIXI.Graphics.prototype = Object.create( PIXI.DisplayObjectContainer.prototype );
  6537. PIXI.Graphics.prototype.constructor = PIXI.Graphics;
  6538. /**
  6539. * If cacheAsBitmap is true the graphics object will then be rendered as if it was a sprite.
  6540. * This is useful if your graphics element does not change often as it will speed up the rendering of the object
  6541. * It is also usful as the graphics object will always be antialiased because it will be rendered using canvas
  6542. * Not recommended if you are constanly redrawing the graphics element.
  6543. *
  6544. * @property cacheAsBitmap
  6545. * @default false
  6546. * @type Boolean
  6547. * @private
  6548. */
  6549. Object.defineProperty(PIXI.Graphics.prototype, "cacheAsBitmap", {
  6550. get: function() {
  6551. return this._cacheAsBitmap;
  6552. },
  6553. set: function(value) {
  6554. this._cacheAsBitmap = value;
  6555. if(this._cacheAsBitmap)
  6556. {
  6557. this._generateCachedSprite();
  6558. }
  6559. else
  6560. {
  6561. this.destroyCachedSprite();
  6562. this.dirty = true;
  6563. }
  6564. }
  6565. });
  6566. /**
  6567. * Specifies the line style used for subsequent calls to Graphics methods such as the lineTo() method or the drawCircle() method.
  6568. *
  6569. * @method lineStyle
  6570. * @param lineWidth {Number} width of the line to draw, will update the object's stored style
  6571. * @param color {Number} color of the line to draw, will update the object's stored style
  6572. * @param alpha {Number} alpha of the line to draw, will update the object's stored style
  6573. */
  6574. PIXI.Graphics.prototype.lineStyle = function(lineWidth, color, alpha)
  6575. {
  6576. if (!this.currentPath.points.length) this.graphicsData.pop();
  6577. this.lineWidth = lineWidth || 0;
  6578. this.lineColor = color || 0;
  6579. this.lineAlpha = (arguments.length < 3) ? 1 : alpha;
  6580. this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
  6581. fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY};
  6582. this.graphicsData.push(this.currentPath);
  6583. return this;
  6584. };
  6585. /**
  6586. * Moves the current drawing position to (x, y).
  6587. *
  6588. * @method moveTo
  6589. * @param x {Number} the X coordinate to move to
  6590. * @param y {Number} the Y coordinate to move to
  6591. */
  6592. PIXI.Graphics.prototype.moveTo = function(x, y)
  6593. {
  6594. if (!this.currentPath.points.length) this.graphicsData.pop();
  6595. this.currentPath = this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
  6596. fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling, points:[], type:PIXI.Graphics.POLY};
  6597. this.currentPath.points.push(x, y);
  6598. this.graphicsData.push(this.currentPath);
  6599. return this;
  6600. };
  6601. /**
  6602. * Draws a line using the current line style from the current drawing position to (x, y);
  6603. * the current drawing position is then set to (x, y).
  6604. *
  6605. * @method lineTo
  6606. * @param x {Number} the X coordinate to draw to
  6607. * @param y {Number} the Y coordinate to draw to
  6608. */
  6609. PIXI.Graphics.prototype.lineTo = function(x, y)
  6610. {
  6611. this.currentPath.points.push(x, y);
  6612. this.dirty = true;
  6613. return this;
  6614. };
  6615. /**
  6616. * Specifies a simple one-color fill that subsequent calls to other Graphics methods
  6617. * (such as lineTo() or drawCircle()) use when drawing.
  6618. *
  6619. * @method beginFill
  6620. * @param color {Number} the color of the fill
  6621. * @param alpha {Number} the alpha of the fill
  6622. */
  6623. PIXI.Graphics.prototype.beginFill = function(color, alpha)
  6624. {
  6625. this.filling = true;
  6626. this.fillColor = color || 0;
  6627. this.fillAlpha = (arguments.length < 2) ? 1 : alpha;
  6628. return this;
  6629. };
  6630. /**
  6631. * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method.
  6632. *
  6633. * @method endFill
  6634. */
  6635. PIXI.Graphics.prototype.endFill = function()
  6636. {
  6637. this.filling = false;
  6638. this.fillColor = null;
  6639. this.fillAlpha = 1;
  6640. return this;
  6641. };
  6642. /**
  6643. * @method drawRect
  6644. *
  6645. * @param x {Number} The X coord of the top-left of the rectangle
  6646. * @param y {Number} The Y coord of the top-left of the rectangle
  6647. * @param width {Number} The width of the rectangle
  6648. * @param height {Number} The height of the rectangle
  6649. */
  6650. PIXI.Graphics.prototype.drawRect = function( x, y, width, height )
  6651. {
  6652. if (!this.currentPath.points.length) this.graphicsData.pop();
  6653. this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
  6654. fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling,
  6655. points:[x, y, width, height], type:PIXI.Graphics.RECT};
  6656. this.graphicsData.push(this.currentPath);
  6657. this.dirty = true;
  6658. return this;
  6659. };
  6660. /**
  6661. * Draws a circle.
  6662. *
  6663. * @method drawCircle
  6664. * @param x {Number} The X coordinate of the center of the circle
  6665. * @param y {Number} The Y coordinate of the center of the circle
  6666. * @param radius {Number} The radius of the circle
  6667. */
  6668. PIXI.Graphics.prototype.drawCircle = function( x, y, radius)
  6669. {
  6670. if (!this.currentPath.points.length) this.graphicsData.pop();
  6671. this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
  6672. fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling,
  6673. points:[x, y, radius, radius], type:PIXI.Graphics.CIRC};
  6674. this.graphicsData.push(this.currentPath);
  6675. this.dirty = true;
  6676. return this;
  6677. };
  6678. /**
  6679. * Draws an ellipse.
  6680. *
  6681. * @method drawEllipse
  6682. * @param x {Number} The X coordinate of the upper-left corner of the framing rectangle of this ellipse
  6683. * @param y {Number} The Y coordinate of the upper-left corner of the framing rectangle of this ellipse
  6684. * @param width {Number} The width of the ellipse
  6685. * @param height {Number} The height of the ellipse
  6686. */
  6687. PIXI.Graphics.prototype.drawEllipse = function( x, y, width, height)
  6688. {
  6689. if (!this.currentPath.points.length) this.graphicsData.pop();
  6690. this.currentPath = {lineWidth:this.lineWidth, lineColor:this.lineColor, lineAlpha:this.lineAlpha,
  6691. fillColor:this.fillColor, fillAlpha:this.fillAlpha, fill:this.filling,
  6692. points:[x, y, width, height], type:PIXI.Graphics.ELIP};
  6693. this.graphicsData.push(this.currentPath);
  6694. this.dirty = true;
  6695. return this;
  6696. };
  6697. /**
  6698. * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings.
  6699. *
  6700. * @method clear
  6701. */
  6702. PIXI.Graphics.prototype.clear = function()
  6703. {
  6704. this.lineWidth = 0;
  6705. this.filling = false;
  6706. this.dirty = true;
  6707. this.clearDirty = true;
  6708. this.graphicsData = [];
  6709. this.bounds = null; //new PIXI.Rectangle();
  6710. return this;
  6711. };
  6712. /**
  6713. * Useful function that returns a texture of the graphics object that can then be used to create sprites
  6714. * This can be quite useful if your geometry is complicated and needs to be reused multiple times.
  6715. *
  6716. * @method generateTexture
  6717. * @return {Texture} a texture of the graphics object
  6718. */
  6719. PIXI.Graphics.prototype.generateTexture = function()
  6720. {
  6721. var bounds = this.getBounds();
  6722. var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height);
  6723. var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
  6724. canvasBuffer.context.translate(-bounds.x,-bounds.y);
  6725. PIXI.CanvasGraphics.renderGraphics(this, canvasBuffer.context);
  6726. return texture;
  6727. };
  6728. /**
  6729. * Renders the object using the WebGL renderer
  6730. *
  6731. * @method _renderWebGL
  6732. * @param renderSession {RenderSession}
  6733. * @private
  6734. */
  6735. PIXI.Graphics.prototype._renderWebGL = function(renderSession)
  6736. {
  6737. // if the sprite is not visible or the alpha is 0 then no need to render this element
  6738. if(this.visible === false || this.alpha === 0 || this.isMask === true)return;
  6739. if(this._cacheAsBitmap)
  6740. {
  6741. if(this.dirty)
  6742. {
  6743. this._generateCachedSprite();
  6744. // we will also need to update the texture on the gpu too!
  6745. PIXI.updateWebGLTexture(this._cachedSprite.texture.baseTexture, renderSession.gl);
  6746. this.dirty = false;
  6747. }
  6748. this._cachedSprite.alpha = this.alpha;
  6749. PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession);
  6750. return;
  6751. }
  6752. else
  6753. {
  6754. renderSession.spriteBatch.stop();
  6755. if(this._mask)renderSession.maskManager.pushMask(this.mask, renderSession);
  6756. if(this._filters)renderSession.filterManager.pushFilter(this._filterBlock);
  6757. // check blend mode
  6758. if(this.blendMode !== renderSession.spriteBatch.currentBlendMode)
  6759. {
  6760. renderSession.spriteBatch.currentBlendMode = this.blendMode;
  6761. var blendModeWebGL = PIXI.blendModesWebGL[renderSession.spriteBatch.currentBlendMode];
  6762. renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
  6763. }
  6764. PIXI.WebGLGraphics.renderGraphics(this, renderSession);
  6765. // only render if it has children!
  6766. if(this.children.length)
  6767. {
  6768. renderSession.spriteBatch.start();
  6769. // simple render children!
  6770. for(var i=0, j=this.children.length; i<j; i++)
  6771. {
  6772. this.children[i]._renderWebGL(renderSession);
  6773. }
  6774. renderSession.spriteBatch.stop();
  6775. }
  6776. if(this._filters)renderSession.filterManager.popFilter();
  6777. if(this._mask)renderSession.maskManager.popMask(renderSession);
  6778. renderSession.drawCount++;
  6779. renderSession.spriteBatch.start();
  6780. }
  6781. };
  6782. /**
  6783. * Renders the object using the Canvas renderer
  6784. *
  6785. * @method _renderCanvas
  6786. * @param renderSession {RenderSession}
  6787. * @private
  6788. */
  6789. PIXI.Graphics.prototype._renderCanvas = function(renderSession)
  6790. {
  6791. // if the sprite is not visible or the alpha is 0 then no need to render this element
  6792. if(this.visible === false || this.alpha === 0 || this.isMask === true)return;
  6793. var context = renderSession.context;
  6794. var transform = this.worldTransform;
  6795. if(this.blendMode !== renderSession.currentBlendMode)
  6796. {
  6797. renderSession.currentBlendMode = this.blendMode;
  6798. context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
  6799. }
  6800. context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty);
  6801. PIXI.CanvasGraphics.renderGraphics(this, context);
  6802. // simple render children!
  6803. for(var i=0, j=this.children.length; i<j; i++)
  6804. {
  6805. this.children[i]._renderCanvas(renderSession);
  6806. }
  6807. };
  6808. /**
  6809. * Retrieves the bounds of the graphic shape as a rectangle object
  6810. *
  6811. * @method getBounds
  6812. * @return {Rectangle} the rectangular bounding area
  6813. */
  6814. PIXI.Graphics.prototype.getBounds = function( matrix )
  6815. {
  6816. if(!this.bounds)this.updateBounds();
  6817. var w0 = this.bounds.x;
  6818. var w1 = this.bounds.width + this.bounds.x;
  6819. var h0 = this.bounds.y;
  6820. var h1 = this.bounds.height + this.bounds.y;
  6821. var worldTransform = matrix || this.worldTransform;
  6822. var a = worldTransform.a;
  6823. var b = worldTransform.c;
  6824. var c = worldTransform.b;
  6825. var d = worldTransform.d;
  6826. var tx = worldTransform.tx;
  6827. var ty = worldTransform.ty;
  6828. var x1 = a * w1 + c * h1 + tx;
  6829. var y1 = d * h1 + b * w1 + ty;
  6830. var x2 = a * w0 + c * h1 + tx;
  6831. var y2 = d * h1 + b * w0 + ty;
  6832. var x3 = a * w0 + c * h0 + tx;
  6833. var y3 = d * h0 + b * w0 + ty;
  6834. var x4 = a * w1 + c * h0 + tx;
  6835. var y4 = d * h0 + b * w1 + ty;
  6836. var maxX = -Infinity;
  6837. var maxY = -Infinity;
  6838. var minX = Infinity;
  6839. var minY = Infinity;
  6840. minX = x1 < minX ? x1 : minX;
  6841. minX = x2 < minX ? x2 : minX;
  6842. minX = x3 < minX ? x3 : minX;
  6843. minX = x4 < minX ? x4 : minX;
  6844. minY = y1 < minY ? y1 : minY;
  6845. minY = y2 < minY ? y2 : minY;
  6846. minY = y3 < minY ? y3 : minY;
  6847. minY = y4 < minY ? y4 : minY;
  6848. maxX = x1 > maxX ? x1 : maxX;
  6849. maxX = x2 > maxX ? x2 : maxX;
  6850. maxX = x3 > maxX ? x3 : maxX;
  6851. maxX = x4 > maxX ? x4 : maxX;
  6852. maxY = y1 > maxY ? y1 : maxY;
  6853. maxY = y2 > maxY ? y2 : maxY;
  6854. maxY = y3 > maxY ? y3 : maxY;
  6855. maxY = y4 > maxY ? y4 : maxY;
  6856. var bounds = this._bounds;
  6857. bounds.x = minX;
  6858. bounds.width = maxX - minX;
  6859. bounds.y = minY;
  6860. bounds.height = maxY - minY;
  6861. return bounds;
  6862. };
  6863. /**
  6864. * Update the bounds of the object
  6865. *
  6866. * @method updateBounds
  6867. */
  6868. PIXI.Graphics.prototype.updateBounds = function()
  6869. {
  6870. var minX = Infinity;
  6871. var maxX = -Infinity;
  6872. var minY = Infinity;
  6873. var maxY = -Infinity;
  6874. var points, x, y, w, h;
  6875. for (var i = 0; i < this.graphicsData.length; i++) {
  6876. var data = this.graphicsData[i];
  6877. var type = data.type;
  6878. var lineWidth = data.lineWidth;
  6879. points = data.points;
  6880. if(type === PIXI.Graphics.RECT)
  6881. {
  6882. x = points[0] - lineWidth/2;
  6883. y = points[1] - lineWidth/2;
  6884. w = points[2] + lineWidth;
  6885. h = points[3] + lineWidth;
  6886. minX = x < minX ? x : minX;
  6887. maxX = x + w > maxX ? x + w : maxX;
  6888. minY = y < minY ? x : minY;
  6889. maxY = y + h > maxY ? y + h : maxY;
  6890. }
  6891. else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP)
  6892. {
  6893. x = points[0];
  6894. y = points[1];
  6895. w = points[2] + lineWidth/2;
  6896. h = points[3] + lineWidth/2;
  6897. minX = x - w < minX ? x - w : minX;
  6898. maxX = x + w > maxX ? x + w : maxX;
  6899. minY = y - h < minY ? y - h : minY;
  6900. maxY = y + h > maxY ? y + h : maxY;
  6901. }
  6902. else
  6903. {
  6904. // POLY
  6905. for (var j = 0; j < points.length; j+=2)
  6906. {
  6907. x = points[j];
  6908. y = points[j+1];
  6909. minX = x-lineWidth < minX ? x-lineWidth : minX;
  6910. maxX = x+lineWidth > maxX ? x+lineWidth : maxX;
  6911. minY = y-lineWidth < minY ? y-lineWidth : minY;
  6912. maxY = y+lineWidth > maxY ? y+lineWidth : maxY;
  6913. }
  6914. }
  6915. }
  6916. var padding = this.boundsPadding;
  6917. this.bounds = new PIXI.Rectangle(minX - padding, minY - padding, (maxX - minX) + padding * 2, (maxY - minY) + padding * 2);
  6918. };
  6919. /**
  6920. * Generates the cached sprite when the sprite has cacheAsBitmap = true
  6921. *
  6922. * @method _generateCachedSprite
  6923. * @private
  6924. */
  6925. PIXI.Graphics.prototype._generateCachedSprite = function()
  6926. {
  6927. var bounds = this.getLocalBounds();
  6928. if(!this._cachedSprite)
  6929. {
  6930. var canvasBuffer = new PIXI.CanvasBuffer(bounds.width, bounds.height);
  6931. var texture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
  6932. this._cachedSprite = new PIXI.Sprite(texture);
  6933. this._cachedSprite.buffer = canvasBuffer;
  6934. this._cachedSprite.worldTransform = this.worldTransform;
  6935. }
  6936. else
  6937. {
  6938. this._cachedSprite.buffer.resize(bounds.width, bounds.height);
  6939. }
  6940. // leverage the anchor to account for the offset of the element
  6941. this._cachedSprite.anchor.x = -( bounds.x / bounds.width );
  6942. this._cachedSprite.anchor.y = -( bounds.y / bounds.height );
  6943. // this._cachedSprite.buffer.context.save();
  6944. this._cachedSprite.buffer.context.translate(-bounds.x,-bounds.y);
  6945. PIXI.CanvasGraphics.renderGraphics(this, this._cachedSprite.buffer.context);
  6946. this._cachedSprite.alpha = this.alpha;
  6947. // this._cachedSprite.buffer.context.restore();
  6948. };
  6949. PIXI.Graphics.prototype.destroyCachedSprite = function()
  6950. {
  6951. this._cachedSprite.texture.destroy(true);
  6952. // let the gc collect the unused sprite
  6953. // TODO could be object pooled!
  6954. this._cachedSprite = null;
  6955. };
  6956. // SOME TYPES:
  6957. PIXI.Graphics.POLY = 0;
  6958. PIXI.Graphics.RECT = 1;
  6959. PIXI.Graphics.CIRC = 2;
  6960. PIXI.Graphics.ELIP = 3;
  6961. /**
  6962. * @author Mat Groves http://matgroves.com/
  6963. */
  6964. /**
  6965. * A tiling sprite is a fast way of rendering a tiling image
  6966. *
  6967. * @class TilingSprite
  6968. * @extends Sprite
  6969. * @constructor
  6970. * @param texture {Texture} the texture of the tiling sprite
  6971. * @param width {Number} the width of the tiling sprite
  6972. * @param height {Number} the height of the tiling sprite
  6973. */
  6974. PIXI.TilingSprite = function(texture, width, height)
  6975. {
  6976. PIXI.Sprite.call( this, texture);
  6977. /**
  6978. * The with of the tiling sprite
  6979. *
  6980. * @property width
  6981. * @type Number
  6982. */
  6983. this.width = width || 100;
  6984. /**
  6985. * The height of the tiling sprite
  6986. *
  6987. * @property height
  6988. * @type Number
  6989. */
  6990. this.height = height || 100;
  6991. /**
  6992. * The scaling of the image that is being tiled
  6993. *
  6994. * @property tileScale
  6995. * @type Point
  6996. */
  6997. this.tileScale = new PIXI.Point(1,1);
  6998. /**
  6999. * A point that represents the scale of the texture object
  7000. *
  7001. * @property tileScaleOffset
  7002. * @type Point
  7003. */
  7004. this.tileScaleOffset = new PIXI.Point(1,1);
  7005. /**
  7006. * The offset position of the image that is being tiled
  7007. *
  7008. * @property tilePosition
  7009. * @type Point
  7010. */
  7011. this.tilePosition = new PIXI.Point(0,0);
  7012. /**
  7013. * Whether this sprite is renderable or not
  7014. *
  7015. * @property renderable
  7016. * @type Boolean
  7017. * @default true
  7018. */
  7019. this.renderable = true;
  7020. /**
  7021. * The tint applied to the sprite. This is a hex value
  7022. *
  7023. * @property tint
  7024. * @type Number
  7025. * @default 0xFFFFFF
  7026. */
  7027. this.tint = 0xFFFFFF;
  7028. /**
  7029. * The blend mode to be applied to the sprite
  7030. *
  7031. * @property blendMode
  7032. * @type Number
  7033. * @default PIXI.blendModes.NORMAL;
  7034. */
  7035. this.blendMode = PIXI.blendModes.NORMAL;
  7036. };
  7037. // constructor
  7038. PIXI.TilingSprite.prototype = Object.create(PIXI.Sprite.prototype);
  7039. PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;
  7040. /**
  7041. * The width of the sprite, setting this will actually modify the scale to achieve the value set
  7042. *
  7043. * @property width
  7044. * @type Number
  7045. */
  7046. Object.defineProperty(PIXI.TilingSprite.prototype, 'width', {
  7047. get: function() {
  7048. return this._width;
  7049. },
  7050. set: function(value) {
  7051. this._width = value;
  7052. }
  7053. });
  7054. /**
  7055. * The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
  7056. *
  7057. * @property height
  7058. * @type Number
  7059. */
  7060. Object.defineProperty(PIXI.TilingSprite.prototype, 'height', {
  7061. get: function() {
  7062. return this._height;
  7063. },
  7064. set: function(value) {
  7065. this._height = value;
  7066. }
  7067. });
  7068. /**
  7069. * When the texture is updated, this event will be fired to update the scale and frame
  7070. *
  7071. * @method onTextureUpdate
  7072. * @param event
  7073. * @private
  7074. */
  7075. PIXI.TilingSprite.prototype.onTextureUpdate = function()
  7076. {
  7077. this.updateFrame = true;
  7078. };
  7079. PIXI.TilingSprite.prototype.setTexture = function(texture)
  7080. {
  7081. if(this.texture === texture)return;
  7082. this.texture = texture;
  7083. this.refreshTexture = true;
  7084. /*
  7085. if(this.tilingTexture)
  7086. {
  7087. this.generateTilingTexture(true);
  7088. }
  7089. */
  7090. /*
  7091. // stop current texture;
  7092. if(this.texture.baseTexture !== texture.baseTexture)
  7093. {
  7094. this.textureChange = true;
  7095. this.texture = texture;
  7096. }
  7097. else
  7098. {
  7099. this.texture = texture;
  7100. }
  7101. this.updateFrame = true;*/
  7102. this.cachedTint = 0xFFFFFF;
  7103. };
  7104. /**
  7105. * Renders the object using the WebGL renderer
  7106. *
  7107. * @method _renderWebGL
  7108. * @param renderSession {RenderSession}
  7109. * @private
  7110. */
  7111. PIXI.TilingSprite.prototype._renderWebGL = function(renderSession)
  7112. {
  7113. if(this.visible === false || this.alpha === 0)return;
  7114. var i,j;
  7115. if(this.mask)
  7116. {
  7117. renderSession.spriteBatch.stop();
  7118. renderSession.maskManager.pushMask(this.mask, renderSession);
  7119. renderSession.spriteBatch.start();
  7120. }
  7121. if(this.filters)
  7122. {
  7123. renderSession.spriteBatch.flush();
  7124. renderSession.filterManager.pushFilter(this._filterBlock);
  7125. }
  7126. if(!this.tilingTexture || this.refreshTexture)
  7127. {
  7128. this.generateTilingTexture(true);
  7129. if(this.tilingTexture && this.tilingTexture.needsUpdate)
  7130. {
  7131. //TODO - tweaking
  7132. PIXI.updateWebGLTexture(this.tilingTexture.baseTexture, renderSession.gl);
  7133. this.tilingTexture.needsUpdate = false;
  7134. // this.tilingTexture._uvs = null;
  7135. }
  7136. }
  7137. else renderSession.spriteBatch.renderTilingSprite(this);
  7138. // simple render children!
  7139. for(i=0,j=this.children.length; i<j; i++)
  7140. {
  7141. this.children[i]._renderWebGL(renderSession);
  7142. }
  7143. renderSession.spriteBatch.stop();
  7144. if(this.filters)renderSession.filterManager.popFilter();
  7145. if(this.mask)renderSession.maskManager.popMask(renderSession);
  7146. renderSession.spriteBatch.start();
  7147. };
  7148. /**
  7149. * Renders the object using the Canvas renderer
  7150. *
  7151. * @method _renderCanvas
  7152. * @param renderSession {RenderSession}
  7153. * @private
  7154. */
  7155. PIXI.TilingSprite.prototype._renderCanvas = function(renderSession)
  7156. {
  7157. if(this.visible === false || this.alpha === 0)return;
  7158. var context = renderSession.context;
  7159. if(this._mask)
  7160. {
  7161. renderSession.maskManager.pushMask(this._mask, context);
  7162. }
  7163. context.globalAlpha = this.worldAlpha;
  7164. var transform = this.worldTransform;
  7165. // allow for trimming
  7166. //(this.anchor.x) * -frame.width,
  7167. // (this.anchor.y) * -frame.height,
  7168. context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx , transform.ty);
  7169. if(!this.__tilePattern || this.refreshTexture)
  7170. {
  7171. this.generateTilingTexture(false);
  7172. if(this.tilingTexture)
  7173. {
  7174. this.__tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
  7175. }
  7176. else
  7177. {
  7178. return;
  7179. }
  7180. }
  7181. // check blend mode
  7182. if(this.blendMode !== renderSession.currentBlendMode)
  7183. {
  7184. renderSession.currentBlendMode = this.blendMode;
  7185. context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
  7186. }
  7187. context.beginPath();
  7188. var tilePosition = this.tilePosition;
  7189. var tileScale = this.tileScale;
  7190. tilePosition.x %= this.tilingTexture.baseTexture.width;
  7191. tilePosition.y %= this.tilingTexture.baseTexture.height;
  7192. // offset
  7193. context.scale(tileScale.x,tileScale.y);
  7194. context.translate(tilePosition.x, tilePosition.y);
  7195. context.fillStyle = this.__tilePattern;
  7196. // make sure to account for the anchor point..
  7197. context.fillRect(-tilePosition.x + (this.anchor.x * -this._width),-tilePosition.y + (this.anchor.y * -this._height),
  7198. this._width / tileScale.x, this._height / tileScale.y);
  7199. context.scale(1/tileScale.x, 1/tileScale.y);
  7200. context.translate(-tilePosition.x, -tilePosition.y);
  7201. context.closePath();
  7202. if(this._mask)
  7203. {
  7204. renderSession.maskManager.popMask(renderSession.context);
  7205. }
  7206. };
  7207. /**
  7208. * Returns the framing rectangle of the sprite as a PIXI.Rectangle object
  7209. *
  7210. * @method getBounds
  7211. * @return {Rectangle} the framing rectangle
  7212. */
  7213. PIXI.TilingSprite.prototype.getBounds = function()
  7214. {
  7215. var width = this._width;
  7216. var height = this._height;
  7217. var w0 = width * (1-this.anchor.x);
  7218. var w1 = width * -this.anchor.x;
  7219. var h0 = height * (1-this.anchor.y);
  7220. var h1 = height * -this.anchor.y;
  7221. var worldTransform = this.worldTransform;
  7222. var a = worldTransform.a;
  7223. var b = worldTransform.c;
  7224. var c = worldTransform.b;
  7225. var d = worldTransform.d;
  7226. var tx = worldTransform.tx;
  7227. var ty = worldTransform.ty;
  7228. var x1 = a * w1 + c * h1 + tx;
  7229. var y1 = d * h1 + b * w1 + ty;
  7230. var x2 = a * w0 + c * h1 + tx;
  7231. var y2 = d * h1 + b * w0 + ty;
  7232. var x3 = a * w0 + c * h0 + tx;
  7233. var y3 = d * h0 + b * w0 + ty;
  7234. var x4 = a * w1 + c * h0 + tx;
  7235. var y4 = d * h0 + b * w1 + ty;
  7236. var maxX = -Infinity;
  7237. var maxY = -Infinity;
  7238. var minX = Infinity;
  7239. var minY = Infinity;
  7240. minX = x1 < minX ? x1 : minX;
  7241. minX = x2 < minX ? x2 : minX;
  7242. minX = x3 < minX ? x3 : minX;
  7243. minX = x4 < minX ? x4 : minX;
  7244. minY = y1 < minY ? y1 : minY;
  7245. minY = y2 < minY ? y2 : minY;
  7246. minY = y3 < minY ? y3 : minY;
  7247. minY = y4 < minY ? y4 : minY;
  7248. maxX = x1 > maxX ? x1 : maxX;
  7249. maxX = x2 > maxX ? x2 : maxX;
  7250. maxX = x3 > maxX ? x3 : maxX;
  7251. maxX = x4 > maxX ? x4 : maxX;
  7252. maxY = y1 > maxY ? y1 : maxY;
  7253. maxY = y2 > maxY ? y2 : maxY;
  7254. maxY = y3 > maxY ? y3 : maxY;
  7255. maxY = y4 > maxY ? y4 : maxY;
  7256. var bounds = this._bounds;
  7257. bounds.x = minX;
  7258. bounds.width = maxX - minX;
  7259. bounds.y = minY;
  7260. bounds.height = maxY - minY;
  7261. // store a reference so that if this function gets called again in the render cycle we do not have to recalculate
  7262. this._currentBounds = bounds;
  7263. return bounds;
  7264. };
  7265. /**
  7266. *
  7267. * @method generateTilingTexture
  7268. *
  7269. * @param forcePowerOfTwo {Boolean} Whether we want to force the texture to be a power of two
  7270. */
  7271. PIXI.TilingSprite.prototype.generateTilingTexture = function(forcePowerOfTwo)
  7272. {
  7273. var texture = this.texture;
  7274. if(!texture.baseTexture.hasLoaded)return;
  7275. var baseTexture = texture.baseTexture;
  7276. var frame = texture.frame;
  7277. var targetWidth, targetHeight;
  7278. // check that the frame is the same size as the base texture.
  7279. var isFrame = frame.width !== baseTexture.width || frame.height !== baseTexture.height;
  7280. var newTextureRequired = false;
  7281. if(!forcePowerOfTwo)
  7282. {
  7283. if(isFrame)
  7284. {
  7285. targetWidth = frame.width;
  7286. targetHeight = frame.height;
  7287. newTextureRequired = true;
  7288. }
  7289. }
  7290. else
  7291. {
  7292. targetWidth = PIXI.getNextPowerOfTwo(frame.width);
  7293. targetHeight = PIXI.getNextPowerOfTwo(frame.height);
  7294. if(frame.width !== targetWidth && frame.height !== targetHeight)newTextureRequired = true;
  7295. }
  7296. if(newTextureRequired)
  7297. {
  7298. var canvasBuffer;
  7299. if(this.tilingTexture && this.tilingTexture.isTiling)
  7300. {
  7301. canvasBuffer = this.tilingTexture.canvasBuffer;
  7302. canvasBuffer.resize(targetWidth, targetHeight);
  7303. this.tilingTexture.baseTexture.width = targetWidth;
  7304. this.tilingTexture.baseTexture.height = targetHeight;
  7305. this.tilingTexture.needsUpdate = true;
  7306. }
  7307. else
  7308. {
  7309. canvasBuffer = new PIXI.CanvasBuffer(targetWidth, targetHeight);
  7310. this.tilingTexture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
  7311. this.tilingTexture.canvasBuffer = canvasBuffer;
  7312. this.tilingTexture.isTiling = true;
  7313. }
  7314. canvasBuffer.context.drawImage(texture.baseTexture.source,
  7315. frame.x,
  7316. frame.y,
  7317. frame.width,
  7318. frame.height,
  7319. 0,
  7320. 0,
  7321. targetWidth,
  7322. targetHeight);
  7323. this.tileScaleOffset.x = frame.width / targetWidth;
  7324. this.tileScaleOffset.y = frame.height / targetHeight;
  7325. }
  7326. else
  7327. {
  7328. //TODO - switching?
  7329. if(this.tilingTexture && this.tilingTexture.isTiling)
  7330. {
  7331. // destroy the tiling texture!
  7332. // TODO could store this somewhere?
  7333. this.tilingTexture.destroy(true);
  7334. }
  7335. this.tileScaleOffset.x = 1;
  7336. this.tileScaleOffset.y = 1;
  7337. this.tilingTexture = texture;
  7338. }
  7339. this.refreshTexture = false;
  7340. this.tilingTexture.baseTexture._powerOf2 = true;
  7341. };
  7342. /**
  7343. * @author Mat Groves http://matgroves.com/ @Doormat23
  7344. */
  7345. PIXI.BaseTextureCache = {};
  7346. PIXI.texturesToUpdate = [];
  7347. PIXI.texturesToDestroy = [];
  7348. PIXI.BaseTextureCacheIdGenerator = 0;
  7349. /**
  7350. * A texture stores the information that represents an image. All textures have a base texture
  7351. *
  7352. * @class BaseTexture
  7353. * @uses EventTarget
  7354. * @constructor
  7355. * @param source {String} the source object (image or canvas)
  7356. * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts
  7357. */
  7358. PIXI.BaseTexture = function(source, scaleMode)
  7359. {
  7360. PIXI.EventTarget.call( this );
  7361. /**
  7362. * [read-only] The width of the base texture set when the image has loaded
  7363. *
  7364. * @property width
  7365. * @type Number
  7366. * @readOnly
  7367. */
  7368. this.width = 100;
  7369. /**
  7370. * [read-only] The height of the base texture set when the image has loaded
  7371. *
  7372. * @property height
  7373. * @type Number
  7374. * @readOnly
  7375. */
  7376. this.height = 100;
  7377. /**
  7378. * The scale mode to apply when scaling this texture
  7379. * @property scaleMode
  7380. * @type PIXI.scaleModes
  7381. * @default PIXI.scaleModes.LINEAR
  7382. */
  7383. this.scaleMode = scaleMode || PIXI.scaleModes.DEFAULT;
  7384. /**
  7385. * [read-only] Describes if the base texture has loaded or not
  7386. *
  7387. * @property hasLoaded
  7388. * @type Boolean
  7389. * @readOnly
  7390. */
  7391. this.hasLoaded = false;
  7392. /**
  7393. * The source that is loaded to create the texture
  7394. *
  7395. * @property source
  7396. * @type Image
  7397. */
  7398. this.source = source;
  7399. //TODO will be used for futer pixi 1.5...
  7400. this.id = PIXI.BaseTextureCacheIdGenerator++;
  7401. // used for webGL
  7402. this._glTextures = [];
  7403. if(!source)return;
  7404. if(this.source.complete || this.source.getContext)
  7405. {
  7406. this.hasLoaded = true;
  7407. this.width = this.source.width;
  7408. this.height = this.source.height;
  7409. PIXI.texturesToUpdate.push(this);
  7410. }
  7411. else
  7412. {
  7413. var scope = this;
  7414. this.source.onload = function() {
  7415. scope.hasLoaded = true;
  7416. scope.width = scope.source.width;
  7417. scope.height = scope.source.height;
  7418. // add it to somewhere...
  7419. PIXI.texturesToUpdate.push(scope);
  7420. scope.dispatchEvent( { type: 'loaded', content: scope } );
  7421. };
  7422. }
  7423. this.imageUrl = null;
  7424. this._powerOf2 = false;
  7425. };
  7426. PIXI.BaseTexture.prototype.constructor = PIXI.BaseTexture;
  7427. /**
  7428. * Destroys this base texture
  7429. *
  7430. * @method destroy
  7431. */
  7432. PIXI.BaseTexture.prototype.destroy = function()
  7433. {
  7434. if(this.imageUrl)
  7435. {
  7436. delete PIXI.BaseTextureCache[this.imageUrl];
  7437. this.imageUrl = null;
  7438. this.source.src = null;
  7439. }
  7440. this.source = null;
  7441. PIXI.texturesToDestroy.push(this);
  7442. };
  7443. /**
  7444. * Changes the source image of the texture
  7445. *
  7446. * @method updateSourceImage
  7447. * @param newSrc {String} the path of the image
  7448. */
  7449. PIXI.BaseTexture.prototype.updateSourceImage = function(newSrc)
  7450. {
  7451. this.hasLoaded = false;
  7452. this.source.src = null;
  7453. this.source.src = newSrc;
  7454. };
  7455. /**
  7456. * Helper function that returns a base texture based on an image url
  7457. * If the image is not in the base texture cache it will be created and loaded
  7458. *
  7459. * @static
  7460. * @method fromImage
  7461. * @param imageUrl {String} The image url of the texture
  7462. * @param crossorigin {Boolean}
  7463. * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts
  7464. * @return BaseTexture
  7465. */
  7466. PIXI.BaseTexture.fromImage = function(imageUrl, crossorigin, scaleMode)
  7467. {
  7468. var baseTexture = PIXI.BaseTextureCache[imageUrl];
  7469. if(crossorigin === undefined)crossorigin = true;
  7470. if(!baseTexture)
  7471. {
  7472. // new Image() breaks tex loading in some versions of Chrome.
  7473. // See https://code.google.com/p/chromium/issues/detail?id=238071
  7474. var image = new Image();//document.createElement('img');
  7475. if (crossorigin)
  7476. {
  7477. image.crossOrigin = '';
  7478. }
  7479. image.src = imageUrl;
  7480. baseTexture = new PIXI.BaseTexture(image, scaleMode);
  7481. baseTexture.imageUrl = imageUrl;
  7482. PIXI.BaseTextureCache[imageUrl] = baseTexture;
  7483. }
  7484. return baseTexture;
  7485. };
  7486. PIXI.BaseTexture.fromCanvas = function(canvas, scaleMode)
  7487. {
  7488. if(!canvas._pixiId)
  7489. {
  7490. canvas._pixiId = 'canvas_' + PIXI.TextureCacheIdGenerator++;
  7491. }
  7492. var baseTexture = PIXI.BaseTextureCache[canvas._pixiId];
  7493. if(!baseTexture)
  7494. {
  7495. baseTexture = new PIXI.BaseTexture(canvas, scaleMode);
  7496. PIXI.BaseTextureCache[canvas._pixiId] = baseTexture;
  7497. }
  7498. return baseTexture;
  7499. };
  7500. /**
  7501. * @author Mat Groves http://matgroves.com/ @Doormat23
  7502. */
  7503. PIXI.TextureCache = {};
  7504. PIXI.FrameCache = {};
  7505. PIXI.TextureCacheIdGenerator = 0;
  7506. /**
  7507. * A texture stores the information that represents an image or part of an image. It cannot be added
  7508. * to the display list directly. To do this use PIXI.Sprite. If no frame is provided then the whole image is used
  7509. *
  7510. * @class Texture
  7511. * @uses EventTarget
  7512. * @constructor
  7513. * @param baseTexture {BaseTexture} The base texture source to create the texture from
  7514. * @param frame {Rectangle} The rectangle frame of the texture to show
  7515. */
  7516. PIXI.Texture = function(baseTexture, frame)
  7517. {
  7518. PIXI.EventTarget.call( this );
  7519. if(!frame)
  7520. {
  7521. this.noFrame = true;
  7522. frame = new PIXI.Rectangle(0,0,1,1);
  7523. }
  7524. if(baseTexture instanceof PIXI.Texture)
  7525. baseTexture = baseTexture.baseTexture;
  7526. /**
  7527. * The base texture of that this texture uses
  7528. *
  7529. * @property baseTexture
  7530. * @type BaseTexture
  7531. */
  7532. this.baseTexture = baseTexture;
  7533. /**
  7534. * The frame specifies the region of the base texture that this texture uses
  7535. *
  7536. * @property frame
  7537. * @type Rectangle
  7538. */
  7539. this.frame = frame;
  7540. /**
  7541. * The trim point
  7542. *
  7543. * @property trim
  7544. * @type Rectangle
  7545. */
  7546. this.trim = null;
  7547. this.scope = this;
  7548. this._uvs = null;
  7549. if(baseTexture.hasLoaded)
  7550. {
  7551. if(this.noFrame)frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
  7552. this.setFrame(frame);
  7553. }
  7554. else
  7555. {
  7556. var scope = this;
  7557. baseTexture.addEventListener('loaded', function(){ scope.onBaseTextureLoaded(); });
  7558. }
  7559. };
  7560. PIXI.Texture.prototype.constructor = PIXI.Texture;
  7561. /**
  7562. * Called when the base texture is loaded
  7563. *
  7564. * @method onBaseTextureLoaded
  7565. * @param event
  7566. * @private
  7567. */
  7568. PIXI.Texture.prototype.onBaseTextureLoaded = function()
  7569. {
  7570. var baseTexture = this.baseTexture;
  7571. baseTexture.removeEventListener( 'loaded', this.onLoaded );
  7572. if(this.noFrame)this.frame = new PIXI.Rectangle(0,0, baseTexture.width, baseTexture.height);
  7573. this.setFrame(this.frame);
  7574. this.scope.dispatchEvent( { type: 'update', content: this } );
  7575. };
  7576. /**
  7577. * Destroys this texture
  7578. *
  7579. * @method destroy
  7580. * @param destroyBase {Boolean} Whether to destroy the base texture as well
  7581. */
  7582. PIXI.Texture.prototype.destroy = function(destroyBase)
  7583. {
  7584. if(destroyBase) this.baseTexture.destroy();
  7585. };
  7586. /**
  7587. * Specifies the rectangle region of the baseTexture
  7588. *
  7589. * @method setFrame
  7590. * @param frame {Rectangle} The frame of the texture to set it to
  7591. */
  7592. PIXI.Texture.prototype.setFrame = function(frame)
  7593. {
  7594. this.frame = frame;
  7595. this.width = frame.width;
  7596. this.height = frame.height;
  7597. if(frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height)
  7598. {
  7599. throw new Error('Texture Error: frame does not fit inside the base Texture dimensions ' + this);
  7600. }
  7601. this.updateFrame = true;
  7602. PIXI.Texture.frameUpdates.push(this);
  7603. //this.dispatchEvent( { type: 'update', content: this } );
  7604. };
  7605. PIXI.Texture.prototype._updateWebGLuvs = function()
  7606. {
  7607. if(!this._uvs)this._uvs = new PIXI.TextureUvs();
  7608. var frame = this.frame;
  7609. var tw = this.baseTexture.width;
  7610. var th = this.baseTexture.height;
  7611. this._uvs.x0 = frame.x / tw;
  7612. this._uvs.y0 = frame.y / th;
  7613. this._uvs.x1 = (frame.x + frame.width) / tw;
  7614. this._uvs.y1 = frame.y / th;
  7615. this._uvs.x2 = (frame.x + frame.width) / tw;
  7616. this._uvs.y2 = (frame.y + frame.height) / th;
  7617. this._uvs.x3 = frame.x / tw;
  7618. this._uvs.y3 = (frame.y + frame.height) / th;
  7619. };
  7620. /**
  7621. * Helper function that returns a texture based on an image url
  7622. * If the image is not in the texture cache it will be created and loaded
  7623. *
  7624. * @static
  7625. * @method fromImage
  7626. * @param imageUrl {String} The image url of the texture
  7627. * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
  7628. * @return Texture
  7629. */
  7630. PIXI.Texture.fromImage = function(imageUrl, crossorigin, scaleMode)
  7631. {
  7632. var texture = PIXI.TextureCache[imageUrl];
  7633. if(!texture)
  7634. {
  7635. texture = new PIXI.Texture(PIXI.BaseTexture.fromImage(imageUrl, crossorigin, scaleMode));
  7636. PIXI.TextureCache[imageUrl] = texture;
  7637. }
  7638. return texture;
  7639. };
  7640. /**
  7641. * Helper function that returns a texture based on a frame id
  7642. * If the frame id is not in the texture cache an error will be thrown
  7643. *
  7644. * @static
  7645. * @method fromFrame
  7646. * @param frameId {String} The frame id of the texture
  7647. * @return Texture
  7648. */
  7649. PIXI.Texture.fromFrame = function(frameId)
  7650. {
  7651. var texture = PIXI.TextureCache[frameId];
  7652. if(!texture) throw new Error('The frameId "' + frameId + '" does not exist in the texture cache ');
  7653. return texture;
  7654. };
  7655. /**
  7656. * Helper function that returns a texture based on a canvas element
  7657. * If the canvas is not in the texture cache it will be created and loaded
  7658. *
  7659. * @static
  7660. * @method fromCanvas
  7661. * @param canvas {Canvas} The canvas element source of the texture
  7662. * @return Texture
  7663. */
  7664. PIXI.Texture.fromCanvas = function(canvas, scaleMode)
  7665. {
  7666. var baseTexture = PIXI.BaseTexture.fromCanvas(canvas, scaleMode);
  7667. return new PIXI.Texture( baseTexture );
  7668. };
  7669. /**
  7670. * Adds a texture to the textureCache.
  7671. *
  7672. * @static
  7673. * @method addTextureToCache
  7674. * @param texture {Texture}
  7675. * @param id {String} the id that the texture will be stored against.
  7676. */
  7677. PIXI.Texture.addTextureToCache = function(texture, id)
  7678. {
  7679. PIXI.TextureCache[id] = texture;
  7680. };
  7681. /**
  7682. * Remove a texture from the textureCache.
  7683. *
  7684. * @static
  7685. * @method removeTextureFromCache
  7686. * @param id {String} the id of the texture to be removed
  7687. * @return {Texture} the texture that was removed
  7688. */
  7689. PIXI.Texture.removeTextureFromCache = function(id)
  7690. {
  7691. var texture = PIXI.TextureCache[id];
  7692. delete PIXI.TextureCache[id];
  7693. delete PIXI.BaseTextureCache[id];
  7694. return texture;
  7695. };
  7696. // this is more for webGL.. it contains updated frames..
  7697. PIXI.Texture.frameUpdates = [];
  7698. PIXI.TextureUvs = function()
  7699. {
  7700. this.x0 = 0;
  7701. this.y0 = 0;
  7702. this.x1 = 0;
  7703. this.y1 = 0;
  7704. this.x2 = 0;
  7705. this.y2 = 0;
  7706. this.x3 = 0;
  7707. this.y4 = 0;
  7708. };
  7709. /**
  7710. * @author Mat Groves http://matgroves.com/ @Doormat23
  7711. */
  7712. /**
  7713. A RenderTexture is a special texture that allows any pixi displayObject to be rendered to it.
  7714. __Hint__: All DisplayObjects (exmpl. Sprites) that render on RenderTexture should be preloaded.
  7715. Otherwise black rectangles will be drawn instead.
  7716. RenderTexture takes snapshot of DisplayObject passed to render method. If DisplayObject is passed to render method, position and rotation of it will be ignored. For example:
  7717. var renderTexture = new PIXI.RenderTexture(800, 600);
  7718. var sprite = PIXI.Sprite.fromImage("spinObj_01.png");
  7719. sprite.position.x = 800/2;
  7720. sprite.position.y = 600/2;
  7721. sprite.anchor.x = 0.5;
  7722. sprite.anchor.y = 0.5;
  7723. renderTexture.render(sprite);
  7724. Sprite in this case will be rendered to 0,0 position. To render this sprite at center DisplayObjectContainer should be used:
  7725. var doc = new PIXI.DisplayObjectContainer();
  7726. doc.addChild(sprite);
  7727. renderTexture.render(doc); // Renders to center of renderTexture
  7728. * @class RenderTexture
  7729. * @extends Texture
  7730. * @constructor
  7731. * @param width {Number} The width of the render texture
  7732. * @param height {Number} The height of the render texture
  7733. */
  7734. PIXI.RenderTexture = function(width, height, renderer)
  7735. {
  7736. PIXI.EventTarget.call( this );
  7737. /**
  7738. * The with of the render texture
  7739. *
  7740. * @property width
  7741. * @type Number
  7742. */
  7743. this.width = width || 100;
  7744. /**
  7745. * The height of the render texture
  7746. *
  7747. * @property height
  7748. * @type Number
  7749. */
  7750. this.height = height || 100;
  7751. /**
  7752. * The framing rectangle of the render texture
  7753. *
  7754. * @property frame
  7755. * @type Rectangle
  7756. */
  7757. this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
  7758. /**
  7759. * The base texture object that this texture uses
  7760. *
  7761. * @property baseTexture
  7762. * @type BaseTexture
  7763. */
  7764. this.baseTexture = new PIXI.BaseTexture();
  7765. this.baseTexture.width = this.width;
  7766. this.baseTexture.height = this.height;
  7767. this.baseTexture._glTextures = [];
  7768. this.baseTexture.hasLoaded = true;
  7769. // each render texture can only belong to one renderer at the moment if its webGL
  7770. this.renderer = renderer || PIXI.defaultRenderer;
  7771. if(this.renderer.type === PIXI.WEBGL_RENDERER)
  7772. {
  7773. var gl = this.renderer.gl;
  7774. this.textureBuffer = new PIXI.FilterTexture(gl, this.width, this.height);
  7775. this.baseTexture._glTextures[gl.id] = this.textureBuffer.texture;
  7776. this.render = this.renderWebGL;
  7777. this.projection = new PIXI.Point(this.width/2 , -this.height/2);
  7778. }
  7779. else
  7780. {
  7781. this.render = this.renderCanvas;
  7782. this.textureBuffer = new PIXI.CanvasBuffer(this.width, this.height);
  7783. this.baseTexture.source = this.textureBuffer.canvas;
  7784. }
  7785. PIXI.Texture.frameUpdates.push(this);
  7786. };
  7787. PIXI.RenderTexture.prototype = Object.create(PIXI.Texture.prototype);
  7788. PIXI.RenderTexture.prototype.constructor = PIXI.RenderTexture;
  7789. PIXI.RenderTexture.prototype.resize = function(width, height)
  7790. {
  7791. this.width = width;
  7792. this.height = height;
  7793. this.frame.width = this.width;
  7794. this.frame.height = this.height;
  7795. if(this.renderer.type === PIXI.WEBGL_RENDERER)
  7796. {
  7797. this.projection.x = this.width / 2;
  7798. this.projection.y = -this.height / 2;
  7799. var gl = this.renderer.gl;
  7800. gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTextures[gl.id]);
  7801. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  7802. }
  7803. else
  7804. {
  7805. this.textureBuffer.resize(this.width, this.height);
  7806. }
  7807. PIXI.Texture.frameUpdates.push(this);
  7808. };
  7809. /**
  7810. * This function will draw the display object to the texture.
  7811. *
  7812. * @method renderWebGL
  7813. * @param displayObject {DisplayObject} The display object to render this texture on
  7814. * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn
  7815. * @private
  7816. */
  7817. PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear)
  7818. {
  7819. //TOOD replace position with matrix..
  7820. var gl = this.renderer.gl;
  7821. gl.colorMask(true, true, true, true);
  7822. gl.viewport(0, 0, this.width, this.height);
  7823. gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer );
  7824. if(clear)this.textureBuffer.clear();
  7825. // THIS WILL MESS WITH HIT TESTING!
  7826. var children = displayObject.children;
  7827. //TODO -? create a new one??? dont think so!
  7828. var originalWorldTransform = displayObject.worldTransform;
  7829. displayObject.worldTransform = PIXI.RenderTexture.tempMatrix;
  7830. // modify to flip...
  7831. displayObject.worldTransform.d = -1;
  7832. displayObject.worldTransform.ty = this.projection.y * -2;
  7833. if(position)
  7834. {
  7835. displayObject.worldTransform.tx = position.x;
  7836. displayObject.worldTransform.ty -= position.y;
  7837. }
  7838. for(var i=0,j=children.length; i<j; i++)
  7839. {
  7840. children[i].updateTransform();
  7841. }
  7842. // update the textures!
  7843. PIXI.WebGLRenderer.updateTextures();
  7844. //
  7845. this.renderer.renderDisplayObject(displayObject, this.projection, this.textureBuffer.frameBuffer);
  7846. displayObject.worldTransform = originalWorldTransform;
  7847. };
  7848. /**
  7849. * This function will draw the display object to the texture.
  7850. *
  7851. * @method renderCanvas
  7852. * @param displayObject {DisplayObject} The display object to render this texture on
  7853. * @param clear {Boolean} If true the texture will be cleared before the displayObject is drawn
  7854. * @private
  7855. */
  7856. PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, position, clear)
  7857. {
  7858. var children = displayObject.children;
  7859. var originalWorldTransform = displayObject.worldTransform;
  7860. displayObject.worldTransform = PIXI.RenderTexture.tempMatrix;
  7861. if(position)
  7862. {
  7863. displayObject.worldTransform.tx = position.x;
  7864. displayObject.worldTransform.ty = position.y;
  7865. }
  7866. for(var i = 0, j = children.length; i < j; i++)
  7867. {
  7868. children[i].updateTransform();
  7869. }
  7870. if(clear)this.textureBuffer.clear();
  7871. var context = this.textureBuffer.context;
  7872. this.renderer.renderDisplayObject(displayObject, context);
  7873. context.setTransform(1,0,0,1,0,0);
  7874. displayObject.worldTransform = originalWorldTransform;
  7875. };
  7876. PIXI.RenderTexture.tempMatrix = new PIXI.Matrix();
  7877. /**
  7878. * @author Mat Groves http://matgroves.com/ @Doormat23
  7879. */
  7880. if (typeof exports !== 'undefined') {
  7881. if (typeof module !== 'undefined' && module.exports) {
  7882. exports = module.exports = PIXI;
  7883. }
  7884. exports.PIXI = PIXI;
  7885. } else if (typeof define !== 'undefined' && define.amd) {
  7886. define('PIXI', (function() { return root.PIXI = PIXI; })() );
  7887. } else {
  7888. root.PIXI = PIXI;
  7889. }
  7890. }).call(this);
  7891. /**
  7892. * @author Richard Davey <rich@photonstorm.com>
  7893. * @copyright 2014 Photon Storm Ltd.
  7894. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  7895. *
  7896. * @overview
  7897. *
  7898. * Phaser - http://phaser.io
  7899. *
  7900. * v2.0.3 "Allorallen" - Built: Fri Apr 11 2014 13:08:30
  7901. *
  7902. * By Richard Davey http://www.photonstorm.com @photonstorm
  7903. *
  7904. * Phaser is a fun, free and fast 2D game framework for making HTML5 games
  7905. * for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
  7906. *
  7907. * Phaser uses Pixi.js for rendering, created by Mat Groves http://matgroves.com @Doormat23
  7908. * Phaser uses p2.js for full-body physics, created by Stefan Hedman https://github.com/schteppe/p2.js @schteppe
  7909. * Phaser contains a port of N+ Physics, converted by Richard Davey, original by http://www.metanetsoftware.com
  7910. *
  7911. * Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel, from which both Phaser
  7912. * and my love of framework development originate.
  7913. *
  7914. * Follow development at http://phaser.io and on our forum
  7915. *
  7916. * "If you want your children to be intelligent, read them fairy tales."
  7917. * "If you want them to be more intelligent, read them more fairy tales."
  7918. * -- Albert Einstein
  7919. */
  7920. /**
  7921. * @author Richard Davey <rich@photonstorm.com>
  7922. * @copyright 2014 Photon Storm Ltd.
  7923. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  7924. */
  7925. (function(){
  7926. var root = this;
  7927. /* global Phaser:true */
  7928. /**
  7929. * @author Richard Davey <rich@photonstorm.com>
  7930. * @copyright 2014 Photon Storm Ltd.
  7931. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  7932. */
  7933. /**
  7934. * @namespace Phaser
  7935. */
  7936. var Phaser = Phaser || {
  7937. VERSION: '<%= version %>',
  7938. DEV_VERSION: '2.0.3',
  7939. GAMES: [],
  7940. AUTO: 0,
  7941. CANVAS: 1,
  7942. WEBGL: 2,
  7943. HEADLESS: 3,
  7944. NONE: 0,
  7945. LEFT: 1,
  7946. RIGHT: 2,
  7947. UP: 3,
  7948. DOWN: 4,
  7949. SPRITE: 0,
  7950. BUTTON: 1,
  7951. IMAGE: 2,
  7952. GRAPHICS: 3,
  7953. TEXT: 4,
  7954. TILESPRITE: 5,
  7955. BITMAPTEXT: 6,
  7956. GROUP: 7,
  7957. RENDERTEXTURE: 8,
  7958. TILEMAP: 9,
  7959. TILEMAPLAYER: 10,
  7960. EMITTER: 11,
  7961. POLYGON: 12,
  7962. BITMAPDATA: 13,
  7963. CANVAS_FILTER: 14,
  7964. WEBGL_FILTER: 15,
  7965. ELLIPSE: 16,
  7966. SPRITEBATCH: 17,
  7967. RETROFONT: 18,
  7968. // The various blend modes supported by pixi / phaser
  7969. blendModes: {
  7970. NORMAL:0,
  7971. ADD:1,
  7972. MULTIPLY:2,
  7973. SCREEN:3,
  7974. OVERLAY:4,
  7975. DARKEN:5,
  7976. LIGHTEN:6,
  7977. COLOR_DODGE:7,
  7978. COLOR_BURN:8,
  7979. HARD_LIGHT:9,
  7980. SOFT_LIGHT:10,
  7981. DIFFERENCE:11,
  7982. EXCLUSION:12,
  7983. HUE:13,
  7984. SATURATION:14,
  7985. COLOR:15,
  7986. LUMINOSITY:16
  7987. },
  7988. // The scale modes
  7989. scaleModes: {
  7990. DEFAULT:0,
  7991. LINEAR:0,
  7992. NEAREST:1
  7993. }
  7994. };
  7995. PIXI.InteractionManager = function () {
  7996. // We don't need this in Pixi, so we've removed it to save space
  7997. // however the Stage object expects a reference to it, so here is a dummy entry.
  7998. };
  7999. /* jshint supernew: true */
  8000. /**
  8001. * @author Richard Davey <rich@photonstorm.com>
  8002. * @copyright 2014 Photon Storm Ltd.
  8003. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  8004. */
  8005. /**
  8006. * @class Phaser.Utils
  8007. * @static
  8008. */
  8009. Phaser.Utils = {
  8010. /**
  8011. * Get a unit dimension from a string.
  8012. *
  8013. * @method Phaser.Utils.parseDimension
  8014. * @param {string|number} size - The size to parse.
  8015. * @param {number} dimension - The window dimension to check.
  8016. * @return {number} The parsed dimension.
  8017. */
  8018. parseDimension: function (size, dimension) {
  8019. var f = 0;
  8020. var px = 0;
  8021. if (typeof size === 'string')
  8022. {
  8023. // %?
  8024. if (size.substr(-1) === '%')
  8025. {
  8026. f = parseInt(size, 10) / 100;
  8027. if (dimension === 0)
  8028. {
  8029. px = window.innerWidth * f;
  8030. }
  8031. else
  8032. {
  8033. px = window.innerHeight * f;
  8034. }
  8035. }
  8036. else
  8037. {
  8038. px = parseInt(size, 10);
  8039. }
  8040. }
  8041. else
  8042. {
  8043. px = size;
  8044. }
  8045. return px;
  8046. },
  8047. /**
  8048. * A standard Fisher-Yates Array shuffle implementation.
  8049. * @method Phaser.Utils.shuffle
  8050. * @param {array} array - The array to shuffle.
  8051. * @return {array} The shuffled array.
  8052. */
  8053. shuffle: function (array) {
  8054. for (var i = array.length - 1; i > 0; i--)
  8055. {
  8056. var j = Math.floor(Math.random() * (i + 1));
  8057. var temp = array[i];
  8058. array[i] = array[j];
  8059. array[j] = temp;
  8060. }
  8061. return array;
  8062. },
  8063. /**
  8064. * Javascript string pad http://www.webtoolkit.info/.
  8065. * pad = the string to pad it out with (defaults to a space)
  8066. * dir = 1 (left), 2 (right), 3 (both)
  8067. * @method Phaser.Utils.pad
  8068. * @param {string} str - The target string.
  8069. * @param {number} len - The number of characters to be added.
  8070. * @param {number} pad - The string to pad it out with (defaults to a space).
  8071. * @param {number} [dir=3] The direction dir = 1 (left), 2 (right), 3 (both).
  8072. * @return {string} The padded string
  8073. */
  8074. pad: function (str, len, pad, dir) {
  8075. if (typeof(len) == "undefined") { var len = 0; }
  8076. if (typeof(pad) == "undefined") { var pad = ' '; }
  8077. if (typeof(dir) == "undefined") { var dir = 3; }
  8078. var padlen = 0;
  8079. if (len + 1 >= str.length)
  8080. {
  8081. switch (dir)
  8082. {
  8083. case 1:
  8084. str = new Array(len + 1 - str.length).join(pad) + str;
  8085. break;
  8086. case 3:
  8087. var right = Math.ceil((padlen = len - str.length) / 2);
  8088. var left = padlen - right;
  8089. str = new Array(left+1).join(pad) + str + new Array(right+1).join(pad);
  8090. break;
  8091. default:
  8092. str = str + new Array(len + 1 - str.length).join(pad);
  8093. break;
  8094. }
  8095. }
  8096. return str;
  8097. },
  8098. /**
  8099. * This is a slightly modified version of jQuery.isPlainObject. A plain object is an object whose internal class property is [object Object].
  8100. * @method Phaser.Utils.isPlainObject
  8101. * @param {object} obj - The object to inspect.
  8102. * @return {boolean} - true if the object is plain, otherwise false.
  8103. */
  8104. isPlainObject: function (obj) {
  8105. // Not plain objects:
  8106. // - Any object or value whose internal [[Class]] property is not "[object Object]"
  8107. // - DOM nodes
  8108. // - window
  8109. if (typeof(obj) !== "object" || obj.nodeType || obj === obj.window)
  8110. {
  8111. return false;
  8112. }
  8113. // Support: Firefox <20
  8114. // The try/catch suppresses exceptions thrown when attempting to access
  8115. // the "constructor" property of certain host objects, ie. |window.location|
  8116. // https://bugzilla.mozilla.org/show_bug.cgi?id=814622
  8117. try {
  8118. if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf"))
  8119. {
  8120. return false;
  8121. }
  8122. } catch (e) {
  8123. return false;
  8124. }
  8125. // If the function hasn't returned already, we're confident that
  8126. // |obj| is a plain object, created by {} or constructed with new Object
  8127. return true;
  8128. },
  8129. /**
  8130. * This is a slightly modified version of http://api.jquery.com/jQuery.extend/
  8131. * @method Phaser.Utils.extend
  8132. * @param {boolean} deep - Perform a deep copy?
  8133. * @param {object} target - The target object to copy to.
  8134. * @return {object} The extended object.
  8135. */
  8136. extend: function () {
  8137. var options, name, src, copy, copyIsArray, clone,
  8138. target = arguments[0] || {},
  8139. i = 1,
  8140. length = arguments.length,
  8141. deep = false;
  8142. // Handle a deep copy situation
  8143. if (typeof target === "boolean")
  8144. {
  8145. deep = target;
  8146. target = arguments[1] || {};
  8147. // skip the boolean and the target
  8148. i = 2;
  8149. }
  8150. // extend Phaser if only one argument is passed
  8151. if (length === i)
  8152. {
  8153. target = this;
  8154. --i;
  8155. }
  8156. for (; i < length; i++)
  8157. {
  8158. // Only deal with non-null/undefined values
  8159. if ((options = arguments[i]) != null)
  8160. {
  8161. // Extend the base object
  8162. for (name in options)
  8163. {
  8164. src = target[name];
  8165. copy = options[name];
  8166. // Prevent never-ending loop
  8167. if (target === copy)
  8168. {
  8169. continue;
  8170. }
  8171. // Recurse if we're merging plain objects or arrays
  8172. if (deep && copy && (Phaser.Utils.isPlainObject(copy) || (copyIsArray = Array.isArray(copy))))
  8173. {
  8174. if (copyIsArray)
  8175. {
  8176. copyIsArray = false;
  8177. clone = src && Array.isArray(src) ? src : [];
  8178. }
  8179. else
  8180. {
  8181. clone = src && Phaser.Utils.isPlainObject(src) ? src : {};
  8182. }
  8183. // Never move original objects, clone them
  8184. target[name] = Phaser.Utils.extend(deep, clone, copy);
  8185. // Don't bring in undefined values
  8186. }
  8187. else if (copy !== undefined)
  8188. {
  8189. target[name] = copy;
  8190. }
  8191. }
  8192. }
  8193. }
  8194. // Return the modified object
  8195. return target;
  8196. }
  8197. };
  8198. /**
  8199. * A polyfill for Function.prototype.bind
  8200. */
  8201. if (typeof Function.prototype.bind != 'function') {
  8202. /* jshint freeze: false */
  8203. Function.prototype.bind = (function () {
  8204. var slice = Array.prototype.slice;
  8205. return function (thisArg) {
  8206. var target = this, boundArgs = slice.call(arguments, 1);
  8207. if (typeof target != 'function')
  8208. {
  8209. throw new TypeError();
  8210. }
  8211. function bound() {
  8212. var args = boundArgs.concat(slice.call(arguments));
  8213. target.apply(this instanceof bound ? this : thisArg, args);
  8214. }
  8215. bound.prototype = (function F(proto) {
  8216. if (proto)
  8217. {
  8218. F.prototype = proto;
  8219. }
  8220. if (!(this instanceof F))
  8221. {
  8222. return new F;
  8223. }
  8224. })(target.prototype);
  8225. return bound;
  8226. };
  8227. })();
  8228. }
  8229. /**
  8230. * A polyfill for Array.isArray
  8231. */
  8232. if (!Array.isArray)
  8233. {
  8234. Array.isArray = function (arg)
  8235. {
  8236. return Object.prototype.toString.call(arg) == '[object Array]';
  8237. };
  8238. }
  8239. /**
  8240. * A polyfill for Array.forEach
  8241. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
  8242. */
  8243. if (!Array.prototype.forEach)
  8244. {
  8245. Array.prototype.forEach = function(fun /*, thisArg */)
  8246. {
  8247. "use strict";
  8248. if (this === void 0 || this === null)
  8249. {
  8250. throw new TypeError();
  8251. }
  8252. var t = Object(this);
  8253. var len = t.length >>> 0;
  8254. if (typeof fun !== "function")
  8255. {
  8256. throw new TypeError();
  8257. }
  8258. var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
  8259. for (var i = 0; i < len; i++)
  8260. {
  8261. if (i in t)
  8262. {
  8263. fun.call(thisArg, t[i], i, t);
  8264. }
  8265. }
  8266. };
  8267. }
  8268. /**
  8269. * @author Richard Davey <rich@photonstorm.com>
  8270. * @copyright 2014 Photon Storm Ltd.
  8271. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  8272. */
  8273. /**
  8274. * Creates a new Circle object with the center coordinate specified by the x and y parameters and the diameter specified by the diameter parameter. If you call this function without parameters, a circle with x, y, diameter and radius properties set to 0 is created.
  8275. * @class Circle
  8276. * @classdesc Phaser - Circle
  8277. * @constructor
  8278. * @param {number} [x=0] - The x coordinate of the center of the circle.
  8279. * @param {number} [y=0] - The y coordinate of the center of the circle.
  8280. * @param {number} [diameter=0] - The diameter of the circle.
  8281. * @return {Phaser.Circle} This circle object
  8282. */
  8283. Phaser.Circle = function (x, y, diameter) {
  8284. x = x || 0;
  8285. y = y || 0;
  8286. diameter = diameter || 0;
  8287. /**
  8288. * @property {number} x - The x coordinate of the center of the circle.
  8289. */
  8290. this.x = x;
  8291. /**
  8292. * @property {number} y - The y coordinate of the center of the circle.
  8293. */
  8294. this.y = y;
  8295. /**
  8296. * @property {number} _diameter - The diameter of the circle.
  8297. * @private
  8298. */
  8299. this._diameter = diameter;
  8300. if (diameter > 0)
  8301. {
  8302. /**
  8303. * @property {number} _radius - The radius of the circle.
  8304. * @private
  8305. */
  8306. this._radius = diameter * 0.5;
  8307. }
  8308. else
  8309. {
  8310. this._radius = 0;
  8311. }
  8312. };
  8313. Phaser.Circle.prototype = {
  8314. /**
  8315. * The circumference of the circle.
  8316. * @method Phaser.Circle#circumference
  8317. * @return {number}
  8318. */
  8319. circumference: function () {
  8320. return 2 * (Math.PI * this._radius);
  8321. },
  8322. /**
  8323. * Sets the members of Circle to the specified values.
  8324. * @method Phaser.Circle#setTo
  8325. * @param {number} x - The x coordinate of the center of the circle.
  8326. * @param {number} y - The y coordinate of the center of the circle.
  8327. * @param {number} diameter - The diameter of the circle in pixels.
  8328. * @return {Circle} This circle object.
  8329. */
  8330. setTo: function (x, y, diameter) {
  8331. this.x = x;
  8332. this.y = y;
  8333. this._diameter = diameter;
  8334. this._radius = diameter * 0.5;
  8335. return this;
  8336. },
  8337. /**
  8338. * Copies the x, y and diameter properties from any given object to this Circle.
  8339. * @method Phaser.Circle#copyFrom
  8340. * @param {any} source - The object to copy from.
  8341. * @return {Circle} This Circle object.
  8342. */
  8343. copyFrom: function (source) {
  8344. return this.setTo(source.x, source.y, source.diameter);
  8345. },
  8346. /**
  8347. * Copies the x, y and diameter properties from this Circle to any given object.
  8348. * @method Phaser.Circle#copyTo
  8349. * @param {any} dest - The object to copy to.
  8350. * @return {Object} This dest object.
  8351. */
  8352. copyTo: function (dest) {
  8353. dest.x = this.x;
  8354. dest.y = this.y;
  8355. dest.diameter = this._diameter;
  8356. return dest;
  8357. },
  8358. /**
  8359. * Returns the distance from the center of the Circle object to the given object
  8360. * (can be Circle, Point or anything with x/y properties)
  8361. * @method Phaser.Circle#distance
  8362. * @param {object} dest - The target object. Must have visible x and y properties that represent the center of the object.
  8363. * @param {boolean} [round] - Round the distance to the nearest integer (default false).
  8364. * @return {number} The distance between this Point object and the destination Point object.
  8365. */
  8366. distance: function (dest, round) {
  8367. if (typeof round === "undefined") { round = false; }
  8368. if (round)
  8369. {
  8370. return Phaser.Math.distanceRound(this.x, this.y, dest.x, dest.y);
  8371. }
  8372. else
  8373. {
  8374. return Phaser.Math.distance(this.x, this.y, dest.x, dest.y);
  8375. }
  8376. },
  8377. /**
  8378. * Returns a new Circle object with the same values for the x, y, width, and height properties as this Circle object.
  8379. * @method Phaser.Circle#clone
  8380. * @param {Phaser.Circle} out - Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned.
  8381. * @return {Phaser.Circle} The cloned Circle object.
  8382. */
  8383. clone: function (out) {
  8384. if (typeof out === "undefined")
  8385. {
  8386. out = new Phaser.Circle(this.x, this.y, this.diameter);
  8387. }
  8388. else
  8389. {
  8390. out.setTo(this.x, this.y, this.diameter);
  8391. }
  8392. return out;
  8393. },
  8394. /**
  8395. * Return true if the given x/y coordinates are within this Circle object.
  8396. * @method Phaser.Circle#contains
  8397. * @param {number} x - The X value of the coordinate to test.
  8398. * @param {number} y - The Y value of the coordinate to test.
  8399. * @return {boolean} True if the coordinates are within this circle, otherwise false.
  8400. */
  8401. contains: function (x, y) {
  8402. return Phaser.Circle.contains(this, x, y);
  8403. },
  8404. /**
  8405. * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle.
  8406. * @method Phaser.Circle#circumferencePoint
  8407. * @param {number} angle - The angle in radians (unless asDegrees is true) to return the point from.
  8408. * @param {boolean} asDegrees - Is the given angle in radians (false) or degrees (true)?
  8409. * @param {Phaser.Point} [out] - An optional Point object to put the result in to. If none specified a new Point object will be created.
  8410. * @return {Phaser.Point} The Point object holding the result.
  8411. */
  8412. circumferencePoint: function (angle, asDegrees, out) {
  8413. return Phaser.Circle.circumferencePoint(this, angle, asDegrees, out);
  8414. },
  8415. /**
  8416. * Adjusts the location of the Circle object, as determined by its center coordinate, by the specified amounts.
  8417. * @method Phaser.Circle#offset
  8418. * @param {number} dx - Moves the x value of the Circle object by this amount.
  8419. * @param {number} dy - Moves the y value of the Circle object by this amount.
  8420. * @return {Circle} This Circle object.
  8421. */
  8422. offset: function (dx, dy) {
  8423. this.x += dx;
  8424. this.y += dy;
  8425. return this;
  8426. },
  8427. /**
  8428. * Adjusts the location of the Circle object using a Point object as a parameter. This method is similar to the Circle.offset() method, except that it takes a Point object as a parameter.
  8429. * @method Phaser.Circle#offsetPoint
  8430. * @param {Point} point A Point object to use to offset this Circle object (or any valid object with exposed x and y properties).
  8431. * @return {Circle} This Circle object.
  8432. */
  8433. offsetPoint: function (point) {
  8434. return this.offset(point.x, point.y);
  8435. },
  8436. /**
  8437. * Returns a string representation of this object.
  8438. * @method Phaser.Circle#toString
  8439. * @return {string} a string representation of the instance.
  8440. */
  8441. toString: function () {
  8442. return "[{Phaser.Circle (x=" + this.x + " y=" + this.y + " diameter=" + this.diameter + " radius=" + this.radius + ")}]";
  8443. }
  8444. };
  8445. Phaser.Circle.prototype.constructor = Phaser.Circle;
  8446. /**
  8447. * The largest distance between any two points on the circle. The same as the radius * 2.
  8448. * @name Phaser.Circle#diameter
  8449. * @property {number} diameter - Gets or sets the diameter of the circle.
  8450. */
  8451. Object.defineProperty(Phaser.Circle.prototype, "diameter", {
  8452. get: function () {
  8453. return this._diameter;
  8454. },
  8455. set: function (value) {
  8456. if (value > 0)
  8457. {
  8458. this._diameter = value;
  8459. this._radius = value * 0.5;
  8460. }
  8461. }
  8462. });
  8463. /**
  8464. * The length of a line extending from the center of the circle to any point on the circle itself. The same as half the diameter.
  8465. * @name Phaser.Circle#radius
  8466. * @property {number} radius - Gets or sets the radius of the circle.
  8467. */
  8468. Object.defineProperty(Phaser.Circle.prototype, "radius", {
  8469. get: function () {
  8470. return this._radius;
  8471. },
  8472. set: function (value) {
  8473. if (value > 0)
  8474. {
  8475. this._radius = value;
  8476. this._diameter = value * 2;
  8477. }
  8478. }
  8479. });
  8480. /**
  8481. * The x coordinate of the leftmost point of the circle. Changing the left property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
  8482. * @name Phaser.Circle#left
  8483. * @propety {number} left - Gets or sets the value of the leftmost point of the circle.
  8484. */
  8485. Object.defineProperty(Phaser.Circle.prototype, "left", {
  8486. get: function () {
  8487. return this.x - this._radius;
  8488. },
  8489. set: function (value) {
  8490. if (value > this.x)
  8491. {
  8492. this._radius = 0;
  8493. this._diameter = 0;
  8494. }
  8495. else
  8496. {
  8497. this.radius = this.x - value;
  8498. }
  8499. }
  8500. });
  8501. /**
  8502. * The x coordinate of the rightmost point of the circle. Changing the right property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property.
  8503. * @name Phaser.Circle#right
  8504. * @property {number} right - Gets or sets the value of the rightmost point of the circle.
  8505. */
  8506. Object.defineProperty(Phaser.Circle.prototype, "right", {
  8507. get: function () {
  8508. return this.x + this._radius;
  8509. },
  8510. set: function (value) {
  8511. if (value < this.x)
  8512. {
  8513. this._radius = 0;
  8514. this._diameter = 0;
  8515. }
  8516. else
  8517. {
  8518. this.radius = value - this.x;
  8519. }
  8520. }
  8521. });
  8522. /**
  8523. * The sum of the y minus the radius property. Changing the top property of a Circle object has no effect on the x and y properties, but does change the diameter.
  8524. * @name Phaser.Circle#top
  8525. * @property {number} top - Gets or sets the top of the circle.
  8526. */
  8527. Object.defineProperty(Phaser.Circle.prototype, "top", {
  8528. get: function () {
  8529. return this.y - this._radius;
  8530. },
  8531. set: function (value) {
  8532. if (value > this.y)
  8533. {
  8534. this._radius = 0;
  8535. this._diameter = 0;
  8536. }
  8537. else
  8538. {
  8539. this.radius = this.y - value;
  8540. }
  8541. }
  8542. });
  8543. /**
  8544. * The sum of the y and radius properties. Changing the bottom property of a Circle object has no effect on the x and y properties, but does change the diameter.
  8545. * @name Phaser.Circle#bottom
  8546. * @property {number} bottom - Gets or sets the bottom of the circle.
  8547. */
  8548. Object.defineProperty(Phaser.Circle.prototype, "bottom", {
  8549. get: function () {
  8550. return this.y + this._radius;
  8551. },
  8552. set: function (value) {
  8553. if (value < this.y)
  8554. {
  8555. this._radius = 0;
  8556. this._diameter = 0;
  8557. }
  8558. else
  8559. {
  8560. this.radius = value - this.y;
  8561. }
  8562. }
  8563. });
  8564. /**
  8565. * The area of this Circle.
  8566. * @name Phaser.Circle#area
  8567. * @property {number} area - The area of this circle.
  8568. * @readonly
  8569. */
  8570. Object.defineProperty(Phaser.Circle.prototype, "area", {
  8571. get: function () {
  8572. if (this._radius > 0)
  8573. {
  8574. return Math.PI * this._radius * this._radius;
  8575. }
  8576. else
  8577. {
  8578. return 0;
  8579. }
  8580. }
  8581. });
  8582. /**
  8583. * Determines whether or not this Circle object is empty. Will return a value of true if the Circle objects diameter is less than or equal to 0; otherwise false.
  8584. * If set to true it will reset all of the Circle objects properties to 0. A Circle object is empty if its diameter is less than or equal to 0.
  8585. * @name Phaser.Circle#empty
  8586. * @property {boolean} empty - Gets or sets the empty state of the circle.
  8587. */
  8588. Object.defineProperty(Phaser.Circle.prototype, "empty", {
  8589. get: function () {
  8590. return (this._diameter === 0);
  8591. },
  8592. set: function (value) {
  8593. if (value === true)
  8594. {
  8595. this.setTo(0, 0, 0);
  8596. }
  8597. }
  8598. });
  8599. /**
  8600. * Return true if the given x/y coordinates are within the Circle object.
  8601. * @method Phaser.Circle.contains
  8602. * @param {Phaser.Circle} a - The Circle to be checked.
  8603. * @param {number} x - The X value of the coordinate to test.
  8604. * @param {number} y - The Y value of the coordinate to test.
  8605. * @return {boolean} True if the coordinates are within this circle, otherwise false.
  8606. */
  8607. Phaser.Circle.contains = function (a, x, y) {
  8608. // Check if x/y are within the bounds first
  8609. if (a.radius > 0 && x >= a.left && x <= a.right && y >= a.top && y <= a.bottom)
  8610. {
  8611. var dx = (a.x - x) * (a.x - x);
  8612. var dy = (a.y - y) * (a.y - y);
  8613. return (dx + dy) <= (a.radius * a.radius);
  8614. }
  8615. else
  8616. {
  8617. return false;
  8618. }
  8619. };
  8620. /**
  8621. * Determines whether the two Circle objects match. This method compares the x, y and diameter properties.
  8622. * @method Phaser.Circle.equals
  8623. * @param {Phaser.Circle} a - The first Circle object.
  8624. * @param {Phaser.Circle} b - The second Circle object.
  8625. * @return {boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false.
  8626. */
  8627. Phaser.Circle.equals = function (a, b) {
  8628. return (a.x == b.x && a.y == b.y && a.diameter == b.diameter);
  8629. };
  8630. /**
  8631. * Determines whether the two Circle objects intersect.
  8632. * This method checks the radius distances between the two Circle objects to see if they intersect.
  8633. * @method Phaser.Circle.intersects
  8634. * @param {Phaser.Circle} a - The first Circle object.
  8635. * @param {Phaser.Circle} b - The second Circle object.
  8636. * @return {boolean} A value of true if the specified object intersects with this Circle object; otherwise false.
  8637. */
  8638. Phaser.Circle.intersects = function (a, b) {
  8639. return (Phaser.Math.distance(a.x, a.y, b.x, b.y) <= (a.radius + b.radius));
  8640. };
  8641. /**
  8642. * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle.
  8643. * @method Phaser.Circle.circumferencePoint
  8644. * @param {Phaser.Circle} a - The first Circle object.
  8645. * @param {number} angle - The angle in radians (unless asDegrees is true) to return the point from.
  8646. * @param {boolean} asDegrees - Is the given angle in radians (false) or degrees (true)?
  8647. * @param {Phaser.Point} [out] - An optional Point object to put the result in to. If none specified a new Point object will be created.
  8648. * @return {Phaser.Point} The Point object holding the result.
  8649. */
  8650. Phaser.Circle.circumferencePoint = function (a, angle, asDegrees, out) {
  8651. if (typeof asDegrees === "undefined") { asDegrees = false; }
  8652. if (typeof out === "undefined") { out = new Phaser.Point(); }
  8653. if (asDegrees === true)
  8654. {
  8655. angle = Phaser.Math.degToRad(angle);
  8656. }
  8657. out.x = a.x + a.radius * Math.cos(angle);
  8658. out.y = a.y + a.radius * Math.sin(angle);
  8659. return out;
  8660. };
  8661. /**
  8662. * Checks if the given Circle and Rectangle objects intersect.
  8663. * @method Phaser.Circle.intersectsRectangle
  8664. * @param {Phaser.Circle} c - The Circle object to test.
  8665. * @param {Phaser.Rectangle} r - The Rectangle object to test.
  8666. * @return {boolean} True if the two objects intersect, otherwise false.
  8667. */
  8668. Phaser.Circle.intersectsRectangle = function (c, r) {
  8669. var cx = Math.abs(c.x - r.x - r.halfWidth);
  8670. var xDist = r.halfWidth + c.radius;
  8671. if (cx > xDist)
  8672. {
  8673. return false;
  8674. }
  8675. var cy = Math.abs(c.y - r.y - r.halfHeight);
  8676. var yDist = r.halfHeight + c.radius;
  8677. if (cy > yDist)
  8678. {
  8679. return false;
  8680. }
  8681. if (cx <= r.halfWidth || cy <= r.halfHeight)
  8682. {
  8683. return true;
  8684. }
  8685. var xCornerDist = cx - r.halfWidth;
  8686. var yCornerDist = cy - r.halfHeight;
  8687. var xCornerDistSq = xCornerDist * xCornerDist;
  8688. var yCornerDistSq = yCornerDist * yCornerDist;
  8689. var maxCornerDistSq = c.radius * c.radius;
  8690. return xCornerDistSq + yCornerDistSq <= maxCornerDistSq;
  8691. };
  8692. // Because PIXI uses its own Circle, we'll replace it with ours to avoid duplicating code or confusion.
  8693. PIXI.Circle = Phaser.Circle;
  8694. /**
  8695. * @author Richard Davey <rich@photonstorm.com>
  8696. * @copyright 2014 Photon Storm Ltd.
  8697. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  8698. */
  8699. /**
  8700. * Creates a new Point. If you pass no parameters a Point is created set to (0,0).
  8701. * @class Phaser.Point
  8702. * @classdesc The Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis.
  8703. * @constructor
  8704. * @param {number} x The horizontal position of this Point (default 0)
  8705. * @param {number} y The vertical position of this Point (default 0)
  8706. */
  8707. Phaser.Point = function (x, y) {
  8708. x = x || 0;
  8709. y = y || 0;
  8710. /**
  8711. * @property {number} x - The x coordinate of the point.
  8712. */
  8713. this.x = x;
  8714. /**
  8715. * @property {number} y - The y coordinate of the point.
  8716. */
  8717. this.y = y;
  8718. };
  8719. Phaser.Point.prototype = {
  8720. /**
  8721. * Copies the x and y properties from any given object to this Point.
  8722. * @method Phaser.Point#copyFrom
  8723. * @param {any} source - The object to copy from.
  8724. * @return {Point} This Point object.
  8725. */
  8726. copyFrom: function (source) {
  8727. return this.setTo(source.x, source.y);
  8728. },
  8729. /**
  8730. * Inverts the x and y values of this Point
  8731. * @method Phaser.Point#invert
  8732. * @return {Point} This Point object.
  8733. */
  8734. invert: function () {
  8735. return this.setTo(this.y, this.x);
  8736. },
  8737. /**
  8738. * Sets the x and y values of this Point object to the given coordinates.
  8739. * @method Phaser.Point#setTo
  8740. * @param {number} x - The horizontal position of this point.
  8741. * @param {number} y - The vertical position of this point.
  8742. * @return {Point} This Point object. Useful for chaining method calls.
  8743. */
  8744. setTo: function (x, y) {
  8745. this.x = x || 0;
  8746. this.y = y || ( (y !== 0) ? this.x : 0 );
  8747. return this;
  8748. },
  8749. /**
  8750. * Sets the x and y values of this Point object to the given coordinates.
  8751. * @method Phaser.Point#set
  8752. * @param {number} x - The horizontal position of this point.
  8753. * @param {number} y - The vertical position of this point.
  8754. * @return {Point} This Point object. Useful for chaining method calls.
  8755. */
  8756. set: function (x, y) {
  8757. this.x = x || 0;
  8758. this.y = y || ( (y !== 0) ? this.x : 0 );
  8759. return this;
  8760. },
  8761. /**
  8762. * Adds the given x and y values to this Point.
  8763. * @method Phaser.Point#add
  8764. * @param {number} x - The value to add to Point.x.
  8765. * @param {number} y - The value to add to Point.y.
  8766. * @return {Phaser.Point} This Point object. Useful for chaining method calls.
  8767. */
  8768. add: function (x, y) {
  8769. this.x += x;
  8770. this.y += y;
  8771. return this;
  8772. },
  8773. /**
  8774. * Subtracts the given x and y values from this Point.
  8775. * @method Phaser.Point#subtract
  8776. * @param {number} x - The value to subtract from Point.x.
  8777. * @param {number} y - The value to subtract from Point.y.
  8778. * @return {Phaser.Point} This Point object. Useful for chaining method calls.
  8779. */
  8780. subtract: function (x, y) {
  8781. this.x -= x;
  8782. this.y -= y;
  8783. return this;
  8784. },
  8785. /**
  8786. * Multiplies Point.x and Point.y by the given x and y values.
  8787. * @method Phaser.Point#multiply
  8788. * @param {number} x - The value to multiply Point.x by.
  8789. * @param {number} y - The value to multiply Point.x by.
  8790. * @return {Phaser.Point} This Point object. Useful for chaining method calls.
  8791. */
  8792. multiply: function (x, y) {
  8793. this.x *= x;
  8794. this.y *= y;
  8795. return this;
  8796. },
  8797. /**
  8798. * Divides Point.x and Point.y by the given x and y values.
  8799. * @method Phaser.Point#divide
  8800. * @param {number} x - The value to divide Point.x by.
  8801. * @param {number} y - The value to divide Point.x by.
  8802. * @return {Phaser.Point} This Point object. Useful for chaining method calls.
  8803. */
  8804. divide: function (x, y) {
  8805. this.x /= x;
  8806. this.y /= y;
  8807. return this;
  8808. },
  8809. /**
  8810. * Clamps the x value of this Point to be between the given min and max.
  8811. * @method Phaser.Point#clampX
  8812. * @param {number} min - The minimum value to clamp this Point to.
  8813. * @param {number} max - The maximum value to clamp this Point to.
  8814. * @return {Phaser.Point} This Point object.
  8815. */
  8816. clampX: function (min, max) {
  8817. this.x = Phaser.Math.clamp(this.x, min, max);
  8818. return this;
  8819. },
  8820. /**
  8821. * Clamps the y value of this Point to be between the given min and max
  8822. * @method Phaser.Point#clampY
  8823. * @param {number} min - The minimum value to clamp this Point to.
  8824. * @param {number} max - The maximum value to clamp this Point to.
  8825. * @return {Phaser.Point} This Point object.
  8826. */
  8827. clampY: function (min, max) {
  8828. this.y = Phaser.Math.clamp(this.y, min, max);
  8829. return this;
  8830. },
  8831. /**
  8832. * Clamps this Point object values to be between the given min and max.
  8833. * @method Phaser.Point#clamp
  8834. * @param {number} min - The minimum value to clamp this Point to.
  8835. * @param {number} max - The maximum value to clamp this Point to.
  8836. * @return {Phaser.Point} This Point object.
  8837. */
  8838. clamp: function (min, max) {
  8839. this.x = Phaser.Math.clamp(this.x, min, max);
  8840. this.y = Phaser.Math.clamp(this.y, min, max);
  8841. return this;
  8842. },
  8843. /**
  8844. * Creates a copy of the given Point.
  8845. * @method Phaser.Point#clone
  8846. * @param {Phaser.Point} [output] Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned.
  8847. * @return {Phaser.Point} The new Point object.
  8848. */
  8849. clone: function (output) {
  8850. if (typeof output === "undefined")
  8851. {
  8852. output = new Phaser.Point(this.x, this.y);
  8853. }
  8854. else
  8855. {
  8856. output.setTo(this.x, this.y);
  8857. }
  8858. return output;
  8859. },
  8860. /**
  8861. * Copies the x and y properties from this Point to any given object.
  8862. * @method Phaser.Point#copyTo
  8863. * @param {any} dest - The object to copy to.
  8864. * @return {Object} The dest object.
  8865. */
  8866. copyTo: function(dest) {
  8867. dest.x = this.x;
  8868. dest.y = this.y;
  8869. return dest;
  8870. },
  8871. /**
  8872. * Returns the distance of this Point object to the given object (can be a Circle, Point or anything with x/y properties)
  8873. * @method Phaser.Point#distance
  8874. * @param {object} dest - The target object. Must have visible x and y properties that represent the center of the object.
  8875. * @param {boolean} [round] - Round the distance to the nearest integer (default false).
  8876. * @return {number} The distance between this Point object and the destination Point object.
  8877. */
  8878. distance: function (dest, round) {
  8879. return Phaser.Point.distance(this, dest, round);
  8880. },
  8881. /**
  8882. * Determines whether the given objects x/y values are equal to this Point object.
  8883. * @method Phaser.Point#equals
  8884. * @param {Phaser.Point} a - The first object to compare.
  8885. * @return {boolean} A value of true if the Points are equal, otherwise false.
  8886. */
  8887. equals: function (a) {
  8888. return (a.x == this.x && a.y == this.y);
  8889. },
  8890. /**
  8891. * Rotates this Point around the x/y coordinates given to the desired angle.
  8892. * @method Phaser.Point#rotate
  8893. * @param {number} x - The x coordinate of the anchor point
  8894. * @param {number} y - The y coordinate of the anchor point
  8895. * @param {number} angle - The angle in radians (unless asDegrees is true) to rotate the Point to.
  8896. * @param {boolean} asDegrees - Is the given rotation in radians (false) or degrees (true)?
  8897. * @param {number} [distance] - An optional distance constraint between the Point and the anchor.
  8898. * @return {Phaser.Point} The modified point object.
  8899. */
  8900. rotate: function (x, y, angle, asDegrees, distance) {
  8901. return Phaser.Point.rotate(this, x, y, angle, asDegrees, distance);
  8902. },
  8903. /**
  8904. * Calculates the length of the vector
  8905. * @method Phaser.Point#getMagnitude
  8906. * @return {number} the length of the vector
  8907. */
  8908. getMagnitude: function() {
  8909. return Math.sqrt((this.x * this.x) + (this.y * this.y));
  8910. },
  8911. /**
  8912. * Alters the length of the vector without changing the direction
  8913. * @method Phaser.Point#setMagnitude
  8914. * @param {number} magnitude the desired magnitude of the resulting vector
  8915. * @return {Phaser.Point} the modified original vector
  8916. */
  8917. setMagnitude: function(magnitude) {
  8918. return this.normalize().multiply(magnitude, magnitude);
  8919. },
  8920. /**
  8921. * Alters the vector so that its length is 1, but it retains the same direction
  8922. * @method Phaser.Point#normalize
  8923. * @return {Phaser.Point} the modified original vector
  8924. */
  8925. normalize: function() {
  8926. if(!this.isZero()) {
  8927. var m = this.getMagnitude();
  8928. this.x /= m;
  8929. this.y /= m;
  8930. }
  8931. return this;
  8932. },
  8933. /**
  8934. * Determine if this point is at 0,0
  8935. * @method Phaser.Point#isZero
  8936. * @return {boolean} True if this Point is 0,0, otherwise false
  8937. */
  8938. isZero: function() {
  8939. return (this.x === 0 && this.y === 0);
  8940. },
  8941. /**
  8942. * Returns a string representation of this object.
  8943. * @method Phaser.Point#toString
  8944. * @return {string} A string representation of the instance.
  8945. */
  8946. toString: function () {
  8947. return '[{Point (x=' + this.x + ' y=' + this.y + ')}]';
  8948. }
  8949. };
  8950. Phaser.Point.prototype.constructor = Phaser.Point;
  8951. /**
  8952. * Adds the coordinates of two points together to create a new point.
  8953. * @method Phaser.Point.add
  8954. * @param {Phaser.Point} a - The first Point object.
  8955. * @param {Phaser.Point} b - The second Point object.
  8956. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created.
  8957. * @return {Phaser.Point} The new Point object.
  8958. */
  8959. Phaser.Point.add = function (a, b, out) {
  8960. if (typeof out === "undefined") { out = new Phaser.Point(); }
  8961. out.x = a.x + b.x;
  8962. out.y = a.y + b.y;
  8963. return out;
  8964. };
  8965. /**
  8966. * Subtracts the coordinates of two points to create a new point.
  8967. * @method Phaser.Point.subtract
  8968. * @param {Phaser.Point} a - The first Point object.
  8969. * @param {Phaser.Point} b - The second Point object.
  8970. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created.
  8971. * @return {Phaser.Point} The new Point object.
  8972. */
  8973. Phaser.Point.subtract = function (a, b, out) {
  8974. if (typeof out === "undefined") { out = new Phaser.Point(); }
  8975. out.x = a.x - b.x;
  8976. out.y = a.y - b.y;
  8977. return out;
  8978. };
  8979. /**
  8980. * Multiplies the coordinates of two points to create a new point.
  8981. * @method Phaser.Point.multiply
  8982. * @param {Phaser.Point} a - The first Point object.
  8983. * @param {Phaser.Point} b - The second Point object.
  8984. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created.
  8985. * @return {Phaser.Point} The new Point object.
  8986. */
  8987. Phaser.Point.multiply = function (a, b, out) {
  8988. if (typeof out === "undefined") { out = new Phaser.Point(); }
  8989. out.x = a.x * b.x;
  8990. out.y = a.y * b.y;
  8991. return out;
  8992. };
  8993. /**
  8994. * Divides the coordinates of two points to create a new point.
  8995. * @method Phaser.Point.divide
  8996. * @param {Phaser.Point} a - The first Point object.
  8997. * @param {Phaser.Point} b - The second Point object.
  8998. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created.
  8999. * @return {Phaser.Point} The new Point object.
  9000. */
  9001. Phaser.Point.divide = function (a, b, out) {
  9002. if (typeof out === "undefined") { out = new Phaser.Point(); }
  9003. out.x = a.x / b.x;
  9004. out.y = a.y / b.y;
  9005. return out;
  9006. };
  9007. /**
  9008. * Determines whether the two given Point objects are equal. They are considered equal if they have the same x and y values.
  9009. * @method Phaser.Point.equals
  9010. * @param {Phaser.Point} a - The first Point object.
  9011. * @param {Phaser.Point} b - The second Point object.
  9012. * @return {boolean} A value of true if the Points are equal, otherwise false.
  9013. */
  9014. Phaser.Point.equals = function (a, b) {
  9015. return (a.x == b.x && a.y == b.y);
  9016. };
  9017. /**
  9018. * Returns the distance of this Point object to the given object (can be a Circle, Point or anything with x/y properties).
  9019. * @method Phaser.Point.distance
  9020. * @param {object} a - The target object. Must have visible x and y properties that represent the center of the object.
  9021. * @param {object} b - The target object. Must have visible x and y properties that represent the center of the object.
  9022. * @param {boolean} [round] - Round the distance to the nearest integer (default false).
  9023. * @return {number} The distance between this Point object and the destination Point object.
  9024. */
  9025. Phaser.Point.distance = function (a, b, round) {
  9026. if (typeof round === "undefined") { round = false; }
  9027. if (round)
  9028. {
  9029. return Phaser.Math.distanceRound(a.x, a.y, b.x, b.y);
  9030. }
  9031. else
  9032. {
  9033. return Phaser.Math.distance(a.x, a.y, b.x, b.y);
  9034. }
  9035. };
  9036. /**
  9037. * Rotates a Point around the x/y coordinates given to the desired angle.
  9038. * @method Phaser.Point.rotate
  9039. * @param {Phaser.Point} a - The Point object to rotate.
  9040. * @param {number} x - The x coordinate of the anchor point
  9041. * @param {number} y - The y coordinate of the anchor point
  9042. * @param {number} angle - The angle in radians (unless asDegrees is true) to rotate the Point to.
  9043. * @param {boolean} asDegrees - Is the given rotation in radians (false) or degrees (true)?
  9044. * @param {number} distance - An optional distance constraint between the Point and the anchor.
  9045. * @return {Phaser.Point} The modified point object.
  9046. */
  9047. Phaser.Point.rotate = function (a, x, y, angle, asDegrees, distance) {
  9048. asDegrees = asDegrees || false;
  9049. distance = distance || null;
  9050. if (asDegrees)
  9051. {
  9052. angle = Phaser.Math.degToRad(angle);
  9053. }
  9054. // Get distance from origin (cx/cy) to this point
  9055. if (distance === null)
  9056. {
  9057. distance = Math.sqrt(((x - a.x) * (x - a.x)) + ((y - a.y) * (y - a.y)));
  9058. }
  9059. return a.setTo(x + distance * Math.cos(angle), y + distance * Math.sin(angle));
  9060. };
  9061. /**
  9062. * Calculates centroid (or midpoint) from an array of points. If only one point is provided, that point is returned.
  9063. * @method Phaser.Point.centroid
  9064. * @param {Phaser.Point[]} points - The array of one or more points.
  9065. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created.
  9066. * @return {Phaser.Point} The new Point object.
  9067. */
  9068. Phaser.Point.centroid = function (points, out) {
  9069. if (typeof out === "undefined") { out = new Phaser.Point(); }
  9070. if (Object.prototype.toString.call(points) !== '[object Array]')
  9071. {
  9072. throw new Error("Phaser.Point. Parameter 'points' must be an array");
  9073. }
  9074. var pointslength = points.length;
  9075. if (pointslength < 1)
  9076. {
  9077. throw new Error("Phaser.Point. Parameter 'points' array must not be empty");
  9078. }
  9079. if (pointslength === 1)
  9080. {
  9081. out.copyFrom(points[0]);
  9082. return out;
  9083. }
  9084. for (var i = 0; i < pointslength; i++)
  9085. {
  9086. Phaser.Point.add(out, points[i], out);
  9087. }
  9088. out.divide(pointslength, pointslength);
  9089. return out;
  9090. };
  9091. // Because PIXI uses its own Point, we'll replace it with ours to avoid duplicating code or confusion.
  9092. PIXI.Point = Phaser.Point;
  9093. /**
  9094. * @author Richard Davey <rich@photonstorm.com>
  9095. * @copyright 2014 Photon Storm Ltd.
  9096. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  9097. */
  9098. /**
  9099. * Creates a new Rectangle object with the top-left corner specified by the x and y parameters and with the specified width and height parameters. If you call this function without parameters, a Rectangle with x, y, width, and height properties set to 0 is created.
  9100. *
  9101. * @class Phaser.Rectangle
  9102. * @constructor
  9103. * @param {number} x - The x coordinate of the top-left corner of the Rectangle.
  9104. * @param {number} y - The y coordinate of the top-left corner of the Rectangle.
  9105. * @param {number} width - The width of the Rectangle.
  9106. * @param {number} height - The height of the Rectangle.
  9107. * @return {Phaser.Rectangle} This Rectangle object.
  9108. */
  9109. Phaser.Rectangle = function (x, y, width, height) {
  9110. x = x || 0;
  9111. y = y || 0;
  9112. width = width || 0;
  9113. height = height || 0;
  9114. /**
  9115. * @property {number} x - The x coordinate of the top-left corner of the Rectangle.
  9116. */
  9117. this.x = x;
  9118. /**
  9119. * @property {number} y - The y coordinate of the top-left corner of the Rectangle.
  9120. */
  9121. this.y = y;
  9122. /**
  9123. * @property {number} width - The width of the Rectangle.
  9124. */
  9125. this.width = width;
  9126. /**
  9127. * @property {number} height - The height of the Rectangle.
  9128. */
  9129. this.height = height;
  9130. };
  9131. Phaser.Rectangle.prototype = {
  9132. /**
  9133. * Adjusts the location of the Rectangle object, as determined by its top-left corner, by the specified amounts.
  9134. * @method Phaser.Rectangle#offset
  9135. * @param {number} dx - Moves the x value of the Rectangle object by this amount.
  9136. * @param {number} dy - Moves the y value of the Rectangle object by this amount.
  9137. * @return {Phaser.Rectangle} This Rectangle object.
  9138. */
  9139. offset: function (dx, dy) {
  9140. this.x += dx;
  9141. this.y += dy;
  9142. return this;
  9143. },
  9144. /**
  9145. * Adjusts the location of the Rectangle object using a Point object as a parameter. This method is similar to the Rectangle.offset() method, except that it takes a Point object as a parameter.
  9146. * @method Phaser.Rectangle#offsetPoint
  9147. * @param {Phaser.Point} point - A Point object to use to offset this Rectangle object.
  9148. * @return {Phaser.Rectangle} This Rectangle object.
  9149. */
  9150. offsetPoint: function (point) {
  9151. return this.offset(point.x, point.y);
  9152. },
  9153. /**
  9154. * Sets the members of Rectangle to the specified values.
  9155. * @method Phaser.Rectangle#setTo
  9156. * @param {number} x - The x coordinate of the top-left corner of the Rectangle.
  9157. * @param {number} y - The y coordinate of the top-left corner of the Rectangle.
  9158. * @param {number} width - The width of the Rectangle in pixels.
  9159. * @param {number} height - The height of the Rectangle in pixels.
  9160. * @return {Phaser.Rectangle} This Rectangle object
  9161. */
  9162. setTo: function (x, y, width, height) {
  9163. this.x = x;
  9164. this.y = y;
  9165. this.width = width;
  9166. this.height = height;
  9167. return this;
  9168. },
  9169. /**
  9170. * Runs Math.floor() on both the x and y values of this Rectangle.
  9171. * @method Phaser.Rectangle#floor
  9172. */
  9173. floor: function () {
  9174. this.x = Math.floor(this.x);
  9175. this.y = Math.floor(this.y);
  9176. },
  9177. /**
  9178. * Runs Math.floor() on the x, y, width and height values of this Rectangle.
  9179. * @method Phaser.Rectangle#floorAll
  9180. */
  9181. floorAll: function () {
  9182. this.x = Math.floor(this.x);
  9183. this.y = Math.floor(this.y);
  9184. this.width = Math.floor(this.width);
  9185. this.height = Math.floor(this.height);
  9186. },
  9187. /**
  9188. * Copies the x, y, width and height properties from any given object to this Rectangle.
  9189. * @method Phaser.Rectangle#copyFrom
  9190. * @param {any} source - The object to copy from.
  9191. * @return {Phaser.Rectangle} This Rectangle object.
  9192. */
  9193. copyFrom: function (source) {
  9194. return this.setTo(source.x, source.y, source.width, source.height);
  9195. },
  9196. /**
  9197. * Copies the x, y, width and height properties from this Rectangle to any given object.
  9198. * @method Phaser.Rectangle#copyTo
  9199. * @param {any} source - The object to copy to.
  9200. * @return {object} This object.
  9201. */
  9202. copyTo: function (dest) {
  9203. dest.x = this.x;
  9204. dest.y = this.y;
  9205. dest.width = this.width;
  9206. dest.height = this.height;
  9207. return dest;
  9208. },
  9209. /**
  9210. * Increases the size of the Rectangle object by the specified amounts. The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, and to the top and the bottom by the dy value.
  9211. * @method Phaser.Rectangle#inflate
  9212. * @param {number} dx - The amount to be added to the left side of the Rectangle.
  9213. * @param {number} dy - The amount to be added to the bottom side of the Rectangle.
  9214. * @return {Phaser.Rectangle} This Rectangle object.
  9215. */
  9216. inflate: function (dx, dy) {
  9217. return Phaser.Rectangle.inflate(this, dx, dy);
  9218. },
  9219. /**
  9220. * The size of the Rectangle object, expressed as a Point object with the values of the width and height properties.
  9221. * @method Phaser.Rectangle#size
  9222. * @param {Phaser.Point} [output] - Optional Point object. If given the values will be set into the object, otherwise a brand new Point object will be created and returned.
  9223. * @return {Phaser.Point} The size of the Rectangle object.
  9224. */
  9225. size: function (output) {
  9226. return Phaser.Rectangle.size(this, output);
  9227. },
  9228. /**
  9229. * Returns a new Rectangle object with the same values for the x, y, width, and height properties as the original Rectangle object.
  9230. * @method Phaser.Rectangle#clone
  9231. * @param {Phaser.Rectangle} [output] - Optional Rectangle object. If given the values will be set into the object, otherwise a brand new Rectangle object will be created and returned.
  9232. * @return {Phaser.Rectangle}
  9233. */
  9234. clone: function (output) {
  9235. return Phaser.Rectangle.clone(this, output);
  9236. },
  9237. /**
  9238. * Determines whether the specified coordinates are contained within the region defined by this Rectangle object.
  9239. * @method Phaser.Rectangle#contains
  9240. * @param {number} x - The x coordinate of the point to test.
  9241. * @param {number} y - The y coordinate of the point to test.
  9242. * @return {boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
  9243. */
  9244. contains: function (x, y) {
  9245. return Phaser.Rectangle.contains(this, x, y);
  9246. },
  9247. /**
  9248. * Determines whether the first Rectangle object is fully contained within the second Rectangle object.
  9249. * A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first.
  9250. * @method Phaser.Rectangle#containsRect
  9251. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9252. * @return {boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
  9253. */
  9254. containsRect: function (b) {
  9255. return Phaser.Rectangle.containsRect(this, b);
  9256. },
  9257. /**
  9258. * Determines whether the two Rectangles are equal.
  9259. * This method compares the x, y, width and height properties of each Rectangle.
  9260. * @method Phaser.Rectangle#equals
  9261. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9262. * @return {boolean} A value of true if the two Rectangles have exactly the same values for the x, y, width and height properties; otherwise false.
  9263. */
  9264. equals: function (b) {
  9265. return Phaser.Rectangle.equals(this, b);
  9266. },
  9267. /**
  9268. * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, returns the area of intersection as a Rectangle object. If the Rectangles do not intersect, this method returns an empty Rectangle object with its properties set to 0.
  9269. * @method Phaser.Rectangle#intersection
  9270. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9271. * @param {Phaser.Rectangle} out - Optional Rectangle object. If given the intersection values will be set into this object, otherwise a brand new Rectangle object will be created and returned.
  9272. * @return {Phaser.Rectangle} A Rectangle object that equals the area of intersection. If the Rectangles do not intersect, this method returns an empty Rectangle object; that is, a Rectangle with its x, y, width, and height properties set to 0.
  9273. */
  9274. intersection: function (b, out) {
  9275. return Phaser.Rectangle.intersection(this, b, out);
  9276. },
  9277. /**
  9278. * Determines whether the two Rectangles intersect with each other.
  9279. * This method checks the x, y, width, and height properties of the Rectangles.
  9280. * @method Phaser.Rectangle#intersects
  9281. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9282. * @param {number} tolerance - A tolerance value to allow for an intersection test with padding, default to 0.
  9283. * @return {boolean} A value of true if the specified object intersects with this Rectangle object; otherwise false.
  9284. */
  9285. intersects: function (b, tolerance) {
  9286. return Phaser.Rectangle.intersects(this, b, tolerance);
  9287. },
  9288. /**
  9289. * Determines whether the object specified intersects (overlaps) with the given values.
  9290. * @method Phaser.Rectangle#intersectsRaw
  9291. * @param {number} left - Description.
  9292. * @param {number} right - Description.
  9293. * @param {number} top - Description.
  9294. * @param {number} bottomt - Description.
  9295. * @param {number} tolerance - A tolerance value to allow for an intersection test with padding, default to 0
  9296. * @return {boolean} A value of true if the specified object intersects with the Rectangle; otherwise false.
  9297. */
  9298. intersectsRaw: function (left, right, top, bottom, tolerance) {
  9299. return Phaser.Rectangle.intersectsRaw(this, left, right, top, bottom, tolerance);
  9300. },
  9301. /**
  9302. * Adds two Rectangles together to create a new Rectangle object, by filling in the horizontal and vertical space between the two Rectangles.
  9303. * @method Phaser.Rectangle#union
  9304. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9305. * @param {Phaser.Rectangle} [out] - Optional Rectangle object. If given the new values will be set into this object, otherwise a brand new Rectangle object will be created and returned.
  9306. * @return {Phaser.Rectangle} A Rectangle object that is the union of the two Rectangles.
  9307. */
  9308. union: function (b, out) {
  9309. return Phaser.Rectangle.union(this, b, out);
  9310. },
  9311. /**
  9312. * Returns a string representation of this object.
  9313. * @method Phaser.Rectangle#toString
  9314. * @return {string} A string representation of the instance.
  9315. */
  9316. toString: function () {
  9317. return "[{Rectangle (x=" + this.x + " y=" + this.y + " width=" + this.width + " height=" + this.height + " empty=" + this.empty + ")}]";
  9318. }
  9319. };
  9320. /**
  9321. * @name Phaser.Rectangle#halfWidth
  9322. * @property {number} halfWidth - Half of the width of the Rectangle.
  9323. * @readonly
  9324. */
  9325. Object.defineProperty(Phaser.Rectangle.prototype, "halfWidth", {
  9326. get: function () {
  9327. return Math.round(this.width / 2);
  9328. }
  9329. });
  9330. /**
  9331. * @name Phaser.Rectangle#halfHeight
  9332. * @property {number} halfHeight - Half of the height of the Rectangle.
  9333. * @readonly
  9334. */
  9335. Object.defineProperty(Phaser.Rectangle.prototype, "halfHeight", {
  9336. get: function () {
  9337. return Math.round(this.height / 2);
  9338. }
  9339. });
  9340. /**
  9341. * The sum of the y and height properties. Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property.
  9342. * @name Phaser.Rectangle#bottom
  9343. * @property {number} bottom - The sum of the y and height properties.
  9344. */
  9345. Object.defineProperty(Phaser.Rectangle.prototype, "bottom", {
  9346. get: function () {
  9347. return this.y + this.height;
  9348. },
  9349. set: function (value) {
  9350. if (value <= this.y) {
  9351. this.height = 0;
  9352. } else {
  9353. this.height = (this.y - value);
  9354. }
  9355. }
  9356. });
  9357. /**
  9358. * The location of the Rectangles bottom right corner as a Point object.
  9359. * @name Phaser.Rectangle#bottom
  9360. * @property {Phaser.Point} bottomRight - Gets or sets the location of the Rectangles bottom right corner as a Point object.
  9361. */
  9362. Object.defineProperty(Phaser.Rectangle.prototype, "bottomRight", {
  9363. get: function () {
  9364. return new Phaser.Point(this.right, this.bottom);
  9365. },
  9366. set: function (value) {
  9367. this.right = value.x;
  9368. this.bottom = value.y;
  9369. }
  9370. });
  9371. /**
  9372. * The x coordinate of the left of the Rectangle. Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property.
  9373. * @name Phaser.Rectangle#left
  9374. * @property {number} left - The x coordinate of the left of the Rectangle.
  9375. */
  9376. Object.defineProperty(Phaser.Rectangle.prototype, "left", {
  9377. get: function () {
  9378. return this.x;
  9379. },
  9380. set: function (value) {
  9381. if (value >= this.right) {
  9382. this.width = 0;
  9383. } else {
  9384. this.width = this.right - value;
  9385. }
  9386. this.x = value;
  9387. }
  9388. });
  9389. /**
  9390. * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties, however it does affect the width property.
  9391. * @name Phaser.Rectangle#right
  9392. * @property {number} right - The sum of the x and width properties.
  9393. */
  9394. Object.defineProperty(Phaser.Rectangle.prototype, "right", {
  9395. get: function () {
  9396. return this.x + this.width;
  9397. },
  9398. set: function (value) {
  9399. if (value <= this.x) {
  9400. this.width = 0;
  9401. } else {
  9402. this.width = this.x + value;
  9403. }
  9404. }
  9405. });
  9406. /**
  9407. * The volume of the Rectangle derived from width * height.
  9408. * @name Phaser.Rectangle#volume
  9409. * @property {number} volume - The volume of the Rectangle derived from width * height.
  9410. * @readonly
  9411. */
  9412. Object.defineProperty(Phaser.Rectangle.prototype, "volume", {
  9413. get: function () {
  9414. return this.width * this.height;
  9415. }
  9416. });
  9417. /**
  9418. * The perimeter size of the Rectangle. This is the sum of all 4 sides.
  9419. * @name Phaser.Rectangle#perimeter
  9420. * @property {number} perimeter - The perimeter size of the Rectangle. This is the sum of all 4 sides.
  9421. * @readonly
  9422. */
  9423. Object.defineProperty(Phaser.Rectangle.prototype, "perimeter", {
  9424. get: function () {
  9425. return (this.width * 2) + (this.height * 2);
  9426. }
  9427. });
  9428. /**
  9429. * The x coordinate of the center of the Rectangle.
  9430. * @name Phaser.Rectangle#centerX
  9431. * @property {number} centerX - The x coordinate of the center of the Rectangle.
  9432. */
  9433. Object.defineProperty(Phaser.Rectangle.prototype, "centerX", {
  9434. get: function () {
  9435. return this.x + this.halfWidth;
  9436. },
  9437. set: function (value) {
  9438. this.x = value - this.halfWidth;
  9439. }
  9440. });
  9441. /**
  9442. * The y coordinate of the center of the Rectangle.
  9443. * @name Phaser.Rectangle#centerY
  9444. * @property {number} centerY - The y coordinate of the center of the Rectangle.
  9445. */
  9446. Object.defineProperty(Phaser.Rectangle.prototype, "centerY", {
  9447. get: function () {
  9448. return this.y + this.halfHeight;
  9449. },
  9450. set: function (value) {
  9451. this.y = value - this.halfHeight;
  9452. }
  9453. });
  9454. /**
  9455. * The y coordinate of the top of the Rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties.
  9456. * However it does affect the height property, whereas changing the y value does not affect the height property.
  9457. * @name Phaser.Rectangle#top
  9458. * @property {number} top - The y coordinate of the top of the Rectangle.
  9459. */
  9460. Object.defineProperty(Phaser.Rectangle.prototype, "top", {
  9461. get: function () {
  9462. return this.y;
  9463. },
  9464. set: function (value) {
  9465. if (value >= this.bottom) {
  9466. this.height = 0;
  9467. this.y = value;
  9468. } else {
  9469. this.height = (this.bottom - value);
  9470. }
  9471. }
  9472. });
  9473. /**
  9474. * The location of the Rectangles top left corner as a Point object.
  9475. * @name Phaser.Rectangle#topLeft
  9476. * @property {Phaser.Point} topLeft - The location of the Rectangles top left corner as a Point object.
  9477. */
  9478. Object.defineProperty(Phaser.Rectangle.prototype, "topLeft", {
  9479. get: function () {
  9480. return new Phaser.Point(this.x, this.y);
  9481. },
  9482. set: function (value) {
  9483. this.x = value.x;
  9484. this.y = value.y;
  9485. }
  9486. });
  9487. /**
  9488. * Determines whether or not this Rectangle object is empty. A Rectangle object is empty if its width or height is less than or equal to 0.
  9489. * If set to true then all of the Rectangle properties are set to 0.
  9490. * @name Phaser.Rectangle#empty
  9491. * @property {boolean} empty - Gets or sets the Rectangles empty state.
  9492. */
  9493. Object.defineProperty(Phaser.Rectangle.prototype, "empty", {
  9494. get: function () {
  9495. return (!this.width || !this.height);
  9496. },
  9497. set: function (value) {
  9498. if (value === true)
  9499. {
  9500. this.setTo(0, 0, 0, 0);
  9501. }
  9502. }
  9503. });
  9504. Phaser.Rectangle.prototype.constructor = Phaser.Rectangle;
  9505. /**
  9506. * Increases the size of the Rectangle object by the specified amounts. The center point of the Rectangle object stays the same, and its size increases to the left and right by the dx value, and to the top and the bottom by the dy value.
  9507. * @method Phaser.Rectangle.inflate
  9508. * @param {Phaser.Rectangle} a - The Rectangle object.
  9509. * @param {number} dx - The amount to be added to the left side of the Rectangle.
  9510. * @param {number} dy - The amount to be added to the bottom side of the Rectangle.
  9511. * @return {Phaser.Rectangle} This Rectangle object.
  9512. */
  9513. Phaser.Rectangle.inflate = function (a, dx, dy) {
  9514. a.x -= dx;
  9515. a.width += 2 * dx;
  9516. a.y -= dy;
  9517. a.height += 2 * dy;
  9518. return a;
  9519. };
  9520. /**
  9521. * Increases the size of the Rectangle object. This method is similar to the Rectangle.inflate() method except it takes a Point object as a parameter.
  9522. * @method Phaser.Rectangle.inflatePoint
  9523. * @param {Phaser.Rectangle} a - The Rectangle object.
  9524. * @param {Phaser.Point} point - The x property of this Point object is used to increase the horizontal dimension of the Rectangle object. The y property is used to increase the vertical dimension of the Rectangle object.
  9525. * @return {Phaser.Rectangle} The Rectangle object.
  9526. */
  9527. Phaser.Rectangle.inflatePoint = function (a, point) {
  9528. return Phaser.Rectangle.inflate(a, point.x, point.y);
  9529. };
  9530. /**
  9531. * The size of the Rectangle object, expressed as a Point object with the values of the width and height properties.
  9532. * @method Phaser.Rectangle.size
  9533. * @param {Phaser.Rectangle} a - The Rectangle object.
  9534. * @param {Phaser.Point} [output] - Optional Point object. If given the values will be set into the object, otherwise a brand new Point object will be created and returned.
  9535. * @return {Phaser.Point} The size of the Rectangle object
  9536. */
  9537. Phaser.Rectangle.size = function (a, output) {
  9538. if (typeof output === "undefined")
  9539. {
  9540. output = new Phaser.Point(a.width, a.height);
  9541. }
  9542. else
  9543. {
  9544. output.setTo(a.width, a.height);
  9545. }
  9546. return output;
  9547. };
  9548. /**
  9549. * Returns a new Rectangle object with the same values for the x, y, width, and height properties as the original Rectangle object.
  9550. * @method Phaser.Rectangle.clone
  9551. * @param {Phaser.Rectangle} a - The Rectangle object.
  9552. * @param {Phaser.Rectangle} [output] - Optional Rectangle object. If given the values will be set into the object, otherwise a brand new Rectangle object will be created and returned.
  9553. * @return {Phaser.Rectangle}
  9554. */
  9555. Phaser.Rectangle.clone = function (a, output) {
  9556. if (typeof output === "undefined")
  9557. {
  9558. output = new Phaser.Rectangle(a.x, a.y, a.width, a.height);
  9559. }
  9560. else
  9561. {
  9562. output.setTo(a.x, a.y, a.width, a.height);
  9563. }
  9564. return output;
  9565. };
  9566. /**
  9567. * Determines whether the specified coordinates are contained within the region defined by this Rectangle object.
  9568. * @method Phaser.Rectangle.contains
  9569. * @param {Phaser.Rectangle} a - The Rectangle object.
  9570. * @param {number} x - The x coordinate of the point to test.
  9571. * @param {number} y - The y coordinate of the point to test.
  9572. * @return {boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
  9573. */
  9574. Phaser.Rectangle.contains = function (a, x, y) {
  9575. if (a.width <= 0 || a.height <= 0)
  9576. {
  9577. return false;
  9578. }
  9579. return (x >= a.x && x <= a.right && y >= a.y && y <= a.bottom);
  9580. };
  9581. /**
  9582. * Determines whether the specified coordinates are contained within the region defined by the given raw values.
  9583. * @method Phaser.Rectangle.containsRaw
  9584. * @param {number} rx - The x coordinate of the top left of the area.
  9585. * @param {number} ry - The y coordinate of the top left of the area.
  9586. * @param {number} rw - The width of the area.
  9587. * @param {number} rh - The height of the area.
  9588. * @param {number} x - The x coordinate of the point to test.
  9589. * @param {number} y - The y coordinate of the point to test.
  9590. * @return {boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
  9591. */
  9592. Phaser.Rectangle.containsRaw = function (rx, ry, rw, rh, x, y) {
  9593. return (x >= rx && x <= (rx + rw) && y >= ry && y <= (ry + rh));
  9594. };
  9595. /**
  9596. * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. This method is similar to the Rectangle.contains() method, except that it takes a Point object as a parameter.
  9597. * @method Phaser.Rectangle.containsPoint
  9598. * @param {Phaser.Rectangle} a - The Rectangle object.
  9599. * @param {Phaser.Point} point - The point object being checked. Can be Point or any object with .x and .y values.
  9600. * @return {boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
  9601. */
  9602. Phaser.Rectangle.containsPoint = function (a, point) {
  9603. return Phaser.Rectangle.contains(a, point.x, point.y);
  9604. };
  9605. /**
  9606. * Determines whether the first Rectangle object is fully contained within the second Rectangle object.
  9607. * A Rectangle object is said to contain another if the second Rectangle object falls entirely within the boundaries of the first.
  9608. * @method Phaser.Rectangle.containsRect
  9609. * @param {Phaser.Rectangle} a - The first Rectangle object.
  9610. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9611. * @return {boolean} A value of true if the Rectangle object contains the specified point; otherwise false.
  9612. */
  9613. Phaser.Rectangle.containsRect = function (a, b) {
  9614. // If the given rect has a larger volume than this one then it can never contain it
  9615. if (a.volume > b.volume)
  9616. {
  9617. return false;
  9618. }
  9619. return (a.x >= b.x && a.y >= b.y && a.right <= b.right && a.bottom <= b.bottom);
  9620. };
  9621. /**
  9622. * Determines whether the two Rectangles are equal.
  9623. * This method compares the x, y, width and height properties of each Rectangle.
  9624. * @method Phaser.Rectangle.equals
  9625. * @param {Phaser.Rectangle} a - The first Rectangle object.
  9626. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9627. * @return {boolean} A value of true if the two Rectangles have exactly the same values for the x, y, width and height properties; otherwise false.
  9628. */
  9629. Phaser.Rectangle.equals = function (a, b) {
  9630. return (a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height);
  9631. };
  9632. /**
  9633. * If the Rectangle object specified in the toIntersect parameter intersects with this Rectangle object, returns the area of intersection as a Rectangle object. If the Rectangles do not intersect, this method returns an empty Rectangle object with its properties set to 0.
  9634. * @method Phaser.Rectangle.intersection
  9635. * @param {Phaser.Rectangle} a - The first Rectangle object.
  9636. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9637. * @param {Phaser.Rectangle} [output] - Optional Rectangle object. If given the intersection values will be set into this object, otherwise a brand new Rectangle object will be created and returned.
  9638. * @return {Phaser.Rectangle} A Rectangle object that equals the area of intersection. If the Rectangles do not intersect, this method returns an empty Rectangle object; that is, a Rectangle with its x, y, width, and height properties set to 0.
  9639. */
  9640. Phaser.Rectangle.intersection = function (a, b, output) {
  9641. if (typeof output === "undefined")
  9642. {
  9643. output = new Phaser.Rectangle();
  9644. }
  9645. if (Phaser.Rectangle.intersects(a, b))
  9646. {
  9647. output.x = Math.max(a.x, b.x);
  9648. output.y = Math.max(a.y, b.y);
  9649. output.width = Math.min(a.right, b.right) - output.x;
  9650. output.height = Math.min(a.bottom, b.bottom) - output.y;
  9651. }
  9652. return output;
  9653. };
  9654. /**
  9655. * Determines whether the two Rectangles intersect with each other.
  9656. * This method checks the x, y, width, and height properties of the Rectangles.
  9657. * @method Phaser.Rectangle.intersects
  9658. * @param {Phaser.Rectangle} a - The first Rectangle object.
  9659. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9660. * @return {boolean} A value of true if the specified object intersects with this Rectangle object; otherwise false.
  9661. */
  9662. Phaser.Rectangle.intersects = function (a, b) {
  9663. if (a.width <= 0 || a.height <= 0 || b.width <= 0 || b.height <= 0)
  9664. {
  9665. return false;
  9666. }
  9667. return !(a.right < b.x || a.bottom < b.y || a.x > b.right || a.y > b.bottom);
  9668. };
  9669. /**
  9670. * Determines whether the object specified intersects (overlaps) with the given values.
  9671. * @method Phaser.Rectangle.intersectsRaw
  9672. * @param {number} left - Description.
  9673. * @param {number} right - Description.
  9674. * @param {number} top - Description.
  9675. * @param {number} bottom - Description.
  9676. * @param {number} tolerance - A tolerance value to allow for an intersection test with padding, default to 0
  9677. * @return {boolean} A value of true if the specified object intersects with the Rectangle; otherwise false.
  9678. */
  9679. Phaser.Rectangle.intersectsRaw = function (a, left, right, top, bottom, tolerance) {
  9680. if (typeof tolerance === "undefined") { tolerance = 0; }
  9681. return !(left > a.right + tolerance || right < a.left - tolerance || top > a.bottom + tolerance || bottom < a.top - tolerance);
  9682. };
  9683. /**
  9684. * Adds two Rectangles together to create a new Rectangle object, by filling in the horizontal and vertical space between the two Rectangles.
  9685. * @method Phaser.Rectangle.union
  9686. * @param {Phaser.Rectangle} a - The first Rectangle object.
  9687. * @param {Phaser.Rectangle} b - The second Rectangle object.
  9688. * @param {Phaser.Rectangle} [output] - Optional Rectangle object. If given the new values will be set into this object, otherwise a brand new Rectangle object will be created and returned.
  9689. * @return {Phaser.Rectangle} A Rectangle object that is the union of the two Rectangles.
  9690. */
  9691. Phaser.Rectangle.union = function (a, b, output) {
  9692. if (typeof output === "undefined")
  9693. {
  9694. output = new Phaser.Rectangle();
  9695. }
  9696. return output.setTo(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.max(a.right, b.right) - Math.min(a.left, b.left), Math.max(a.bottom, b.bottom) - Math.min(a.top, b.top));
  9697. };
  9698. // Because PIXI uses its own Rectangle, we'll replace it with ours to avoid duplicating code or confusion.
  9699. PIXI.Rectangle = Phaser.Rectangle;
  9700. PIXI.EmptyRectangle = new Phaser.Rectangle(0, 0, 0, 0);
  9701. /**
  9702. * @author Richard Davey <rich@photonstorm.com>
  9703. * @copyright 2014 Photon Storm Ltd.
  9704. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  9705. */
  9706. /**
  9707. * Creates a new Line object with a start and an end point.
  9708. * @class Line
  9709. * @classdesc Phaser - Line
  9710. * @constructor
  9711. * @param {number} [x1=0] - The x coordinate of the start of the line.
  9712. * @param {number} [y1=0] - The y coordinate of the start of the line.
  9713. * @param {number} [x2=0] - The x coordinate of the end of the line.
  9714. * @param {number} [y2=0] - The y coordinate of the end of the line.
  9715. * @return {Phaser.Line} This line object
  9716. */
  9717. Phaser.Line = function (x1, y1, x2, y2) {
  9718. x1 = x1 || 0;
  9719. y1 = y1 || 0;
  9720. x2 = x2 || 0;
  9721. y2 = y2 || 0;
  9722. /**
  9723. * @property {Phaser.Point} start - The start point of the line.
  9724. */
  9725. this.start = new Phaser.Point(x1, y1);
  9726. /**
  9727. * @property {Phaser.Point} end - The end point of the line.
  9728. */
  9729. this.end = new Phaser.Point(x2, y2);
  9730. };
  9731. Phaser.Line.prototype = {
  9732. /**
  9733. * Sets the components of the Line to the specified values.
  9734. * @method Phaser.Line#setTo
  9735. * @param {number} [x1=0] - The x coordinate of the start of the line.
  9736. * @param {number} [y1=0] - The y coordinate of the start of the line.
  9737. * @param {number} [x2=0] - The x coordinate of the end of the line.
  9738. * @param {number} [y2=0] - The y coordinate of the end of the line.
  9739. * @return {Phaser.Line} This line object
  9740. */
  9741. setTo: function (x1, y1, x2, y2) {
  9742. this.start.setTo(x1, y1);
  9743. this.end.setTo(x2, y2);
  9744. return this;
  9745. },
  9746. /**
  9747. * Sets the line to match the x/y coordinates of the two given sprites.
  9748. * Can optionally be calculated from their center coordinates.
  9749. * @method Phaser.Line#fromSprite
  9750. * @param {Phaser.Sprite} startSprite - The coordinates of this Sprite will be set to the Line.start point.
  9751. * @param {Phaser.Sprite} endSprite - The coordinates of this Sprite will be set to the Line.start point.
  9752. * @param {boolean} [useCenter=false] - If true it will use startSprite.center.x, if false startSprite.x. Note that Sprites don't have a center property by default, so only enable if you've over-ridden your Sprite with a custom class.
  9753. * @return {Phaser.Line} This line object
  9754. */
  9755. fromSprite: function (startSprite, endSprite, useCenter) {
  9756. if (typeof useCenter === 'undefined') { useCenter = false; }
  9757. if (useCenter)
  9758. {
  9759. return this.setTo(startSprite.center.x, startSprite.center.y, endSprite.center.x, endSprite.center.y);
  9760. }
  9761. else
  9762. {
  9763. return this.setTo(startSprite.x, startSprite.y, endSprite.x, endSprite.y);
  9764. }
  9765. },
  9766. /**
  9767. * Checks for intersection between this line and another Line.
  9768. * If asSegment is true it will check for segment intersection. If asSegment is false it will check for line intersection.
  9769. * Returns the intersection segment of AB and EF as a Point, or null if there is no intersection.
  9770. *
  9771. * @method Phaser.Line#intersects
  9772. * @param {Phaser.Line} line - The line to check against this one.
  9773. * @param {boolean} [asSegment=true] - If true it will check for segment intersection, otherwise full line intersection.
  9774. * @param {Phaser.Point} [result] - A Point object to store the result in, if not given a new one will be created.
  9775. * @return {Phaser.Point} The intersection segment of the two lines as a Point, or null if there is no intersection.
  9776. */
  9777. intersects: function (line, asSegment, result) {
  9778. return Phaser.Line.intersectsPoints(this.start, this.end, line.start, line.end, asSegment, result);
  9779. },
  9780. /**
  9781. * Tests if the given coordinates fall on this line. See pointOnSegment to test against just the line segment.
  9782. * @method Phaser.Line#pointOnLine
  9783. * @param {number} x - The line to check against this one.
  9784. * @param {number} y - The line to check against this one.
  9785. * @return {boolean} True if the point is on the line, false if not.
  9786. */
  9787. pointOnLine: function (x, y) {
  9788. return ((x - this.start.x) * (this.end.y - this.end.y) === (this.end.x - this.start.x) * (y - this.end.y));
  9789. },
  9790. /**
  9791. * Tests if the given coordinates fall on this line and within the segment. See pointOnLine to test against just the line.
  9792. * @method Phaser.Line#pointOnSegment
  9793. * @param {number} x - The line to check against this one.
  9794. * @param {number} y - The line to check against this one.
  9795. * @return {boolean} True if the point is on the line and segment, false if not.
  9796. */
  9797. pointOnSegment: function (x, y) {
  9798. var xMin = Math.min(this.start.x, this.end.x);
  9799. var xMax = Math.max(this.start.x, this.end.x);
  9800. var yMin = Math.min(this.start.y, this.end.y);
  9801. var yMax = Math.max(this.start.y, this.end.y);
  9802. return (this.pointOnLine(x, y) && (x >= xMin && x <= xMax) && (y >= yMin && y <= yMax));
  9803. },
  9804. /**
  9805. * Using Bresenham's line algorithm this will return an array of all coordinates on this line.
  9806. * The start and end points are rounded before this runs as the algorithm works on integers.
  9807. *
  9808. * @method Phaser.Line#coordinatesOnLine
  9809. * @param {number} [stepRate=1] - How many steps will we return? 1 = every coordinate on the line, 2 = every other coordinate, etc.
  9810. * @param {array} [results] - The array to store the results in. If not provided a new one will be generated.
  9811. * @return {array} An array of coordinates.
  9812. */
  9813. coordinatesOnLine: function (stepRate, results) {
  9814. if (typeof stepRate === 'undefined') { stepRate = 1; }
  9815. if (typeof results === 'undefined') { results = []; }
  9816. var x1 = Math.round(this.start.x);
  9817. var y1 = Math.round(this.start.y);
  9818. var x2 = Math.round(this.end.x);
  9819. var y2 = Math.round(this.end.y);
  9820. var dx = Math.abs(x2 - x1);
  9821. var dy = Math.abs(y2 - y1);
  9822. var sx = (x1 < x2) ? 1 : -1;
  9823. var sy = (y1 < y2) ? 1 : -1;
  9824. var err = dx - dy;
  9825. results.push([x1, y1]);
  9826. var i = 1;
  9827. while (!((x1 == x2) && (y1 == y2)))
  9828. {
  9829. var e2 = err << 1;
  9830. if (e2 > -dy)
  9831. {
  9832. err -= dy;
  9833. x1 += sx;
  9834. }
  9835. if (e2 < dx)
  9836. {
  9837. err += dx;
  9838. y1 += sy;
  9839. }
  9840. if (i % stepRate === 0)
  9841. {
  9842. results.push([x1, y1]);
  9843. }
  9844. i++;
  9845. }
  9846. return results;
  9847. }
  9848. };
  9849. /**
  9850. * @name Phaser.Line#length
  9851. * @property {number} length - Gets the length of the line segment.
  9852. * @readonly
  9853. */
  9854. Object.defineProperty(Phaser.Line.prototype, "length", {
  9855. get: function () {
  9856. return Math.sqrt((this.end.x - this.start.x) * (this.end.x - this.start.x) + (this.end.y - this.start.y) * (this.end.y - this.start.y));
  9857. }
  9858. });
  9859. /**
  9860. * @name Phaser.Line#angle
  9861. * @property {number} angle - Gets the angle of the line.
  9862. * @readonly
  9863. */
  9864. Object.defineProperty(Phaser.Line.prototype, "angle", {
  9865. get: function () {
  9866. return Math.atan2(this.end.x - this.start.x, this.end.y - this.start.y);
  9867. }
  9868. });
  9869. /**
  9870. * @name Phaser.Line#slope
  9871. * @property {number} slope - Gets the slope of the line (y/x).
  9872. * @readonly
  9873. */
  9874. Object.defineProperty(Phaser.Line.prototype, "slope", {
  9875. get: function () {
  9876. return (this.end.y - this.start.y) / (this.end.x - this.start.x);
  9877. }
  9878. });
  9879. /**
  9880. * @name Phaser.Line#perpSlope
  9881. * @property {number} perpSlope - Gets the perpendicular slope of the line (x/y).
  9882. * @readonly
  9883. */
  9884. Object.defineProperty(Phaser.Line.prototype, "perpSlope", {
  9885. get: function () {
  9886. return -((this.end.x - this.start.x) / (this.end.y - this.start.y));
  9887. }
  9888. });
  9889. /**
  9890. * @name Phaser.Line#x
  9891. * @property {number} x - Gets the x coordinate of the top left of the bounds around this line.
  9892. * @readonly
  9893. */
  9894. Object.defineProperty(Phaser.Line.prototype, "x", {
  9895. get: function () {
  9896. return Math.min(this.start.x, this.end.x);
  9897. }
  9898. });
  9899. /**
  9900. * @name Phaser.Line#y
  9901. * @property {number} y - Gets the y coordinate of the top left of the bounds around this line.
  9902. * @readonly
  9903. */
  9904. Object.defineProperty(Phaser.Line.prototype, "y", {
  9905. get: function () {
  9906. return Math.min(this.start.y, this.end.y);
  9907. }
  9908. });
  9909. /**
  9910. * @name Phaser.Line#left
  9911. * @property {number} left - Gets the left-most point of this line.
  9912. * @readonly
  9913. */
  9914. Object.defineProperty(Phaser.Line.prototype, "left", {
  9915. get: function () {
  9916. return Math.min(this.start.x, this.end.x);
  9917. }
  9918. });
  9919. /**
  9920. * @name Phaser.Line#right
  9921. * @property {number} right - Gets the right-most point of this line.
  9922. * @readonly
  9923. */
  9924. Object.defineProperty(Phaser.Line.prototype, "right", {
  9925. get: function () {
  9926. return Math.max(this.start.x, this.end.x);
  9927. }
  9928. });
  9929. /**
  9930. * @name Phaser.Line#top
  9931. * @property {number} top - Gets the top-most point of this line.
  9932. * @readonly
  9933. */
  9934. Object.defineProperty(Phaser.Line.prototype, "top", {
  9935. get: function () {
  9936. return Math.min(this.start.y, this.end.y);
  9937. }
  9938. });
  9939. /**
  9940. * @name Phaser.Line#bottom
  9941. * @property {number} bottom - Gets the bottom-most point of this line.
  9942. * @readonly
  9943. */
  9944. Object.defineProperty(Phaser.Line.prototype, "bottom", {
  9945. get: function () {
  9946. return Math.max(this.start.y, this.end.y);
  9947. }
  9948. });
  9949. /**
  9950. * @name Phaser.Line#width
  9951. * @property {number} width - Gets the width of this bounds of this line.
  9952. * @readonly
  9953. */
  9954. Object.defineProperty(Phaser.Line.prototype, "width", {
  9955. get: function () {
  9956. return Math.abs(this.start.x - this.end.x);
  9957. }
  9958. });
  9959. /**
  9960. * @name Phaser.Line#height
  9961. * @property {number} height - Gets the height of this bounds of this line.
  9962. * @readonly
  9963. */
  9964. Object.defineProperty(Phaser.Line.prototype, "height", {
  9965. get: function () {
  9966. return Math.abs(this.start.y - this.end.y);
  9967. }
  9968. });
  9969. /**
  9970. * Checks for intersection between two lines as defined by the given start and end points.
  9971. * If asSegment is true it will check for line segment intersection. If asSegment is false it will check for line intersection.
  9972. * Returns the intersection segment of AB and EF as a Point, or null if there is no intersection.
  9973. * Adapted from code by Keith Hair
  9974. *
  9975. * @method Phaser.Line.intersectsPoints
  9976. * @param {Phaser.Point} a - The start of the first Line to be checked.
  9977. * @param {Phaser.Point} b - The end of the first line to be checked.
  9978. * @param {Phaser.Point} e - The start of the second Line to be checked.
  9979. * @param {Phaser.Point} f - The end of the second line to be checked.
  9980. * @param {boolean} [asSegment=true] - If true it will check for segment intersection, otherwise full line intersection.
  9981. * @param {Phaser.Point} [result] - A Point object to store the result in, if not given a new one will be created.
  9982. * @return {Phaser.Point} The intersection segment of the two lines as a Point, or null if there is no intersection.
  9983. */
  9984. Phaser.Line.intersectsPoints = function (a, b, e, f, asSegment, result) {
  9985. if (typeof asSegment === 'undefined') { asSegment = true; }
  9986. if (typeof result === 'undefined') { result = new Phaser.Point(); }
  9987. var a1 = b.y - a.y;
  9988. var a2 = f.y - e.y;
  9989. var b1 = a.x - b.x;
  9990. var b2 = e.x - f.x;
  9991. var c1 = (b.x * a.y) - (a.x * b.y);
  9992. var c2 = (f.x * e.y) - (e.x * f.y);
  9993. var denom = (a1 * b2) - (a2 * b1);
  9994. if (denom === 0)
  9995. {
  9996. return null;
  9997. }
  9998. result.x = ((b1 * c2) - (b2 * c1)) / denom;
  9999. result.y = ((a2 * c1) - (a1 * c2)) / denom;
  10000. if (asSegment)
  10001. {
  10002. if (Math.pow((result.x - b.x) + (result.y - b.y), 2) > Math.pow((a.x - b.x) + (a.y - b.y), 2))
  10003. {
  10004. return null;
  10005. }
  10006. if (Math.pow((result.x - a.x) + (result.y - a.y), 2) > Math.pow((a.x - b.x) + (a.y - b.y), 2))
  10007. {
  10008. return null;
  10009. }
  10010. if (Math.pow((result.x - f.x) + (result.y - f.y), 2) > Math.pow((e.x - f.x) + (e.y - f.y), 2))
  10011. {
  10012. return null;
  10013. }
  10014. if (Math.pow((result.x - e.x) + (result.y - e.y), 2) > Math.pow((e.x - f.x) + (e.y - f.y), 2))
  10015. {
  10016. return null;
  10017. }
  10018. }
  10019. return result;
  10020. };
  10021. /**
  10022. * Checks for intersection between two lines.
  10023. * If asSegment is true it will check for segment intersection.
  10024. * If asSegment is false it will check for line intersection.
  10025. * Returns the intersection segment of AB and EF as a Point, or null if there is no intersection.
  10026. * Adapted from code by Keith Hair
  10027. *
  10028. * @method Phaser.Line.intersects
  10029. * @param {Phaser.Line} a - The first Line to be checked.
  10030. * @param {Phaser.Line} b - The second Line to be checked.
  10031. * @param {boolean} [asSegment=true] - If true it will check for segment intersection, otherwise full line intersection.
  10032. * @param {Phaser.Point} [result] - A Point object to store the result in, if not given a new one will be created.
  10033. * @return {Phaser.Point} The intersection segment of the two lines as a Point, or null if there is no intersection.
  10034. */
  10035. Phaser.Line.intersects = function (a, b, asSegment, result) {
  10036. return Phaser.Line.intersectsPoints(a.start, a.end, b.start, b.end, asSegment, result);
  10037. };
  10038. /**
  10039. * @author Richard Davey <rich@photonstorm.com>
  10040. * @author Chad Engler <chad@pantherdev.com>
  10041. * @copyright 2014 Photon Storm Ltd.
  10042. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  10043. */
  10044. /**
  10045. * Creates a Ellipse object. A curve on a plane surrounding two focal points.
  10046. * @class Ellipse
  10047. * @classdesc Phaser - Ellipse
  10048. * @constructor
  10049. * @param {number} [x=0] - The X coordinate of the upper-left corner of the framing rectangle of this ellipse.
  10050. * @param {number} [y=0] - The Y coordinate of the upper-left corner of the framing rectangle of this ellipse.
  10051. * @param {number} [width=0] - The overall width of this ellipse.
  10052. * @param {number} [height=0] - The overall height of this ellipse.
  10053. * @return {Phaser.Ellipse} This Ellipse object
  10054. */
  10055. Phaser.Ellipse = function (x, y, width, height) {
  10056. this.type = Phaser.ELLIPSE;
  10057. x = x || 0;
  10058. y = y || 0;
  10059. width = width || 0;
  10060. height = height || 0;
  10061. /**
  10062. * @property {number} x - The X coordinate of the upper-left corner of the framing rectangle of this ellipse.
  10063. */
  10064. this.x = x;
  10065. /**
  10066. * @property {number} y - The Y coordinate of the upper-left corner of the framing rectangle of this ellipse.
  10067. */
  10068. this.y = y;
  10069. /**
  10070. * @property {number} width - The overall width of this ellipse.
  10071. */
  10072. this.width = width;
  10073. /**
  10074. * @property {number} height - The overall height of this ellipse.
  10075. */
  10076. this.height = height;
  10077. };
  10078. Phaser.Ellipse.prototype = {
  10079. /**
  10080. * Sets the members of the Ellipse to the specified values.
  10081. * @method Phaser.Ellipse#setTo
  10082. * @param {number} x - The X coordinate of the upper-left corner of the framing rectangle of this ellipse.
  10083. * @param {number} y - The Y coordinate of the upper-left corner of the framing rectangle of this ellipse.
  10084. * @param {number} width - The overall width of this ellipse.
  10085. * @param {number} height - The overall height of this ellipse.
  10086. * @return {Phaser.Ellipse} This Ellipse object.
  10087. */
  10088. setTo: function (x, y, width, height) {
  10089. this.x = x;
  10090. this.y = y;
  10091. this.width = width;
  10092. this.height = height;
  10093. return this;
  10094. },
  10095. /**
  10096. * Copies the x, y, width and height properties from any given object to this Ellipse.
  10097. * @method Phaser.Ellipse#copyFrom
  10098. * @param {any} source - The object to copy from.
  10099. * @return {Phaser.Ellipse} This Ellipse object.
  10100. */
  10101. copyFrom: function (source) {
  10102. return this.setTo(source.x, source.y, source.width, source.height);
  10103. },
  10104. /**
  10105. * Copies the x, y and diameter properties from this Circle to any given object.
  10106. * @method Phaser.Ellipse#copyTo
  10107. * @param {any} dest - The object to copy to.
  10108. * @return {Object} This dest object.
  10109. */
  10110. copyTo: function(dest) {
  10111. dest.x = this.x;
  10112. dest.y = this.y;
  10113. dest.width = this.width;
  10114. dest.height = this.height;
  10115. return dest;
  10116. },
  10117. /**
  10118. * Returns a new Ellipse object with the same values for the x, y, width, and height properties as this Ellipse object.
  10119. * @method Phaser.Ellipse#clone
  10120. * @param {Phaser.Ellipse} out - Optional Ellipse object. If given the values will be set into the object, otherwise a brand new Ellipse object will be created and returned.
  10121. * @return {Phaser.Ellipse} The cloned Ellipse object.
  10122. */
  10123. clone: function(out) {
  10124. if (typeof out === "undefined")
  10125. {
  10126. out = new Phaser.Ellipse(this.x, this.y, this.width, this.height);
  10127. }
  10128. else
  10129. {
  10130. out.setTo(this.x, this.y, this.width, this.height);
  10131. }
  10132. return out;
  10133. },
  10134. /**
  10135. * Return true if the given x/y coordinates are within this Ellipse object.
  10136. * @method Phaser.Ellipse#contains
  10137. * @param {number} x - The X value of the coordinate to test.
  10138. * @param {number} y - The Y value of the coordinate to test.
  10139. * @return {boolean} True if the coordinates are within this ellipse, otherwise false.
  10140. */
  10141. contains: function (x, y) {
  10142. return Phaser.Ellipse.contains(this, x, y);
  10143. },
  10144. /**
  10145. * Returns a string representation of this object.
  10146. * @method Phaser.Ellipse#toString
  10147. * @return {string} A string representation of the instance.
  10148. */
  10149. toString: function () {
  10150. return "[{Phaser.Ellipse (x=" + this.x + " y=" + this.y + " width=" + this.width + " height=" + this.height + ")}]";
  10151. }
  10152. };
  10153. Phaser.Ellipse.prototype.constructor = Phaser.Ellipse;
  10154. /**
  10155. * The left coordinate of the Ellipse. The same as the X coordinate.
  10156. * @name Phaser.Ellipse#left
  10157. * @propety {number} left - Gets or sets the value of the leftmost point of the ellipse.
  10158. */
  10159. Object.defineProperty(Phaser.Ellipse.prototype, "left", {
  10160. get: function () {
  10161. return this.x;
  10162. },
  10163. set: function (value) {
  10164. this.x = value;
  10165. }
  10166. });
  10167. /**
  10168. * The x coordinate of the rightmost point of the Ellipse. Changing the right property of an Ellipse object has no effect on the x property, but does adjust the width.
  10169. * @name Phaser.Ellipse#right
  10170. * @property {number} right - Gets or sets the value of the rightmost point of the ellipse.
  10171. */
  10172. Object.defineProperty(Phaser.Ellipse.prototype, "right", {
  10173. get: function () {
  10174. return this.x + this.width;
  10175. },
  10176. set: function (value) {
  10177. if (value < this.x)
  10178. {
  10179. this.width = 0;
  10180. }
  10181. else
  10182. {
  10183. this.width = this.x + value;
  10184. }
  10185. }
  10186. });
  10187. /**
  10188. * The top of the Ellipse. The same as its y property.
  10189. * @name Phaser.Ellipse#top
  10190. * @property {number} top - Gets or sets the top of the ellipse.
  10191. */
  10192. Object.defineProperty(Phaser.Ellipse.prototype, "top", {
  10193. get: function () {
  10194. return this.y;
  10195. },
  10196. set: function (value) {
  10197. this.y = value;
  10198. }
  10199. });
  10200. /**
  10201. * The sum of the y and height properties. Changing the bottom property of an Ellipse doesn't adjust the y property, but does change the height.
  10202. * @name Phaser.Ellipse#bottom
  10203. * @property {number} bottom - Gets or sets the bottom of the ellipse.
  10204. */
  10205. Object.defineProperty(Phaser.Ellipse.prototype, "bottom", {
  10206. get: function () {
  10207. return this.y + this.height;
  10208. },
  10209. set: function (value) {
  10210. if (value < this.y)
  10211. {
  10212. this.height = 0;
  10213. }
  10214. else
  10215. {
  10216. this.height = this.y + value;
  10217. }
  10218. }
  10219. });
  10220. /**
  10221. * Determines whether or not this Ellipse object is empty. Will return a value of true if the Ellipse objects dimensions are less than or equal to 0; otherwise false.
  10222. * If set to true it will reset all of the Ellipse objects properties to 0. An Ellipse object is empty if its width or height is less than or equal to 0.
  10223. * @name Phaser.Ellipse#empty
  10224. * @property {boolean} empty - Gets or sets the empty state of the ellipse.
  10225. */
  10226. Object.defineProperty(Phaser.Ellipse.prototype, "empty", {
  10227. get: function () {
  10228. return (this.width === 0 || this.height === 0);
  10229. },
  10230. set: function (value) {
  10231. if (value === true)
  10232. {
  10233. this.setTo(0, 0, 0, 0);
  10234. }
  10235. }
  10236. });
  10237. /**
  10238. * Return true if the given x/y coordinates are within the Ellipse object.
  10239. * @method Phaser.Ellipse.contains
  10240. * @param {Phaser.Ellipse} a - The Ellipse to be checked.
  10241. * @param {number} x - The X value of the coordinate to test.
  10242. * @param {number} y - The Y value of the coordinate to test.
  10243. * @return {boolean} True if the coordinates are within this ellipse, otherwise false.
  10244. */
  10245. Phaser.Ellipse.contains = function (a, x, y) {
  10246. if (a.width <= 0 || a.height <= 0)
  10247. {
  10248. return false;
  10249. }
  10250. // Normalize the coords to an ellipse with center 0,0 and a radius of 0.5
  10251. var normx = ((x - a.x) / a.width) - 0.5;
  10252. var normy = ((y - a.y) / a.height) - 0.5;
  10253. normx *= normx;
  10254. normy *= normy;
  10255. return (normx + normy < 0.25);
  10256. };
  10257. /**
  10258. * Returns the framing rectangle of the ellipse as a Phaser.Rectangle object.
  10259. *
  10260. * @method Phaser.Ellipse.getBounds
  10261. * @return {Phaser.Rectangle} The framing rectangle
  10262. */
  10263. Phaser.Ellipse.prototype.getBounds = function() {
  10264. return new Phaser.Rectangle(this.x, this.y, this.width, this.height);
  10265. };
  10266. // Because PIXI uses its own Ellipse, we'll replace it with ours to avoid duplicating code or confusion.
  10267. PIXI.Ellipse = Phaser.Ellipse;
  10268. /**
  10269. * @author Richard Davey <rich@photonstorm.com>
  10270. * @author Adrien Brault <adrien.brault@gmail.com>
  10271. * @copyright 2014 Photon Storm Ltd.
  10272. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  10273. */
  10274. /**
  10275. * Creates a new Polygon. You have to provide a list of points.
  10276. * This can be an array of Points that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...],
  10277. * or the arguments passed can be all the points of the polygon e.g. `new Phaser.Polygon(new Phaser.Point(), new Phaser.Point(), ...)`, or the
  10278. * arguments passed can be flat x,y values e.g. `new Phaser.Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are numbers.
  10279. *
  10280. * @class Phaser.Polygon
  10281. * @classdesc The polygon represents a list of orderded points in space
  10282. * @constructor
  10283. * @param {Array<Phaser.Point>|Array<number>} points - The array of Points.
  10284. */
  10285. Phaser.Polygon = function (points) {
  10286. /**
  10287. * @property {number} type - The base object type.
  10288. */
  10289. this.type = Phaser.POLYGON;
  10290. //if points isn't an array, use arguments as the array
  10291. if (!(points instanceof Array))
  10292. {
  10293. points = Array.prototype.slice.call(arguments);
  10294. }
  10295. //if this is a flat array of numbers, convert it to points
  10296. if (typeof points[0] === 'number')
  10297. {
  10298. var p = [];
  10299. for (var i = 0, len = points.length; i < len; i += 2)
  10300. {
  10301. p.push(new Phaser.Point(points[i], points[i + 1]));
  10302. }
  10303. points = p;
  10304. }
  10305. /**
  10306. * @property {array<Phaser.Point>|array<number>} points - The array of Points.
  10307. */
  10308. this.points = points;
  10309. };
  10310. Phaser.Polygon.prototype = {
  10311. /**
  10312. * Creates a clone of this polygon.
  10313. *
  10314. * @method Phaser.Polygon#clone
  10315. * @return {Phaser.Polygon} A copy of the polygon.
  10316. */
  10317. clone: function () {
  10318. var points = [];
  10319. for (var i=0; i < this.points.length; i++)
  10320. {
  10321. points.push(this.points[i].clone());
  10322. }
  10323. return new Phaser.Polygon(points);
  10324. },
  10325. /**
  10326. * Checks whether the x and y coordinates are contained within this polygon.
  10327. *
  10328. * @method Phaser.Polygon#contains
  10329. * @param {number} x - The X value of the coordinate to test.
  10330. * @param {number} y - The Y value of the coordinate to test.
  10331. * @return {boolean} True if the coordinates are within this polygon, otherwise false.
  10332. */
  10333. contains: function (x, y) {
  10334. var inside = false;
  10335. // use some raycasting to test hits https://github.com/substack/point-in-polygon/blob/master/index.js
  10336. for (var i = 0, j = this.points.length - 1; i < this.points.length; j = i++)
  10337. {
  10338. var xi = this.points[i].x;
  10339. var yi = this.points[i].y;
  10340. var xj = this.points[j].x;
  10341. var yj = this.points[j].y;
  10342. var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
  10343. if (intersect)
  10344. {
  10345. inside = true;
  10346. }
  10347. }
  10348. return inside;
  10349. }
  10350. };
  10351. Phaser.Polygon.prototype.constructor = Phaser.Polygon;
  10352. // Because PIXI uses its own Polygon, we'll replace it with ours to avoid duplicating code or confusion.
  10353. PIXI.Polygon = Phaser.Polygon;
  10354. /**
  10355. * @author Richard Davey <rich@photonstorm.com>
  10356. * @copyright 2014 Photon Storm Ltd.
  10357. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  10358. */
  10359. /**
  10360. * A Camera is your view into the game world. It has a position and size and renders only those objects within its field of view.
  10361. * The game automatically creates a single Stage sized camera on boot. Move the camera around the world with Phaser.Camera.x/y
  10362. *
  10363. * @class Phaser.Camera
  10364. * @constructor
  10365. * @param {Phaser.Game} game - Game reference to the currently running game.
  10366. * @param {number} id - Not being used at the moment, will be when Phaser supports multiple camera
  10367. * @param {number} x - Position of the camera on the X axis
  10368. * @param {number} y - Position of the camera on the Y axis
  10369. * @param {number} width - The width of the view rectangle
  10370. * @param {number} height - The height of the view rectangle
  10371. */
  10372. Phaser.Camera = function (game, id, x, y, width, height) {
  10373. /**
  10374. * @property {Phaser.Game} game - A reference to the currently running Game.
  10375. */
  10376. this.game = game;
  10377. /**
  10378. * @property {Phaser.World} world - A reference to the game world.
  10379. */
  10380. this.world = game.world;
  10381. /**
  10382. * @property {number} id - Reserved for future multiple camera set-ups.
  10383. * @default
  10384. */
  10385. this.id = 0;
  10386. /**
  10387. * Camera view.
  10388. * The view into the world we wish to render (by default the game dimensions).
  10389. * The x/y values are in world coordinates, not screen coordinates, the width/height is how many pixels to render.
  10390. * Objects outside of this view are not rendered if set to camera cull.
  10391. * @property {Phaser.Rectangle} view
  10392. */
  10393. this.view = new Phaser.Rectangle(x, y, width, height);
  10394. /**
  10395. * @property {Phaser.Rectangle} screenView - Used by Sprites to work out Camera culling.
  10396. */
  10397. this.screenView = new Phaser.Rectangle(x, y, width, height);
  10398. /**
  10399. * The Camera is bound to this Rectangle and cannot move outside of it. By default it is enabled and set to the size of the World.
  10400. * The Rectangle can be located anywhere in the world and updated as often as you like. If you don't wish the Camera to be bound
  10401. * at all then set this to null. The values can be anything and are in World coordinates, with 0,0 being the center of the world.
  10402. * @property {Phaser.Rectangle} bounds - The Rectangle in which the Camera is bounded. Set to null to allow for movement anywhere.
  10403. */
  10404. this.bounds = new Phaser.Rectangle(x, y, width, height);
  10405. /**
  10406. * @property {Phaser.Rectangle} deadzone - Moving inside this Rectangle will not cause camera moving.
  10407. */
  10408. this.deadzone = null;
  10409. /**
  10410. * @property {boolean} visible - Whether this camera is visible or not.
  10411. * @default
  10412. */
  10413. this.visible = true;
  10414. /**
  10415. * @property {boolean} atLimit - Whether this camera is flush with the World Bounds or not.
  10416. */
  10417. this.atLimit = { x: false, y: false };
  10418. /**
  10419. * @property {Phaser.Sprite} target - If the camera is tracking a Sprite, this is a reference to it, otherwise null.
  10420. * @default
  10421. */
  10422. this.target = null;
  10423. /**
  10424. * @property {number} edge - Edge property.
  10425. * @private
  10426. * @default
  10427. */
  10428. this._edge = 0;
  10429. /**
  10430. * @property {PIXI.DisplayObject} displayObject - The display object to which all game objects are added. Set by World.boot
  10431. */
  10432. this.displayObject = null;
  10433. /**
  10434. * @property {Phaser.Point} scale - The scale of the display object to which all game objects are added. Set by World.boot
  10435. */
  10436. this.scale = null;
  10437. };
  10438. /**
  10439. * @constant
  10440. * @type {number}
  10441. */
  10442. Phaser.Camera.FOLLOW_LOCKON = 0;
  10443. /**
  10444. * @constant
  10445. * @type {number}
  10446. */
  10447. Phaser.Camera.FOLLOW_PLATFORMER = 1;
  10448. /**
  10449. * @constant
  10450. * @type {number}
  10451. */
  10452. Phaser.Camera.FOLLOW_TOPDOWN = 2;
  10453. /**
  10454. * @constant
  10455. * @type {number}
  10456. */
  10457. Phaser.Camera.FOLLOW_TOPDOWN_TIGHT = 3;
  10458. Phaser.Camera.prototype = {
  10459. /**
  10460. * Tells this camera which sprite to follow.
  10461. * @method Phaser.Camera#follow
  10462. * @param {Phaser.Sprite|Phaser.Image|Phaser.Text} target - The object you want the camera to track. Set to null to not follow anything.
  10463. * @param {number} [style] - Leverage one of the existing "deadzone" presets. If you use a custom deadzone, ignore this parameter and manually specify the deadzone after calling follow().
  10464. */
  10465. follow: function (target, style) {
  10466. if (typeof style === "undefined") { style = Phaser.Camera.FOLLOW_LOCKON; }
  10467. this.target = target;
  10468. var helper;
  10469. switch (style) {
  10470. case Phaser.Camera.FOLLOW_PLATFORMER:
  10471. var w = this.width / 8;
  10472. var h = this.height / 3;
  10473. this.deadzone = new Phaser.Rectangle((this.width - w) / 2, (this.height - h) / 2 - h * 0.25, w, h);
  10474. break;
  10475. case Phaser.Camera.FOLLOW_TOPDOWN:
  10476. helper = Math.max(this.width, this.height) / 4;
  10477. this.deadzone = new Phaser.Rectangle((this.width - helper) / 2, (this.height - helper) / 2, helper, helper);
  10478. break;
  10479. case Phaser.Camera.FOLLOW_TOPDOWN_TIGHT:
  10480. helper = Math.max(this.width, this.height) / 8;
  10481. this.deadzone = new Phaser.Rectangle((this.width - helper) / 2, (this.height - helper) / 2, helper, helper);
  10482. break;
  10483. case Phaser.Camera.FOLLOW_LOCKON:
  10484. this.deadzone = null;
  10485. break;
  10486. default:
  10487. this.deadzone = null;
  10488. break;
  10489. }
  10490. },
  10491. /**
  10492. * Move the camera focus on a display object instantly.
  10493. * @method Phaser.Camera#focusOn
  10494. * @param {any} displayObject - The display object to focus the camera on. Must have visible x/y properties.
  10495. */
  10496. focusOn: function (displayObject) {
  10497. this.setPosition(Math.round(displayObject.x - this.view.halfWidth), Math.round(displayObject.y - this.view.halfHeight));
  10498. },
  10499. /**
  10500. * Move the camera focus on a location instantly.
  10501. * @method Phaser.Camera#focusOnXY
  10502. * @param {number} x - X position.
  10503. * @param {number} y - Y position.
  10504. */
  10505. focusOnXY: function (x, y) {
  10506. this.setPosition(Math.round(x - this.view.halfWidth), Math.round(y - this.view.halfHeight));
  10507. },
  10508. /**
  10509. * Update focusing and scrolling.
  10510. * @method Phaser.Camera#update
  10511. */
  10512. update: function () {
  10513. if (this.target)
  10514. {
  10515. this.updateTarget();
  10516. }
  10517. if (this.bounds)
  10518. {
  10519. this.checkBounds();
  10520. }
  10521. this.displayObject.position.x = -this.view.x;
  10522. this.displayObject.position.y = -this.view.y;
  10523. },
  10524. /**
  10525. * Internal method
  10526. * @method Phaser.Camera#updateTarget
  10527. * @private
  10528. */
  10529. updateTarget: function () {
  10530. if (this.deadzone)
  10531. {
  10532. this._edge = this.target.x - this.deadzone.x;
  10533. if (this.view.x > this._edge)
  10534. {
  10535. this.view.x = this._edge;
  10536. }
  10537. this._edge = this.target.x + this.target.width - this.deadzone.x - this.deadzone.width;
  10538. if (this.view.x < this._edge)
  10539. {
  10540. this.view.x = this._edge;
  10541. }
  10542. this._edge = this.target.y - this.deadzone.y;
  10543. if (this.view.y > this._edge)
  10544. {
  10545. this.view.y = this._edge;
  10546. }
  10547. this._edge = this.target.y + this.target.height - this.deadzone.y - this.deadzone.height;
  10548. if (this.view.y < this._edge)
  10549. {
  10550. this.view.y = this._edge;
  10551. }
  10552. }
  10553. else
  10554. {
  10555. this.focusOnXY(this.target.x, this.target.y);
  10556. }
  10557. },
  10558. /**
  10559. * Update the Camera bounds to match the game world.
  10560. * @method Phaser.Camera#setBoundsToWorld
  10561. */
  10562. setBoundsToWorld: function () {
  10563. this.bounds.setTo(this.game.world.bounds.x, this.game.world.bounds.y, this.game.world.bounds.width, this.game.world.bounds.height);
  10564. },
  10565. /**
  10566. * Method called to ensure the camera doesn't venture outside of the game world.
  10567. * @method Phaser.Camera#checkWorldBounds
  10568. */
  10569. checkBounds: function () {
  10570. this.atLimit.x = false;
  10571. this.atLimit.y = false;
  10572. // Make sure we didn't go outside the cameras bounds
  10573. if (this.view.x <= this.bounds.x)
  10574. {
  10575. this.atLimit.x = true;
  10576. this.view.x = this.bounds.x;
  10577. }
  10578. if (this.view.right >= this.bounds.right)
  10579. {
  10580. this.atLimit.x = true;
  10581. this.view.x = this.bounds.right - this.width;
  10582. }
  10583. if (this.view.y <= this.bounds.top)
  10584. {
  10585. this.atLimit.y = true;
  10586. this.view.y = this.bounds.top;
  10587. }
  10588. if (this.view.bottom >= this.bounds.bottom)
  10589. {
  10590. this.atLimit.y = true;
  10591. this.view.y = this.bounds.bottom - this.height;
  10592. }
  10593. this.view.floor();
  10594. },
  10595. /**
  10596. * A helper function to set both the X and Y properties of the camera at once
  10597. * without having to use game.camera.x and game.camera.y.
  10598. *
  10599. * @method Phaser.Camera#setPosition
  10600. * @param {number} x - X position.
  10601. * @param {number} y - Y position.
  10602. */
  10603. setPosition: function (x, y) {
  10604. this.view.x = x;
  10605. this.view.y = y;
  10606. if (this.bounds)
  10607. {
  10608. this.checkBounds();
  10609. }
  10610. },
  10611. /**
  10612. * Sets the size of the view rectangle given the width and height in parameters.
  10613. *
  10614. * @method Phaser.Camera#setSize
  10615. * @param {number} width - The desired width.
  10616. * @param {number} height - The desired height.
  10617. */
  10618. setSize: function (width, height) {
  10619. this.view.width = width;
  10620. this.view.height = height;
  10621. },
  10622. /**
  10623. * Resets the camera back to 0,0 and un-follows any object it may have been tracking.
  10624. *
  10625. * @method Phaser.Camera#reset
  10626. */
  10627. reset: function () {
  10628. this.target = null;
  10629. this.view.x = 0;
  10630. this.view.y = 0;
  10631. }
  10632. };
  10633. Phaser.Camera.prototype.constructor = Phaser.Camera;
  10634. /**
  10635. * The Cameras x coordinate. This value is automatically clamped if it falls outside of the World bounds.
  10636. * @name Phaser.Camera#x
  10637. * @property {number} x - Gets or sets the cameras x position.
  10638. */
  10639. Object.defineProperty(Phaser.Camera.prototype, "x", {
  10640. get: function () {
  10641. return this.view.x;
  10642. },
  10643. set: function (value) {
  10644. this.view.x = value;
  10645. if (this.bounds)
  10646. {
  10647. this.checkBounds();
  10648. }
  10649. }
  10650. });
  10651. /**
  10652. * The Cameras y coordinate. This value is automatically clamped if it falls outside of the World bounds.
  10653. * @name Phaser.Camera#y
  10654. * @property {number} y - Gets or sets the cameras y position.
  10655. */
  10656. Object.defineProperty(Phaser.Camera.prototype, "y", {
  10657. get: function () {
  10658. return this.view.y;
  10659. },
  10660. set: function (value) {
  10661. this.view.y = value;
  10662. if (this.bounds)
  10663. {
  10664. this.checkBounds();
  10665. }
  10666. }
  10667. });
  10668. /**
  10669. * The Cameras width. By default this is the same as the Game size and should not be adjusted for now.
  10670. * @name Phaser.Camera#width
  10671. * @property {number} width - Gets or sets the cameras width.
  10672. */
  10673. Object.defineProperty(Phaser.Camera.prototype, "width", {
  10674. get: function () {
  10675. return this.view.width;
  10676. },
  10677. set: function (value) {
  10678. this.view.width = value;
  10679. }
  10680. });
  10681. /**
  10682. * The Cameras height. By default this is the same as the Game size and should not be adjusted for now.
  10683. * @name Phaser.Camera#height
  10684. * @property {number} height - Gets or sets the cameras height.
  10685. */
  10686. Object.defineProperty(Phaser.Camera.prototype, "height", {
  10687. get: function () {
  10688. return this.view.height;
  10689. },
  10690. set: function (value) {
  10691. this.view.height = value;
  10692. }
  10693. });
  10694. /**
  10695. * @author Richard Davey <rich@photonstorm.com>
  10696. * @copyright 2014 Photon Storm Ltd.
  10697. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  10698. */
  10699. /**
  10700. * This is a base State class which can be extended if you are creating your own game.
  10701. * It provides quick access to common functions such as the camera, cache, input, match, sound and more.
  10702. *
  10703. * @class Phaser.State
  10704. * @constructor
  10705. */
  10706. Phaser.State = function () {
  10707. /**
  10708. * @property {Phaser.Game} game - A reference to the currently running Game.
  10709. */
  10710. this.game = null;
  10711. /**
  10712. * @property {Phaser.GameObjectFactory} add - Reference to the GameObjectFactory.
  10713. */
  10714. this.add = null;
  10715. /**
  10716. * @property {Phaser.GameObjectCreator} make - Reference to the GameObjectCreator.
  10717. */
  10718. this.make = null;
  10719. /**
  10720. * @property {Phaser.Camera} camera - A handy reference to world.camera.
  10721. */
  10722. this.camera = null;
  10723. /**
  10724. * @property {Phaser.Cache} cache - Reference to the assets cache.
  10725. */
  10726. this.cache = null;
  10727. /**
  10728. * @property {Phaser.Input} input - Reference to the input manager
  10729. */
  10730. this.input = null;
  10731. /**
  10732. * @property {Phaser.Loader} load - Reference to the assets loader.
  10733. */
  10734. this.load = null;
  10735. /**
  10736. * @property {Phaser.Math} math - Reference to the math helper.
  10737. */
  10738. this.math = null;
  10739. /**
  10740. * @property {Phaser.SoundManager} sound - Reference to the sound manager.
  10741. */
  10742. this.sound = null;
  10743. /**
  10744. * @property {Phaser.ScaleManager} scale - Reference to the game scale manager.
  10745. */
  10746. this.scale = null;
  10747. /**
  10748. * @property {Phaser.Stage} stage - Reference to the stage.
  10749. */
  10750. this.stage = null;
  10751. /**
  10752. * @property {Phaser.Time} time - Reference to the core game clock.
  10753. */
  10754. this.time = null;
  10755. /**
  10756. * @property {Phaser.TweenManager} tweens - Reference to the tween manager.
  10757. */
  10758. this.tweens = null;
  10759. /**
  10760. * @property {Phaser.World} world - Reference to the world.
  10761. */
  10762. this.world = null;
  10763. /**
  10764. * @property {Phaser.Particles} particles - The Particle Manager for the game. It is called during the game update loop and in turn updates any Emitters attached to it.
  10765. */
  10766. this.particles = null;
  10767. /**
  10768. * @property {Phaser.Physics} physics - Reference to the physics manager.
  10769. */
  10770. this.physics = null;
  10771. /**
  10772. * @property {Phaser.RandomDataGenerator} rnd - Reference to the random data generator.
  10773. */
  10774. this.rnd = null;
  10775. };
  10776. Phaser.State.prototype = {
  10777. /**
  10778. * Override this method to add some load operations.
  10779. * If you need to use the loader, you may need to use them here.
  10780. *
  10781. * @method Phaser.State#preload
  10782. */
  10783. preload: function () {
  10784. },
  10785. /**
  10786. * Put update logic here.
  10787. *
  10788. * @method Phaser.State#loadUpdate
  10789. */
  10790. loadUpdate: function () {
  10791. },
  10792. /**
  10793. * Put render operations here.
  10794. *
  10795. * @method Phaser.State#loadRender
  10796. */
  10797. loadRender: function () {
  10798. },
  10799. /**
  10800. * This method is called after the game engine successfully switches states.
  10801. * Feel free to add any setup code here (do not load anything here, override preload() instead).
  10802. *
  10803. * @method Phaser.State#create
  10804. */
  10805. create: function () {
  10806. },
  10807. /**
  10808. * Put update logic here.
  10809. *
  10810. * @method Phaser.State#update
  10811. */
  10812. update: function () {
  10813. },
  10814. /**
  10815. * Put render operations here.
  10816. *
  10817. * @method Phaser.State#render
  10818. */
  10819. render: function () {
  10820. },
  10821. /**
  10822. * This method will be called when game paused.
  10823. *
  10824. * @method Phaser.State#paused
  10825. */
  10826. paused: function () {
  10827. },
  10828. /**
  10829. * This method will be called when the state is shut down (i.e. you switch to another state from this one).
  10830. * @method Phaser.State#shutdown
  10831. */
  10832. shutdown: function () {
  10833. }
  10834. };
  10835. Phaser.State.prototype.constructor = Phaser.State;
  10836. /* jshint newcap: false */
  10837. /**
  10838. * @author Richard Davey <rich@photonstorm.com>
  10839. * @copyright 2014 Photon Storm Ltd.
  10840. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  10841. */
  10842. /**
  10843. * The State Manager is responsible for loading, setting up and switching game states.
  10844. *
  10845. * @class Phaser.StateManager
  10846. * @constructor
  10847. * @param {Phaser.Game} game - A reference to the currently running game.
  10848. * @param {Phaser.State|Object} [pendingState=null] - A State object to seed the manager with.
  10849. */
  10850. Phaser.StateManager = function (game, pendingState) {
  10851. /**
  10852. * @property {Phaser.Game} game - A reference to the currently running game.
  10853. */
  10854. this.game = game;
  10855. /**
  10856. * @property {Object} states - The object containing Phaser.States.
  10857. */
  10858. this.states = {};
  10859. /**
  10860. * @property {Phaser.State} _pendingState - The state to be switched to in the next frame.
  10861. * @private
  10862. */
  10863. this._pendingState = null;
  10864. if (typeof pendingState !== 'undefined' && pendingState !== null)
  10865. {
  10866. this._pendingState = pendingState;
  10867. }
  10868. /**
  10869. * @property {boolean} _clearWorld - Clear the world when we switch state?
  10870. * @private
  10871. */
  10872. this._clearWorld = false;
  10873. /**
  10874. * @property {boolean} _clearCache - Clear the cache when we switch state?
  10875. * @private
  10876. */
  10877. this._clearCache = false;
  10878. /**
  10879. * @property {boolean} _created - Flag that sets if the State has been created or not.
  10880. * @private
  10881. */
  10882. this._created = false;
  10883. /**
  10884. * @property {array} _args - Temporary container when you pass vars from one State to another.
  10885. * @private
  10886. */
  10887. this._args = [];
  10888. /**
  10889. * @property {string} current - The current active State object (defaults to null).
  10890. */
  10891. this.current = '';
  10892. /**
  10893. * @property {function} onInitCallback - This will be called when the state is started (i.e. set as the current active state).
  10894. */
  10895. this.onInitCallback = null;
  10896. /**
  10897. * @property {function} onPreloadCallback - This will be called when init states (loading assets...).
  10898. */
  10899. this.onPreloadCallback = null;
  10900. /**
  10901. * @property {function} onCreateCallback - This will be called when create states (setup states...).
  10902. */
  10903. this.onCreateCallback = null;
  10904. /**
  10905. * @property {function} onUpdateCallback - This will be called when State is updated, this doesn't happen during load (@see onLoadUpdateCallback).
  10906. */
  10907. this.onUpdateCallback = null;
  10908. /**
  10909. * @property {function} onRenderCallback - This will be called when the State is rendered, this doesn't happen during load (see onLoadRenderCallback).
  10910. */
  10911. this.onRenderCallback = null;
  10912. /**
  10913. * @property {function} onPreRenderCallback - This will be called before the State is rendered and before the stage is cleared.
  10914. */
  10915. this.onPreRenderCallback = null;
  10916. /**
  10917. * @property {function} onLoadUpdateCallback - This will be called when the State is updated but only during the load process.
  10918. */
  10919. this.onLoadUpdateCallback = null;
  10920. /**
  10921. * @property {function} onLoadRenderCallback - This will be called when the State is rendered but only during the load process.
  10922. */
  10923. this.onLoadRenderCallback = null;
  10924. /**
  10925. * @property {function} onPausedCallback - This will be called when the state is paused.
  10926. */
  10927. this.onPausedCallback = null;
  10928. /**
  10929. * @property {function} onResumedCallback - This will be called when the state is resumed from a paused state.
  10930. */
  10931. this.onResumedCallback = null;
  10932. /**
  10933. * @property {function} onShutDownCallback - This will be called when the state is shut down (i.e. swapped to another state).
  10934. */
  10935. this.onShutDownCallback = null;
  10936. };
  10937. Phaser.StateManager.prototype = {
  10938. /**
  10939. * The Boot handler is called by Phaser.Game when it first starts up.
  10940. * @method Phaser.StateManager#boot
  10941. * @private
  10942. */
  10943. boot: function () {
  10944. this.game.onPause.add(this.pause, this);
  10945. this.game.onResume.add(this.resume, this);
  10946. this.game.load.onLoadComplete.add(this.loadComplete, this);
  10947. if (this._pendingState !== null)
  10948. {
  10949. if (typeof this._pendingState === 'string')
  10950. {
  10951. // State was already added, so just start it
  10952. this.start(this._pendingState, false, false);
  10953. }
  10954. else
  10955. {
  10956. this.add('default', this._pendingState, true);
  10957. }
  10958. }
  10959. },
  10960. /**
  10961. * Adds a new State into the StateManager. You must give each State a unique key by which you'll identify it.
  10962. * The State can be either a Phaser.State object (or an object that extends it), a plain JavaScript object or a function.
  10963. * If a function is given a new state object will be created by calling it.
  10964. *
  10965. * @method Phaser.StateManager#add
  10966. * @param {string} key - A unique key you use to reference this state, i.e. "MainMenu", "Level1".
  10967. * @param {Phaser.State|object|function} state - The state you want to switch to.
  10968. * @param {boolean} [autoStart=false] - If true the State will be started immediately after adding it.
  10969. */
  10970. add: function (key, state, autoStart) {
  10971. if (typeof autoStart === "undefined") { autoStart = false; }
  10972. var newState;
  10973. if (state instanceof Phaser.State)
  10974. {
  10975. newState = state;
  10976. }
  10977. else if (typeof state === 'object')
  10978. {
  10979. newState = state;
  10980. newState.game = this.game;
  10981. }
  10982. else if (typeof state === 'function')
  10983. {
  10984. newState = new state(this.game);
  10985. }
  10986. this.states[key] = newState;
  10987. if (autoStart)
  10988. {
  10989. if (this.game.isBooted)
  10990. {
  10991. this.start(key);
  10992. }
  10993. else
  10994. {
  10995. this._pendingState = key;
  10996. }
  10997. }
  10998. return newState;
  10999. },
  11000. /**
  11001. * Delete the given state.
  11002. * @method Phaser.StateManager#remove
  11003. * @param {string} key - A unique key you use to reference this state, i.e. "MainMenu", "Level1".
  11004. */
  11005. remove: function (key) {
  11006. if (this.current === key)
  11007. {
  11008. this.callbackContext = null;
  11009. this.onInitCallback = null;
  11010. this.onShutDownCallback = null;
  11011. this.onPreloadCallback = null;
  11012. this.onLoadRenderCallback = null;
  11013. this.onLoadUpdateCallback = null;
  11014. this.onCreateCallback = null;
  11015. this.onUpdateCallback = null;
  11016. this.onRenderCallback = null;
  11017. this.onPausedCallback = null;
  11018. this.onResumedCallback = null;
  11019. this.onDestroyCallback = null;
  11020. }
  11021. delete this.states[key];
  11022. },
  11023. /**
  11024. * Start the given State. If a State is already running then State.shutDown will be called (if it exists) before switching to the new State.
  11025. *
  11026. * @method Phaser.StateManager#start
  11027. * @param {string} key - The key of the state you want to start.
  11028. * @param {boolean} [clearWorld=true] - Clear everything in the world? This clears the World display list fully (but not the Stage, so if you've added your own objects to the Stage they will need managing directly)
  11029. * @param {boolean} [clearCache=false] - Clear the Game.Cache? This purges out all loaded assets. The default is false and you must have clearWorld=true if you want to clearCache as well.
  11030. * @param {...*} parameter - Additional parameters that will be passed to the State.init function (if it has one).
  11031. */
  11032. start: function (key, clearWorld, clearCache) {
  11033. if (typeof clearWorld === "undefined") { clearWorld = true; }
  11034. if (typeof clearCache === "undefined") { clearCache = false; }
  11035. if (this.checkState(key))
  11036. {
  11037. // Place the state in the queue. It will be started the next time the game loop starts.
  11038. this._pendingState = key;
  11039. this._clearWorld = clearWorld;
  11040. this._clearCache = clearCache;
  11041. if (arguments.length > 3)
  11042. {
  11043. this._args = Array.prototype.splice.call(arguments, 3);
  11044. }
  11045. }
  11046. },
  11047. /**
  11048. * Restarts the current State. State.shutDown will be called (if it exists) before the State is restarted.
  11049. *
  11050. * @method Phaser.StateManager#restart
  11051. * @param {boolean} [clearWorld=true] - Clear everything in the world? This clears the World display list fully (but not the Stage, so if you've added your own objects to the Stage they will need managing directly)
  11052. * @param {boolean} [clearCache=false] - Clear the Game.Cache? This purges out all loaded assets. The default is false and you must have clearWorld=true if you want to clearCache as well.
  11053. * @param {...*} parameter - Additional parameters that will be passed to the State.init function if it has one.
  11054. */
  11055. restart: function (clearWorld, clearCache) {
  11056. if (typeof clearWorld === "undefined") { clearWorld = true; }
  11057. if (typeof clearCache === "undefined") { clearCache = false; }
  11058. // Place the state in the queue. It will be started the next time the game loop starts.
  11059. this._pendingState = this.current;
  11060. this._clearWorld = clearWorld;
  11061. this._clearCache = clearCache;
  11062. if (arguments.length > 3)
  11063. {
  11064. this._args = Array.prototype.splice.call(arguments, 3);
  11065. }
  11066. },
  11067. /**
  11068. * Used by onInit and onShutdown when those functions don't exist on the state
  11069. * @method Phaser.StateManager#dummy
  11070. * @private
  11071. */
  11072. dummy: function () {
  11073. },
  11074. /**
  11075. * preUpdate is called right at the start of the game loop. It is responsible for changing to a new state that was requested previously.
  11076. *
  11077. * @method Phaser.StateManager#preUpdate
  11078. */
  11079. preUpdate: function () {
  11080. if (this._pendingState && this.game.isBooted)
  11081. {
  11082. // Already got a state running?
  11083. if (this.current)
  11084. {
  11085. this.onShutDownCallback.call(this.callbackContext, this.game);
  11086. this.game.tweens.removeAll();
  11087. this.game.camera.reset();
  11088. this.game.input.reset(true);
  11089. this.game.physics.clear();
  11090. this.game.time.removeAll();
  11091. if (this._clearWorld)
  11092. {
  11093. this.game.world.shutdown();
  11094. if (this._clearCache === true)
  11095. {
  11096. this.game.cache.destroy();
  11097. }
  11098. }
  11099. }
  11100. this.setCurrentState(this._pendingState);
  11101. if (this.onPreloadCallback)
  11102. {
  11103. this.game.load.reset();
  11104. this.onPreloadCallback.call(this.callbackContext, this.game);
  11105. // Is the loader empty?
  11106. if (this.game.load.totalQueuedFiles() === 0)
  11107. {
  11108. this.loadComplete();
  11109. }
  11110. else
  11111. {
  11112. // Start the loader going as we have something in the queue
  11113. this.game.load.start();
  11114. }
  11115. }
  11116. else
  11117. {
  11118. // No init? Then there was nothing to load either
  11119. this.loadComplete();
  11120. }
  11121. if (this.current === this._pendingState)
  11122. {
  11123. this._pendingState = null;
  11124. }
  11125. }
  11126. },
  11127. /**
  11128. * Checks if a given phaser state is valid. A State is considered valid if it has at least one of the core functions: preload, create, update or render.
  11129. *
  11130. * @method Phaser.StateManager#checkState
  11131. * @param {string} key - The key of the state you want to check.
  11132. * @return {boolean} true if the State has the required functions, otherwise false.
  11133. */
  11134. checkState: function (key) {
  11135. if (this.states[key])
  11136. {
  11137. var valid = false;
  11138. if (this.states[key]['preload']) { valid = true; }
  11139. if (this.states[key]['create']) { valid = true; }
  11140. if (this.states[key]['update']) { valid = true; }
  11141. if (this.states[key]['render']) { valid = true; }
  11142. if (valid === false)
  11143. {
  11144. console.warn("Invalid Phaser State object given. Must contain at least a one of the required functions: preload, create, update or render");
  11145. return false;
  11146. }
  11147. return true;
  11148. }
  11149. else
  11150. {
  11151. console.warn("Phaser.StateManager - No state found with the key: " + key);
  11152. return false;
  11153. }
  11154. },
  11155. /**
  11156. * Links game properties to the State given by the key.
  11157. * @method Phaser.StateManager#link
  11158. * @param {string} key - State key.
  11159. * @protected
  11160. */
  11161. link: function (key) {
  11162. this.states[key].game = this.game;
  11163. this.states[key].add = this.game.add;
  11164. this.states[key].make = this.game.make;
  11165. this.states[key].camera = this.game.camera;
  11166. this.states[key].cache = this.game.cache;
  11167. this.states[key].input = this.game.input;
  11168. this.states[key].load = this.game.load;
  11169. this.states[key].math = this.game.math;
  11170. this.states[key].sound = this.game.sound;
  11171. this.states[key].scale = this.game.scale;
  11172. this.states[key].state = this;
  11173. this.states[key].stage = this.game.stage;
  11174. this.states[key].time = this.game.time;
  11175. this.states[key].tweens = this.game.tweens;
  11176. this.states[key].world = this.game.world;
  11177. this.states[key].particles = this.game.particles;
  11178. this.states[key].rnd = this.game.rnd;
  11179. this.states[key].physics = this.game.physics;
  11180. },
  11181. /**
  11182. * Sets the current State. Should not be called directly (use StateManager.start)
  11183. * @method Phaser.StateManager#setCurrentState
  11184. * @param {string} key - State key.
  11185. * @private
  11186. */
  11187. setCurrentState: function (key) {
  11188. this.callbackContext = this.states[key];
  11189. this.link(key);
  11190. // Used when the state is set as being the current active state
  11191. this.onInitCallback = this.states[key]['init'] || this.dummy;
  11192. this.onPreloadCallback = this.states[key]['preload'] || null;
  11193. this.onLoadRenderCallback = this.states[key]['loadRender'] || null;
  11194. this.onLoadUpdateCallback = this.states[key]['loadUpdate'] || null;
  11195. this.onCreateCallback = this.states[key]['create'] || null;
  11196. this.onUpdateCallback = this.states[key]['update'] || null;
  11197. this.onPreRenderCallback = this.states[key]['preRender'] || null;
  11198. this.onRenderCallback = this.states[key]['render'] || null;
  11199. this.onPausedCallback = this.states[key]['paused'] || null;
  11200. this.onResumedCallback = this.states[key]['resumed'] || null;
  11201. // Used when the state is no longer the current active state
  11202. this.onShutDownCallback = this.states[key]['shutdown'] || this.dummy;
  11203. this.current = key;
  11204. this._created = false;
  11205. this.onInitCallback.apply(this.callbackContext, this._args);
  11206. this._args = [];
  11207. },
  11208. /**
  11209. * Gets the current State.
  11210. *
  11211. * @method Phaser.StateManager#getCurrentState
  11212. * @return Phaser.State
  11213. * @public
  11214. */
  11215. getCurrentState: function() {
  11216. return this.states[this.current];
  11217. },
  11218. /**
  11219. * @method Phaser.StateManager#loadComplete
  11220. * @protected
  11221. */
  11222. loadComplete: function () {
  11223. if (this._created === false && this.onCreateCallback)
  11224. {
  11225. this._created = true;
  11226. this.onCreateCallback.call(this.callbackContext, this.game);
  11227. }
  11228. else
  11229. {
  11230. this._created = true;
  11231. }
  11232. },
  11233. /**
  11234. * @method Phaser.StateManager#pause
  11235. * @protected
  11236. */
  11237. pause: function () {
  11238. if (this._created && this.onPausedCallback)
  11239. {
  11240. this.onPausedCallback.call(this.callbackContext, this.game);
  11241. }
  11242. },
  11243. /**
  11244. * @method Phaser.StateManager#resume
  11245. * @protected
  11246. */
  11247. resume: function () {
  11248. if (this._created && this.onResumedCallback)
  11249. {
  11250. this.onResumedCallback.call(this.callbackContext, this.game);
  11251. }
  11252. },
  11253. /**
  11254. * @method Phaser.StateManager#update
  11255. * @protected
  11256. */
  11257. update: function () {
  11258. if (this._created && this.onUpdateCallback)
  11259. {
  11260. this.onUpdateCallback.call(this.callbackContext, this.game);
  11261. }
  11262. else
  11263. {
  11264. if (this.onLoadUpdateCallback)
  11265. {
  11266. this.onLoadUpdateCallback.call(this.callbackContext, this.game);
  11267. }
  11268. }
  11269. },
  11270. /**
  11271. * @method Phaser.StateManager#preRender
  11272. * @protected
  11273. */
  11274. preRender: function () {
  11275. if (this.onPreRenderCallback)
  11276. {
  11277. this.onPreRenderCallback.call(this.callbackContext, this.game);
  11278. }
  11279. },
  11280. /**
  11281. * @method Phaser.StateManager#render
  11282. * @protected
  11283. */
  11284. render: function () {
  11285. if (this._created && this.onRenderCallback)
  11286. {
  11287. if (this.game.renderType === Phaser.CANVAS)
  11288. {
  11289. this.game.context.save();
  11290. this.game.context.setTransform(1, 0, 0, 1, 0, 0);
  11291. }
  11292. this.onRenderCallback.call(this.callbackContext, this.game);
  11293. if (this.game.renderType === Phaser.CANVAS)
  11294. {
  11295. this.game.context.restore();
  11296. }
  11297. }
  11298. else
  11299. {
  11300. if (this.onLoadRenderCallback)
  11301. {
  11302. this.onLoadRenderCallback.call(this.callbackContext, this.game);
  11303. }
  11304. }
  11305. },
  11306. /**
  11307. * Removes all StateManager callback references to the State object, nulls the game reference and clears the States object.
  11308. * You don't recover from this without rebuilding the Phaser instance again.
  11309. * @method Phaser.StateManager#destroy
  11310. */
  11311. destroy: function () {
  11312. this.callbackContext = null;
  11313. this.onInitCallback = null;
  11314. this.onShutDownCallback = null;
  11315. this.onPreloadCallback = null;
  11316. this.onLoadRenderCallback = null;
  11317. this.onLoadUpdateCallback = null;
  11318. this.onCreateCallback = null;
  11319. this.onUpdateCallback = null;
  11320. this.onRenderCallback = null;
  11321. this.onPausedCallback = null;
  11322. this.onResumedCallback = null;
  11323. this.onDestroyCallback = null;
  11324. this.game = null;
  11325. this.states = {};
  11326. this._pendingState = null;
  11327. }
  11328. };
  11329. Phaser.StateManager.prototype.constructor = Phaser.StateManager;
  11330. /**
  11331. * @author Richard Davey <rich@photonstorm.com>
  11332. * @copyright 2014 Photon Storm Ltd.
  11333. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  11334. */
  11335. /**
  11336. * A basic linked list data structure.
  11337. *
  11338. * @class Phaser.LinkedList
  11339. * @constructor
  11340. */
  11341. Phaser.LinkedList = function () {
  11342. /**
  11343. * @property {object} next - Next element in the list.
  11344. * @default
  11345. */
  11346. this.next = null;
  11347. /**
  11348. * @property {object} prev - Previous element in the list.
  11349. * @default
  11350. */
  11351. this.prev = null;
  11352. /**
  11353. * @property {object} first - First element in the list.
  11354. * @default
  11355. */
  11356. this.first = null;
  11357. /**
  11358. * @property {object} last - Last element in the list.
  11359. * @default
  11360. */
  11361. this.last = null;
  11362. /**
  11363. * @property {object} game - Number of elements in the list.
  11364. * @default
  11365. */
  11366. this.total = 0;
  11367. };
  11368. Phaser.LinkedList.prototype = {
  11369. /**
  11370. * Adds a new element to this linked list.
  11371. *
  11372. * @method Phaser.LinkedList#add
  11373. * @param {object} child - The element to add to this list. Can be a Phaser.Sprite or any other object you need to quickly iterate through.
  11374. * @return {object} The child that was added.
  11375. */
  11376. add: function (child) {
  11377. // If the list is empty
  11378. if (this.total === 0 && this.first == null && this.last == null)
  11379. {
  11380. this.first = child;
  11381. this.last = child;
  11382. this.next = child;
  11383. child.prev = this;
  11384. this.total++;
  11385. return child;
  11386. }
  11387. // Get gets appended to the end of the list, regardless of anything, and it won't have any children of its own (non-nested list)
  11388. this.last.next = child;
  11389. child.prev = this.last;
  11390. this.last = child;
  11391. this.total++;
  11392. return child;
  11393. },
  11394. /**
  11395. * Removes the given element from this linked list if it exists.
  11396. *
  11397. * @method Phaser.LinkedList#remove
  11398. * @param {object} child - The child to be removed from the list.
  11399. */
  11400. remove: function (child) {
  11401. if (child == this.first)
  11402. {
  11403. // It was 'first', make 'first' point to first.next
  11404. this.first = this.first.next;
  11405. }
  11406. else if (child == this.last)
  11407. {
  11408. // It was 'last', make 'last' point to last.prev
  11409. this.last = this.last.prev;
  11410. }
  11411. if (child.prev)
  11412. {
  11413. // make child.prev.next point to childs.next instead of child
  11414. child.prev.next = child.next;
  11415. }
  11416. if (child.next)
  11417. {
  11418. // make child.next.prev point to child.prev instead of child
  11419. child.next.prev = child.prev;
  11420. }
  11421. child.next = child.prev = null;
  11422. if (this.first == null )
  11423. {
  11424. this.last = null;
  11425. }
  11426. this.total--;
  11427. },
  11428. /**
  11429. * Calls a function on all members of this list, using the member as the context for the callback.
  11430. * The function must exist on the member.
  11431. *
  11432. * @method Phaser.LinkedList#callAll
  11433. * @param {function} callback - The function to call.
  11434. */
  11435. callAll: function (callback) {
  11436. if (!this.first || !this.last)
  11437. {
  11438. return;
  11439. }
  11440. var entity = this.first;
  11441. do
  11442. {
  11443. if (entity && entity[callback])
  11444. {
  11445. entity[callback].call(entity);
  11446. }
  11447. entity = entity.next;
  11448. }
  11449. while(entity != this.last.next);
  11450. }
  11451. };
  11452. Phaser.LinkedList.prototype.constructor = Phaser.LinkedList;
  11453. /**
  11454. * @author Richard Davey <rich@photonstorm.com>
  11455. * @copyright 2014 Photon Storm Ltd.
  11456. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  11457. */
  11458. /**
  11459. * @class Phaser.Signal
  11460. * @classdesc A Signal is used for object communication via a custom broadcaster instead of Events.
  11461. * @author Miller Medeiros http://millermedeiros.github.com/js-signals/
  11462. * @constructor
  11463. */
  11464. Phaser.Signal = function () {
  11465. /**
  11466. * @property {Array.<Phaser.SignalBinding>} _bindings - Internal variable.
  11467. * @private
  11468. */
  11469. this._bindings = [];
  11470. /**
  11471. * @property {any} _prevParams - Internal variable.
  11472. * @private
  11473. */
  11474. this._prevParams = null;
  11475. // enforce dispatch to aways work on same context (#47)
  11476. var self = this;
  11477. /**
  11478. * @property {function} dispatch - The dispatch function is what sends the Signal out.
  11479. */
  11480. this.dispatch = function(){
  11481. Phaser.Signal.prototype.dispatch.apply(self, arguments);
  11482. };
  11483. };
  11484. Phaser.Signal.prototype = {
  11485. /**
  11486. * If Signal should keep record of previously dispatched parameters and
  11487. * automatically execute listener during `add()`/`addOnce()` if Signal was
  11488. * already dispatched before.
  11489. * @property {boolean} memorize
  11490. */
  11491. memorize: false,
  11492. /**
  11493. * @property {boolean} _shouldPropagate
  11494. * @private
  11495. */
  11496. _shouldPropagate: true,
  11497. /**
  11498. * If Signal is active and should broadcast events.
  11499. * <p><strong>IMPORTANT:</strong> Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.</p>
  11500. * @property {boolean} active
  11501. * @default
  11502. */
  11503. active: true,
  11504. /**
  11505. * @method Phaser.Signal#validateListener
  11506. * @param {function} listener - Signal handler function.
  11507. * @param {string} fnName - Function name.
  11508. * @private
  11509. */
  11510. validateListener: function (listener, fnName) {
  11511. if (typeof listener !== 'function') {
  11512. throw new Error('listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName));
  11513. }
  11514. },
  11515. /**
  11516. * @method Phaser.Signal#_registerListener
  11517. * @param {function} listener - Signal handler function.
  11518. * @param {boolean} isOnce - Description.
  11519. * @param {object} [listenerContext] - Description.
  11520. * @param {number} [priority] - The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0).
  11521. * @return {Phaser.SignalBinding} An Object representing the binding between the Signal and listener.
  11522. * @private
  11523. */
  11524. _registerListener: function (listener, isOnce, listenerContext, priority) {
  11525. var prevIndex = this._indexOfListener(listener, listenerContext),
  11526. binding;
  11527. if (prevIndex !== -1) {
  11528. binding = this._bindings[prevIndex];
  11529. if (binding.isOnce() !== isOnce) {
  11530. throw new Error('You cannot add' + (isOnce ? '' : 'Once') + '() then add' + (!isOnce ? '' : 'Once') + '() the same listener without removing the relationship first.');
  11531. }
  11532. } else {
  11533. binding = new Phaser.SignalBinding(this, listener, isOnce, listenerContext, priority);
  11534. this._addBinding(binding);
  11535. }
  11536. if (this.memorize && this._prevParams) {
  11537. binding.execute(this._prevParams);
  11538. }
  11539. return binding;
  11540. },
  11541. /**
  11542. * @method Phaser.Signal#_addBinding
  11543. * @param {Phaser.SignalBinding} binding - An Object representing the binding between the Signal and listener.
  11544. * @private
  11545. */
  11546. _addBinding: function (binding) {
  11547. //simplified insertion sort
  11548. var n = this._bindings.length;
  11549. do { --n; } while (this._bindings[n] && binding._priority <= this._bindings[n]._priority);
  11550. this._bindings.splice(n + 1, 0, binding);
  11551. },
  11552. /**
  11553. * @method Phaser.Signal#_indexOfListener
  11554. * @param {function} listener - Signal handler function.
  11555. * @return {number} Description.
  11556. * @private
  11557. */
  11558. _indexOfListener: function (listener, context) {
  11559. var n = this._bindings.length,
  11560. cur;
  11561. while (n--) {
  11562. cur = this._bindings[n];
  11563. if (cur._listener === listener && cur.context === context) {
  11564. return n;
  11565. }
  11566. }
  11567. return -1;
  11568. },
  11569. /**
  11570. * Check if listener was attached to Signal.
  11571. *
  11572. * @method Phaser.Signal#has
  11573. * @param {Function} listener - Signal handler function.
  11574. * @param {Object} [context] - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
  11575. * @return {boolean} If Signal has the specified listener.
  11576. */
  11577. has: function (listener, context) {
  11578. return this._indexOfListener(listener, context) !== -1;
  11579. },
  11580. /**
  11581. * Add a listener to the signal.
  11582. *
  11583. * @method Phaser.Signal#add
  11584. * @param {function} listener - Signal handler function.
  11585. * @param {object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
  11586. * @param {number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0).
  11587. * @return {Phaser.SignalBinding} An Object representing the binding between the Signal and listener.
  11588. */
  11589. add: function (listener, listenerContext, priority) {
  11590. this.validateListener(listener, 'add');
  11591. return this._registerListener(listener, false, listenerContext, priority);
  11592. },
  11593. /**
  11594. * Add listener to the signal that should be removed after first execution (will be executed only once).
  11595. *
  11596. * @method Phaser.Signal#addOnce
  11597. * @param {function} listener Signal handler function.
  11598. * @param {object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
  11599. * @param {number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0)
  11600. * @return {Phaser.SignalBinding} An Object representing the binding between the Signal and listener.
  11601. */
  11602. addOnce: function (listener, listenerContext, priority) {
  11603. this.validateListener(listener, 'addOnce');
  11604. return this._registerListener(listener, true, listenerContext, priority);
  11605. },
  11606. /**
  11607. * Remove a single listener from the dispatch queue.
  11608. *
  11609. * @method Phaser.Signal#remove
  11610. * @param {function} listener Handler function that should be removed.
  11611. * @param {object} [context] Execution context (since you can add the same handler multiple times if executing in a different context).
  11612. * @return {function} Listener handler function.
  11613. */
  11614. remove: function (listener, context) {
  11615. this.validateListener(listener, 'remove');
  11616. var i = this._indexOfListener(listener, context);
  11617. if (i !== -1)
  11618. {
  11619. this._bindings[i]._destroy(); //no reason to a Phaser.SignalBinding exist if it isn't attached to a signal
  11620. this._bindings.splice(i, 1);
  11621. }
  11622. return listener;
  11623. },
  11624. /**
  11625. * Remove all listeners from the Signal.
  11626. *
  11627. * @method Phaser.Signal#removeAll
  11628. */
  11629. removeAll: function () {
  11630. var n = this._bindings.length;
  11631. while (n--) {
  11632. this._bindings[n]._destroy();
  11633. }
  11634. this._bindings.length = 0;
  11635. },
  11636. /**
  11637. * Gets the total number of listeneres attached to ths Signal.
  11638. *
  11639. * @method Phaser.Signal#getNumListeners
  11640. * @return {number} Number of listeners attached to the Signal.
  11641. */
  11642. getNumListeners: function () {
  11643. return this._bindings.length;
  11644. },
  11645. /**
  11646. * Stop propagation of the event, blocking the dispatch to next listeners on the queue.
  11647. * IMPORTANT: should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast.
  11648. * @see Signal.prototype.disable
  11649. *
  11650. * @method Phaser.Signal#halt
  11651. */
  11652. halt: function () {
  11653. this._shouldPropagate = false;
  11654. },
  11655. /**
  11656. * Dispatch/Broadcast Signal to all listeners added to the queue.
  11657. *
  11658. * @method Phaser.Signal#dispatch
  11659. * @param {any} [params] - Parameters that should be passed to each handler.
  11660. */
  11661. dispatch: function () {
  11662. if (!this.active)
  11663. {
  11664. return;
  11665. }
  11666. var paramsArr = Array.prototype.slice.call(arguments);
  11667. var n = this._bindings.length;
  11668. var bindings;
  11669. if (this.memorize)
  11670. {
  11671. this._prevParams = paramsArr;
  11672. }
  11673. if (!n)
  11674. {
  11675. // Should come after memorize
  11676. return;
  11677. }
  11678. bindings = this._bindings.slice(); //clone array in case add/remove items during dispatch
  11679. this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
  11680. //execute all callbacks until end of the list or until a callback returns `false` or stops propagation
  11681. //reverse loop since listeners with higher priority will be added at the end of the list
  11682. do { n--; } while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false);
  11683. },
  11684. /**
  11685. * Forget memorized arguments.
  11686. * @see Signal.memorize
  11687. *
  11688. * @method Phaser.Signal#forget
  11689. */
  11690. forget: function(){
  11691. this._prevParams = null;
  11692. },
  11693. /**
  11694. * Remove all bindings from signal and destroy any reference to external objects (destroy Signal object).
  11695. * IMPORTANT: calling any method on the signal instance after calling dispose will throw errors.
  11696. *
  11697. * @method Phaser.Signal#dispose
  11698. */
  11699. dispose: function () {
  11700. this.removeAll();
  11701. delete this._bindings;
  11702. delete this._prevParams;
  11703. },
  11704. /**
  11705. *
  11706. * @method Phaser.Signal#toString
  11707. * @return {string} String representation of the object.
  11708. */
  11709. toString: function () {
  11710. return '[Phaser.Signal active:'+ this.active +' numListeners:'+ this.getNumListeners() +']';
  11711. }
  11712. };
  11713. Phaser.Signal.prototype.constructor = Phaser.Signal;
  11714. /**
  11715. * @author Richard Davey <rich@photonstorm.com>
  11716. * @copyright 2014 Photon Storm Ltd.
  11717. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  11718. */
  11719. /**
  11720. * @class Phaser.SignalBinding
  11721. * @classdesc Object that represents a binding between a Signal and a listener function.
  11722. * This is an internal constructor and shouldn't be called by regular users.
  11723. * Inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
  11724. *
  11725. * @author Miller Medeiros http://millermedeiros.github.com/js-signals/
  11726. * @constructor
  11727. * @param {Phaser.Signal} signal - Reference to Signal object that listener is currently bound to.
  11728. * @param {function} listener - Handler function bound to the signal.
  11729. * @param {boolean} isOnce - If binding should be executed just once.
  11730. * @param {object} [listenerContext] - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
  11731. * @param {number} [priority] - The priority level of the event listener. (default = 0).
  11732. */
  11733. Phaser.SignalBinding = function (signal, listener, isOnce, listenerContext, priority) {
  11734. /**
  11735. * @property {Phaser.Game} _listener - Handler function bound to the signal.
  11736. * @private
  11737. */
  11738. this._listener = listener;
  11739. /**
  11740. * @property {boolean} _isOnce - If binding should be executed just once.
  11741. * @private
  11742. */
  11743. this._isOnce = isOnce;
  11744. /**
  11745. * @property {object|undefined|null} context - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
  11746. */
  11747. this.context = listenerContext;
  11748. /**
  11749. * @property {Phaser.Signal} _signal - Reference to Signal object that listener is currently bound to.
  11750. * @private
  11751. */
  11752. this._signal = signal;
  11753. /**
  11754. * @property {number} _priority - Listener priority.
  11755. * @private
  11756. */
  11757. this._priority = priority || 0;
  11758. };
  11759. Phaser.SignalBinding.prototype = {
  11760. /**
  11761. * If binding is active and should be executed.
  11762. * @property {boolean} active
  11763. * @default
  11764. */
  11765. active: true,
  11766. /**
  11767. * Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute` (curried parameters).
  11768. * @property {array|null} params
  11769. * @default
  11770. */
  11771. params: null,
  11772. /**
  11773. * Call listener passing arbitrary parameters.
  11774. * If binding was added using `Signal.addOnce()` it will be automatically removed from signal dispatch queue, this method is used internally for the signal dispatch.
  11775. * @method Phaser.SignalBinding#execute
  11776. * @param {array} [paramsArr] - Array of parameters that should be passed to the listener.
  11777. * @return {any} Value returned by the listener.
  11778. */
  11779. execute: function(paramsArr) {
  11780. var handlerReturn, params;
  11781. if (this.active && !!this._listener)
  11782. {
  11783. params = this.params ? this.params.concat(paramsArr) : paramsArr;
  11784. handlerReturn = this._listener.apply(this.context, params);
  11785. if (this._isOnce)
  11786. {
  11787. this.detach();
  11788. }
  11789. }
  11790. return handlerReturn;
  11791. },
  11792. /**
  11793. * Detach binding from signal.
  11794. * alias to: @see mySignal.remove(myBinding.getListener());
  11795. * @method Phaser.SignalBinding#detach
  11796. * @return {function|null} Handler function bound to the signal or `null` if binding was previously detached.
  11797. */
  11798. detach: function () {
  11799. return this.isBound() ? this._signal.remove(this._listener, this.context) : null;
  11800. },
  11801. /**
  11802. * @method Phaser.SignalBinding#isBound
  11803. * @return {boolean} True if binding is still bound to the signal and has a listener.
  11804. */
  11805. isBound: function () {
  11806. return (!!this._signal && !!this._listener);
  11807. },
  11808. /**
  11809. * @method Phaser.SignalBinding#isOnce
  11810. * @return {boolean} If SignalBinding will only be executed once.
  11811. */
  11812. isOnce: function () {
  11813. return this._isOnce;
  11814. },
  11815. /**
  11816. * @method Phaser.SignalBinding#getListener
  11817. * @return {Function} Handler function bound to the signal.
  11818. */
  11819. getListener: function () {
  11820. return this._listener;
  11821. },
  11822. /**
  11823. * @method Phaser.SignalBinding#getSignal
  11824. * @return {Signal} Signal that listener is currently bound to.
  11825. */
  11826. getSignal: function () {
  11827. return this._signal;
  11828. },
  11829. /**
  11830. * @method Phaser.SignalBinding#_destroy
  11831. * Delete instance properties
  11832. * @private
  11833. */
  11834. _destroy: function () {
  11835. delete this._signal;
  11836. delete this._listener;
  11837. delete this.context;
  11838. },
  11839. /**
  11840. * @method Phaser.SignalBinding#toString
  11841. * @return {string} String representation of the object.
  11842. */
  11843. toString: function () {
  11844. return '[Phaser.SignalBinding isOnce:' + this._isOnce +', isBound:'+ this.isBound() +', active:' + this.active + ']';
  11845. }
  11846. };
  11847. Phaser.SignalBinding.prototype.constructor = Phaser.SignalBinding;
  11848. /**
  11849. * @author Richard Davey <rich@photonstorm.com>
  11850. * @copyright 2014 Photon Storm Ltd.
  11851. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  11852. */
  11853. /**
  11854. * This is a base Filter template to use for any Phaser filter development.
  11855. *
  11856. * @class Phaser.Filter
  11857. * @classdesc Phaser - Filter
  11858. * @constructor
  11859. * @param {Phaser.Game} game - A reference to the currently running game.
  11860. * @param {Object} uniforms - Uniform mappings object
  11861. * @param {Array} fragmentSrc - The fragment shader code.
  11862. */
  11863. Phaser.Filter = function (game, uniforms, fragmentSrc) {
  11864. /**
  11865. * @property {Phaser.Game} game - A reference to the currently running game.
  11866. */
  11867. this.game = game;
  11868. /**
  11869. * @property {number} type - The const type of this object, either Phaser.WEBGL_FILTER or Phaser.CANVAS_FILTER.
  11870. * @default
  11871. */
  11872. this.type = Phaser.WEBGL_FILTER;
  11873. /**
  11874. * An array of passes - some filters contain a few steps this array simply stores the steps in a linear fashion.
  11875. * For example the blur filter has two passes blurX and blurY.
  11876. * @property {array} passes - An array of filter objects.
  11877. * @private
  11878. */
  11879. this.passes = [this];
  11880. /**
  11881. * @property {array} shaders - Array an array of shaders.
  11882. * @private
  11883. */
  11884. this.shaders = [];
  11885. /**
  11886. * @property {boolean} dirty - Internal PIXI var.
  11887. * @default
  11888. */
  11889. this.dirty = true;
  11890. /**
  11891. * @property {number} padding - Internal PIXI var.
  11892. * @default
  11893. */
  11894. this.padding = 0;
  11895. /**
  11896. * @property {object} uniforms - Default uniform mappings.
  11897. */
  11898. this.uniforms = {
  11899. time: { type: '1f', value: 0 },
  11900. resolution: { type: '2f', value: { x: 256, y: 256 }},
  11901. mouse: { type: '2f', value: { x: 0.0, y: 0.0 }}
  11902. };
  11903. /**
  11904. * @property {array} fragmentSrc - The fragment shader code.
  11905. */
  11906. this.fragmentSrc = fragmentSrc || [];
  11907. };
  11908. Phaser.Filter.prototype = {
  11909. /**
  11910. * Should be over-ridden.
  11911. * @method Phaser.Filter#init
  11912. */
  11913. init: function () {
  11914. // This should be over-ridden. Will receive a variable number of arguments.
  11915. },
  11916. /**
  11917. * Set the resolution uniforms on the filter.
  11918. * @method Phaser.Filter#setResolution
  11919. * @param {number} width - The width of the display.
  11920. * @param {number} height - The height of the display.
  11921. */
  11922. setResolution: function (width, height) {
  11923. this.uniforms.resolution.value.x = width;
  11924. this.uniforms.resolution.value.y = height;
  11925. },
  11926. /**
  11927. * Updates the filter.
  11928. * @method Phaser.Filter#update
  11929. * @param {Phaser.Pointer} [pointer] - A Pointer object to use for the filter. The coordinates are mapped to the mouse uniform.
  11930. */
  11931. update: function (pointer) {
  11932. if (typeof pointer !== 'undefined')
  11933. {
  11934. if (pointer.x > 0)
  11935. {
  11936. this.uniforms.mouse.x = pointer.x.toFixed(2);
  11937. }
  11938. if (pointer.y > 0)
  11939. {
  11940. this.uniforms.mouse.y = pointer.y.toFixed(2);
  11941. }
  11942. }
  11943. this.uniforms.time.value = this.game.time.totalElapsedSeconds();
  11944. },
  11945. /**
  11946. * Clear down this Filter and null out references
  11947. * @method Phaser.Filter#destroy
  11948. */
  11949. destroy: function () {
  11950. this.game = null;
  11951. }
  11952. };
  11953. Phaser.Filter.prototype.constructor = Phaser.Filter;
  11954. /**
  11955. * @name Phaser.Filter#width
  11956. * @property {number} width - The width (resolution uniform)
  11957. */
  11958. Object.defineProperty(Phaser.Filter.prototype, 'width', {
  11959. get: function() {
  11960. return this.uniforms.resolution.value.x;
  11961. },
  11962. set: function(value) {
  11963. this.uniforms.resolution.value.x = value;
  11964. }
  11965. });
  11966. /**
  11967. * @name Phaser.Filter#height
  11968. * @property {number} height - The height (resolution uniform)
  11969. */
  11970. Object.defineProperty(Phaser.Filter.prototype, 'height', {
  11971. get: function() {
  11972. return this.uniforms.resolution.value.y;
  11973. },
  11974. set: function(value) {
  11975. this.uniforms.resolution.value.y = value;
  11976. }
  11977. });
  11978. /**
  11979. * @author Richard Davey <rich@photonstorm.com>
  11980. * @copyright 2014 Photon Storm Ltd.
  11981. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  11982. */
  11983. /**
  11984. * This is a base Plugin template to use for any Phaser plugin development.
  11985. *
  11986. * @class Phaser.Plugin
  11987. * @classdesc Phaser - Plugin
  11988. * @constructor
  11989. * @param {Phaser.Game} game - A reference to the currently running game.
  11990. * @param {Any} parent - The object that owns this plugin, usually Phaser.PluginManager.
  11991. */
  11992. Phaser.Plugin = function (game, parent) {
  11993. if (typeof parent === 'undefined') { parent = null; }
  11994. /**
  11995. * @property {Phaser.Game} game - A reference to the currently running game.
  11996. */
  11997. this.game = game;
  11998. /**
  11999. * @property {Any} parent - The parent of this plugin. If added to the PluginManager the parent will be set to that, otherwise it will be null.
  12000. */
  12001. this.parent = parent;
  12002. /**
  12003. * @property {boolean} active - A Plugin with active=true has its preUpdate and update methods called by the parent, otherwise they are skipped.
  12004. * @default
  12005. */
  12006. this.active = false;
  12007. /**
  12008. * @property {boolean} visible - A Plugin with visible=true has its render and postRender methods called by the parent, otherwise they are skipped.
  12009. * @default
  12010. */
  12011. this.visible = false;
  12012. /**
  12013. * @property {boolean} hasPreUpdate - A flag to indicate if this plugin has a preUpdate method.
  12014. * @default
  12015. */
  12016. this.hasPreUpdate = false;
  12017. /**
  12018. * @property {boolean} hasUpdate - A flag to indicate if this plugin has an update method.
  12019. * @default
  12020. */
  12021. this.hasUpdate = false;
  12022. /**
  12023. * @property {boolean} hasPostUpdate - A flag to indicate if this plugin has a postUpdate method.
  12024. * @default
  12025. */
  12026. this.hasPostUpdate = false;
  12027. /**
  12028. * @property {boolean} hasRender - A flag to indicate if this plugin has a render method.
  12029. * @default
  12030. */
  12031. this.hasRender = false;
  12032. /**
  12033. * @property {boolean} hasPostRender - A flag to indicate if this plugin has a postRender method.
  12034. * @default
  12035. */
  12036. this.hasPostRender = false;
  12037. };
  12038. Phaser.Plugin.prototype = {
  12039. /**
  12040. * Pre-update is called at the very start of the update cycle, before any other subsystems have been updated (including Physics).
  12041. * It is only called if active is set to true.
  12042. * @method Phaser.Plugin#preUpdate
  12043. */
  12044. preUpdate: function () {
  12045. },
  12046. /**
  12047. * Update is called after all the core subsystems (Input, Tweens, Sound, etc) and the State have updated, but before the render.
  12048. * It is only called if active is set to true.
  12049. * @method Phaser.Plugin#update
  12050. */
  12051. update: function () {
  12052. },
  12053. /**
  12054. * Render is called right after the Game Renderer completes, but before the State.render.
  12055. * It is only called if visible is set to true.
  12056. * @method Phaser.Plugin#render
  12057. */
  12058. render: function () {
  12059. },
  12060. /**
  12061. * Post-render is called after the Game Renderer and State.render have run.
  12062. * It is only called if visible is set to true.
  12063. * @method Phaser.Plugin#postRender
  12064. */
  12065. postRender: function () {
  12066. },
  12067. /**
  12068. * Clear down this Plugin and null out references
  12069. * @method Phaser.Plugin#destroy
  12070. */
  12071. destroy: function () {
  12072. this.game = null;
  12073. this.parent = null;
  12074. this.active = false;
  12075. this.visible = false;
  12076. }
  12077. };
  12078. Phaser.Plugin.prototype.constructor = Phaser.Plugin;
  12079. /* jshint newcap: false */
  12080. /**
  12081. * @author Richard Davey <rich@photonstorm.com>
  12082. * @copyright 2014 Photon Storm Ltd.
  12083. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  12084. */
  12085. /**
  12086. * The Plugin Manager is responsible for the loading, running and unloading of Phaser Plugins.
  12087. *
  12088. * @class Phaser.PluginManager
  12089. * @classdesc Phaser - PluginManager
  12090. * @constructor
  12091. * @param {Phaser.Game} game - A reference to the currently running game.
  12092. */
  12093. Phaser.PluginManager = function(game) {
  12094. /**
  12095. * @property {Phaser.Game} game - A reference to the currently running game.
  12096. */
  12097. this.game = game;
  12098. /**
  12099. * @property {array} plugins - An array of all the plugins being managed by this PluginManager.
  12100. */
  12101. this.plugins = [];
  12102. /**
  12103. * @property {number} _len - Internal cache var.
  12104. * @private
  12105. */
  12106. this._len = 0;
  12107. /**
  12108. * @property {number} _i - Internal cache var.
  12109. * @private
  12110. */
  12111. this._i = 0;
  12112. };
  12113. Phaser.PluginManager.prototype = {
  12114. /**
  12115. * Add a new Plugin into the PluginManager.
  12116. * The Plugin must have 2 properties: game and parent. Plugin.game is set to ths game reference the PluginManager uses, and parent is set to the PluginManager.
  12117. *
  12118. * @method Phaser.PluginManager#add
  12119. * @param {object|Phaser.Plugin} plugin - The Plugin to add into the PluginManager. This can be a function or an existing object.
  12120. * @return {Phaser.Plugin} The Plugin that was added to the manager.
  12121. */
  12122. add: function (plugin) {
  12123. var result = false;
  12124. // Prototype?
  12125. if (typeof plugin === 'function')
  12126. {
  12127. plugin = new plugin(this.game, this._parent);
  12128. }
  12129. else
  12130. {
  12131. plugin.game = this.game;
  12132. plugin.parent = this;
  12133. }
  12134. // Check for methods now to avoid having to do this every loop
  12135. if (typeof plugin['preUpdate'] === 'function')
  12136. {
  12137. plugin.hasPreUpdate = true;
  12138. result = true;
  12139. }
  12140. if (typeof plugin['update'] === 'function')
  12141. {
  12142. plugin.hasUpdate = true;
  12143. result = true;
  12144. }
  12145. if (typeof plugin['postUpdate'] === 'function')
  12146. {
  12147. plugin.hasPostUpdate = true;
  12148. result = true;
  12149. }
  12150. if (typeof plugin['render'] === 'function')
  12151. {
  12152. plugin.hasRender = true;
  12153. result = true;
  12154. }
  12155. if (typeof plugin['postRender'] === 'function')
  12156. {
  12157. plugin.hasPostRender = true;
  12158. result = true;
  12159. }
  12160. // The plugin must have at least one of the above functions to be added to the PluginManager.
  12161. if (result)
  12162. {
  12163. if (plugin.hasPreUpdate || plugin.hasUpdate || plugin.hasPostUpdate)
  12164. {
  12165. plugin.active = true;
  12166. }
  12167. if (plugin.hasRender || plugin.hasPostRender)
  12168. {
  12169. plugin.visible = true;
  12170. }
  12171. this._len = this.plugins.push(plugin);
  12172. // Allows plugins to run potentially destructive code outside of the constructor, and only if being added to the PluginManager
  12173. if (typeof plugin['init'] === 'function')
  12174. {
  12175. plugin.init();
  12176. }
  12177. return plugin;
  12178. }
  12179. else
  12180. {
  12181. return null;
  12182. }
  12183. },
  12184. /**
  12185. * Remove a Plugin from the PluginManager. It calls Plugin.destroy on the plugin before removing it from the manager.
  12186. *
  12187. * @method Phaser.PluginManager#remove
  12188. * @param {Phaser.Plugin} plugin - The plugin to be removed.
  12189. */
  12190. remove: function (plugin) {
  12191. this._i = this._len;
  12192. while (this._i--)
  12193. {
  12194. if (this.plugins[this._i] === plugin)
  12195. {
  12196. plugin.destroy();
  12197. this.plugins.splice(this._i, 1);
  12198. this._len--;
  12199. return;
  12200. }
  12201. }
  12202. },
  12203. /**
  12204. * Remove all Plugins from the PluginManager. It calls Plugin.destroy on every plugin before removing it from the manager.
  12205. *
  12206. * @method Phaser.PluginManager#removeAll
  12207. */
  12208. removeAll: function() {
  12209. this._i = this._len;
  12210. while (this._i--)
  12211. {
  12212. this.plugins[this._i].destroy();
  12213. }
  12214. this.plugins.length = 0;
  12215. this._len = 0;
  12216. },
  12217. /**
  12218. * Pre-update is called at the very start of the update cycle, before any other subsystems have been updated (including Physics).
  12219. * It only calls plugins who have active=true.
  12220. *
  12221. * @method Phaser.PluginManager#preUpdate
  12222. */
  12223. preUpdate: function () {
  12224. this._i = this._len;
  12225. while (this._i--)
  12226. {
  12227. if (this.plugins[this._i].active && this.plugins[this._i].hasPreUpdate)
  12228. {
  12229. this.plugins[this._i].preUpdate();
  12230. }
  12231. }
  12232. },
  12233. /**
  12234. * Update is called after all the core subsystems (Input, Tweens, Sound, etc) and the State have updated, but before the render.
  12235. * It only calls plugins who have active=true.
  12236. *
  12237. * @method Phaser.PluginManager#update
  12238. */
  12239. update: function () {
  12240. this._i = this._len;
  12241. while (this._i--)
  12242. {
  12243. if (this.plugins[this._i].active && this.plugins[this._i].hasUpdate)
  12244. {
  12245. this.plugins[this._i].update();
  12246. }
  12247. }
  12248. },
  12249. /**
  12250. * PostUpdate is the last thing to be called before the world render.
  12251. * In particular, it is called after the world postUpdate, which means the camera has been adjusted.
  12252. * It only calls plugins who have active=true.
  12253. *
  12254. * @method Phaser.PluginManager#postUpdate
  12255. */
  12256. postUpdate: function () {
  12257. this._i = this._len;
  12258. while (this._i--)
  12259. {
  12260. if (this.plugins[this._i].active && this.plugins[this._i].hasPostUpdate)
  12261. {
  12262. this.plugins[this._i].postUpdate();
  12263. }
  12264. }
  12265. },
  12266. /**
  12267. * Render is called right after the Game Renderer completes, but before the State.render.
  12268. * It only calls plugins who have visible=true.
  12269. *
  12270. * @method Phaser.PluginManager#render
  12271. */
  12272. render: function () {
  12273. this._i = this._len;
  12274. while (this._i--)
  12275. {
  12276. if (this.plugins[this._i].visible && this.plugins[this._i].hasRender)
  12277. {
  12278. this.plugins[this._i].render();
  12279. }
  12280. }
  12281. },
  12282. /**
  12283. * Post-render is called after the Game Renderer and State.render have run.
  12284. * It only calls plugins who have visible=true.
  12285. *
  12286. * @method Phaser.PluginManager#postRender
  12287. */
  12288. postRender: function () {
  12289. this._i = this._len;
  12290. while (this._i--)
  12291. {
  12292. if (this.plugins[this._i].visible && this.plugins[this._i].hasPostRender)
  12293. {
  12294. this.plugins[this._i].postRender();
  12295. }
  12296. }
  12297. },
  12298. /**
  12299. * Clear down this PluginManager, calls destroy on every plugin and nulls out references.
  12300. *
  12301. * @method Phaser.PluginManager#destroy
  12302. */
  12303. destroy: function () {
  12304. this.removeAll();
  12305. this.game = null;
  12306. }
  12307. };
  12308. Phaser.PluginManager.prototype.constructor = Phaser.PluginManager;
  12309. /**
  12310. * @author Richard Davey <rich@photonstorm.com>
  12311. * @copyright 2014 Photon Storm Ltd.
  12312. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  12313. */
  12314. /**
  12315. * The Stage controls the canvas on which everything is displayed. It handles display within the browser,
  12316. * focus handling, game resizing, scaling and the pause, boot and orientation screens.
  12317. *
  12318. * @class Phaser.Stage
  12319. * @extends PIXI.Stage
  12320. * @constructor
  12321. * @param {Phaser.Game} game - Game reference to the currently running game.
  12322. * @param {number} width - Width of the canvas element.
  12323. * @param {number} height - Height of the canvas element.
  12324. */
  12325. Phaser.Stage = function (game, width, height) {
  12326. /**
  12327. * @property {Phaser.Game} game - A reference to the currently running Game.
  12328. */
  12329. this.game = game;
  12330. /**
  12331. * @property {Phaser.Point} offset - Holds the offset coordinates of the Game.canvas from the top-left of the browser window (used by Input and other classes)
  12332. */
  12333. this.offset = new Phaser.Point();
  12334. PIXI.Stage.call(this, 0x000000, false);
  12335. /**
  12336. * @property {string} name - The name of this object.
  12337. * @default
  12338. */
  12339. this.name = '_stage_root';
  12340. this.interactive = false;
  12341. /**
  12342. * @property {boolean} disableVisibilityChange - By default if the browser tab loses focus the game will pause. You can stop that behaviour by setting this property to true.
  12343. * @default
  12344. */
  12345. this.disableVisibilityChange = false;
  12346. /**
  12347. * @property {number|false} checkOffsetInterval - The time (in ms) between which the stage should check to see if it has moved.
  12348. * @default
  12349. */
  12350. this.checkOffsetInterval = 2500;
  12351. /**
  12352. * @property {boolean} exists - If exists is true the Stage and all children are updated, otherwise it is skipped.
  12353. * @default
  12354. */
  12355. this.exists = true;
  12356. /**
  12357. * @property {number} currentRenderOrderID - Reset each frame, keeps a count of the total number of objects updated.
  12358. */
  12359. this.currentRenderOrderID = 0;
  12360. /**
  12361. * @property {string} hiddenVar - The page visibility API event name.
  12362. * @private
  12363. */
  12364. this._hiddenVar = 'hidden';
  12365. /**
  12366. * @property {number} _nextOffsetCheck - The time to run the next offset check.
  12367. * @private
  12368. */
  12369. this._nextOffsetCheck = 0;
  12370. /**
  12371. * @property {number} _backgroundColor - Stage background color.
  12372. * @private
  12373. */
  12374. this._backgroundColor = 0x000000;
  12375. if (game.config)
  12376. {
  12377. this.parseConfig(game.config);
  12378. }
  12379. else
  12380. {
  12381. this.game.canvas = Phaser.Canvas.create(width, height);
  12382. this.game.canvas.style['-webkit-full-screen'] = 'width: 100%; height: 100%';
  12383. }
  12384. };
  12385. Phaser.Stage.prototype = Object.create(PIXI.Stage.prototype);
  12386. Phaser.Stage.prototype.constructor = Phaser.Stage;
  12387. /**
  12388. * This is called automatically after the plugins preUpdate and before the State.update.
  12389. * Most objects have preUpdate methods and it's where initial movement and positioning is done.
  12390. *
  12391. * @method Phaser.Stage#preUpdate
  12392. */
  12393. Phaser.Stage.prototype.preUpdate = function () {
  12394. this.currentRenderOrderID = 0;
  12395. // This can't loop in reverse, we need the orderID to be in sequence
  12396. var len = this.children.length;
  12397. for (var i = 0; i < len; i++)
  12398. {
  12399. this.children[i].preUpdate();
  12400. }
  12401. };
  12402. /**
  12403. * This is called automatically after the State.update, but before particles or plugins update.
  12404. *
  12405. * @method Phaser.Stage#update
  12406. */
  12407. Phaser.Stage.prototype.update = function () {
  12408. var i = this.children.length;
  12409. while (i--)
  12410. {
  12411. this.children[i].update();
  12412. }
  12413. };
  12414. /**
  12415. * This is called automatically before the renderer runs and after the plugins have updated.
  12416. * In postUpdate this is where all the final physics calculatations and object positioning happens.
  12417. * The objects are processed in the order of the display list.
  12418. * The only exception to this is if the camera is following an object, in which case that is updated first.
  12419. *
  12420. * @method Phaser.Stage#postUpdate
  12421. */
  12422. Phaser.Stage.prototype.postUpdate = function () {
  12423. if (this.game.world.camera.target)
  12424. {
  12425. this.game.world.camera.target.postUpdate();
  12426. this.game.world.camera.update();
  12427. var i = this.children.length;
  12428. while (i--)
  12429. {
  12430. if (this.children[i] !== this.game.world.camera.target)
  12431. {
  12432. this.children[i].postUpdate();
  12433. }
  12434. }
  12435. }
  12436. else
  12437. {
  12438. this.game.world.camera.update();
  12439. var i = this.children.length;
  12440. while (i--)
  12441. {
  12442. this.children[i].postUpdate();
  12443. }
  12444. }
  12445. if (this.checkOffsetInterval !== false)
  12446. {
  12447. if (this.game.time.now > this._nextOffsetCheck)
  12448. {
  12449. Phaser.Canvas.getOffset(this.game.canvas, this.offset);
  12450. this._nextOffsetCheck = this.game.time.now + this.checkOffsetInterval;
  12451. }
  12452. }
  12453. };
  12454. /**
  12455. * Parses a Game configuration object.
  12456. *
  12457. * @method Phaser.Stage#parseConfig
  12458. * @protected
  12459. */
  12460. Phaser.Stage.prototype.parseConfig = function (config) {
  12461. if (config['canvasID'])
  12462. {
  12463. this.game.canvas = Phaser.Canvas.create(this.game.width, this.game.height, config['canvasID']);
  12464. }
  12465. else
  12466. {
  12467. this.game.canvas = Phaser.Canvas.create(this.game.width, this.game.height);
  12468. }
  12469. if (config['canvasStyle'])
  12470. {
  12471. this.game.canvas.stlye = config['canvasStyle'];
  12472. }
  12473. else
  12474. {
  12475. this.game.canvas.style['-webkit-full-screen'] = 'width: 100%; height: 100%';
  12476. }
  12477. if (config['checkOffsetInterval'])
  12478. {
  12479. this.checkOffsetInterval = config['checkOffsetInterval'];
  12480. }
  12481. if (config['disableVisibilityChange'])
  12482. {
  12483. this.disableVisibilityChange = config['disableVisibilityChange'];
  12484. }
  12485. if (config['fullScreenScaleMode'])
  12486. {
  12487. this.fullScreenScaleMode = config['fullScreenScaleMode'];
  12488. }
  12489. if (config['scaleMode'])
  12490. {
  12491. this.scaleMode = config['scaleMode'];
  12492. }
  12493. if (config['backgroundColor'])
  12494. {
  12495. this.backgroundColor = config['backgroundColor'];
  12496. }
  12497. };
  12498. /**
  12499. * Initialises the stage and adds the event listeners.
  12500. * @method Phaser.Stage#boot
  12501. * @private
  12502. */
  12503. Phaser.Stage.prototype.boot = function () {
  12504. Phaser.Canvas.getOffset(this.game.canvas, this.offset);
  12505. this.bounds = new Phaser.Rectangle(this.offset.x, this.offset.y, this.game.width, this.game.height);
  12506. var _this = this;
  12507. this._onChange = function (event) {
  12508. return _this.visibilityChange(event);
  12509. };
  12510. Phaser.Canvas.setUserSelect(this.game.canvas, 'none');
  12511. Phaser.Canvas.setTouchAction(this.game.canvas, 'none');
  12512. this.checkVisibility();
  12513. };
  12514. /**
  12515. * Starts a page visibility event listener running, or window.blur/focus if not supported by the browser.
  12516. * @method Phaser.Stage#checkVisibility
  12517. */
  12518. Phaser.Stage.prototype.checkVisibility = function () {
  12519. if (document.webkitHidden !== undefined)
  12520. {
  12521. this._hiddenVar = 'webkitvisibilitychange';
  12522. }
  12523. else if (document.mozHidden !== undefined)
  12524. {
  12525. this._hiddenVar = 'mozvisibilitychange';
  12526. }
  12527. else if (document.msHidden !== undefined)
  12528. {
  12529. this._hiddenVar = 'msvisibilitychange';
  12530. }
  12531. else if (document.hidden !== undefined)
  12532. {
  12533. this._hiddenVar = 'visibilitychange';
  12534. }
  12535. else
  12536. {
  12537. this._hiddenVar = null;
  12538. }
  12539. // Does browser support it? If not (like in IE9 or old Android) we need to fall back to blur/focus
  12540. if (this._hiddenVar)
  12541. {
  12542. document.addEventListener(this._hiddenVar, this._onChange, false);
  12543. }
  12544. window.onpagehide = this._onChange;
  12545. window.onpageshow = this._onChange;
  12546. window.onblur = this._onChange;
  12547. window.onfocus = this._onChange;
  12548. };
  12549. /**
  12550. * This method is called when the document visibility is changed.
  12551. * @method Phaser.Stage#visibilityChange
  12552. * @param {Event} event - Its type will be used to decide whether the game should be paused or not.
  12553. */
  12554. Phaser.Stage.prototype.visibilityChange = function (event) {
  12555. if (this.disableVisibilityChange)
  12556. {
  12557. return;
  12558. }
  12559. if (event.type === 'pagehide' || event.type === 'blur' || event.type === 'pageshow' || event.type === 'focus')
  12560. {
  12561. if (event.type === 'pagehide' || event.type === 'blur')
  12562. {
  12563. this.game.focusLoss(event);
  12564. }
  12565. else if (event.type === 'pageshow' || event.type === 'focus')
  12566. {
  12567. this.game.focusGain(event);
  12568. }
  12569. return;
  12570. }
  12571. if (document.hidden || document.mozHidden || document.msHidden || document.webkitHidden)
  12572. {
  12573. this.game.gamePaused(event);
  12574. }
  12575. else
  12576. {
  12577. this.game.gameResumed(event);
  12578. }
  12579. };
  12580. /**
  12581. * Sets the background color for the stage.
  12582. *
  12583. * @name Phaser.Stage#setBackgroundColor
  12584. * @param {number} backgroundColor - The color of the background, easiest way to pass this in is in hex format like: 0xFFFFFF for white.
  12585. */
  12586. Phaser.Stage.prototype.setBackgroundColor = function(backgroundColor)
  12587. {
  12588. this._backgroundColor = backgroundColor || 0x000000;
  12589. this.backgroundColorSplit = PIXI.hex2rgb(this.backgroundColor);
  12590. var hex = this._backgroundColor.toString(16);
  12591. hex = '000000'.substr(0, 6 - hex.length) + hex;
  12592. this.backgroundColorString = '#' + hex;
  12593. };
  12594. /**
  12595. * @name Phaser.Stage#backgroundColor
  12596. * @property {number|string} backgroundColor - Gets and sets the background color of the stage. The color can be given as a number: 0xff0000 or a hex string: '#ff0000'
  12597. */
  12598. Object.defineProperty(Phaser.Stage.prototype, "backgroundColor", {
  12599. get: function () {
  12600. return this._backgroundColor;
  12601. },
  12602. set: function (color) {
  12603. this._backgroundColor = color;
  12604. if (this.game.transparent === false)
  12605. {
  12606. if (typeof color === 'string')
  12607. {
  12608. color = Phaser.Color.hexToRGB(color);
  12609. }
  12610. this.setBackgroundColor(color);
  12611. }
  12612. }
  12613. });
  12614. /**
  12615. * Enable or disable texture smoothing for all objects on this Stage. Only works for bitmap/image textures. Smoothing is enabled by default.
  12616. *
  12617. * @name Phaser.Stage#smoothed
  12618. * @property {boolean} smoothed - Set to true to smooth all sprites rendered on this Stage, or false to disable smoothing (great for pixel art)
  12619. */
  12620. Object.defineProperty(Phaser.Stage.prototype, "smoothed", {
  12621. get: function () {
  12622. return !PIXI.scaleModes.LINEAR;
  12623. },
  12624. set: function (value) {
  12625. if (value)
  12626. {
  12627. PIXI.scaleModes.LINEAR = 0;
  12628. }
  12629. else
  12630. {
  12631. PIXI.scaleModes.LINEAR = 1;
  12632. }
  12633. }
  12634. });
  12635. /**
  12636. * @author Richard Davey <rich@photonstorm.com>
  12637. * @copyright 2014 Photon Storm Ltd.
  12638. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  12639. */
  12640. /**
  12641. * Phaser Group constructor.
  12642. * @class Phaser.Group
  12643. * @classdesc A Group is a container for display objects that allows for fast pooling and object recycling. Groups can be nested within other Groups and have their own local transforms.
  12644. * @constructor
  12645. * @param {Phaser.Game} game - A reference to the currently running game.
  12646. * @param {Phaser.Group|Phaser.Sprite|null} parent - The parent Group, DisplayObject or DisplayObjectContainer that this Group will be added to. If undefined it will use game.world. If null it won't be added to anything.
  12647. * @param {string} [name=group] - A name for this Group. Not used internally but useful for debugging.
  12648. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  12649. * @param {boolean} [enableBody=false] - If true all Sprites created with `Group.create` or `Group.createMulitple` will have a physics body created on them. Change the body type with physicsBodyType.
  12650. * @param {number} [physicsBodyType=0] - If enableBody is true this is the type of physics body that is created on new Sprites. Phaser.Physics.ARCADE, Phaser.Physics.P2, Phaser.Physics.NINJA, etc.
  12651. */
  12652. Phaser.Group = function (game, parent, name, addToStage, enableBody, physicsBodyType) {
  12653. if (typeof addToStage === 'undefined') { addToStage = false; }
  12654. if (typeof enableBody === 'undefined') { enableBody = false; }
  12655. if (typeof physicsBodyType === 'undefined') { physicsBodyType = Phaser.Physics.ARCADE; }
  12656. /**
  12657. * @property {Phaser.Game} game - A reference to the currently running Game.
  12658. */
  12659. this.game = game;
  12660. if (typeof parent === 'undefined')
  12661. {
  12662. parent = game.world;
  12663. }
  12664. /**
  12665. * @property {string} name - A name for this Group. Not used internally but useful for debugging.
  12666. */
  12667. this.name = name || 'group';
  12668. PIXI.DisplayObjectContainer.call(this);
  12669. if (addToStage)
  12670. {
  12671. this.game.stage.addChild(this);
  12672. }
  12673. else
  12674. {
  12675. if (parent)
  12676. {
  12677. parent.addChild(this);
  12678. }
  12679. }
  12680. /**
  12681. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  12682. */
  12683. this.z = 0;
  12684. /**
  12685. * @property {number} type - Internal Phaser Type value.
  12686. * @protected
  12687. */
  12688. this.type = Phaser.GROUP;
  12689. /**
  12690. * @property {boolean} alive - The alive property is useful for Groups that are children of other Groups and need to be included/excluded in checks like forEachAlive.
  12691. * @default
  12692. */
  12693. this.alive = true;
  12694. /**
  12695. * @property {boolean} exists - If exists is true the Group is updated, otherwise it is skipped.
  12696. * @default
  12697. */
  12698. this.exists = true;
  12699. /**
  12700. * @property {Phaser.Group|Phaser.Sprite} parent - The parent of this Group.
  12701. */
  12702. /**
  12703. * @property {Phaser.Point} scale - The scale of the Group container.
  12704. */
  12705. this.scale = new Phaser.Point(1, 1);
  12706. /**
  12707. * @property {Phaser.Point} pivot - The pivot point of the Group container.
  12708. */
  12709. /**
  12710. * The cursor is a simple way to iterate through the objects in a Group using the Group.next and Group.previous functions.
  12711. * The cursor is set to the first child added to the Group and doesn't change unless you call next, previous or set it directly with Group.cursor.
  12712. * @property {any} cursor - The current display object that the Group cursor is pointing to.
  12713. */
  12714. this.cursor = null;
  12715. /**
  12716. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  12717. */
  12718. this.cameraOffset = new Phaser.Point();
  12719. /**
  12720. * @property {boolean} enableBody - If true all Sprites created by, or added to this Group, will have a physics body enabled on them. Change the body type with `Group.physicsBodyType`.
  12721. * @default
  12722. */
  12723. this.enableBody = enableBody;
  12724. /**
  12725. * @property {boolean} enableBodyDebug - If true when a physics body is created (via Group.enableBody) it will create a physics debug object as well. Only works for P2 bodies.
  12726. */
  12727. this.enableBodyDebug = false;
  12728. /**
  12729. * @property {number} physicsBodyType - If Group.enableBody is true this is the type of physics body that is created on new Sprites. Phaser.Physics.ARCADE, Phaser.Physics.P2, Phaser.Physics.NINJA, etc.
  12730. */
  12731. this.physicsBodyType = physicsBodyType;
  12732. /**
  12733. * @property {string} _sortProperty - The property on which children are sorted.
  12734. * @private
  12735. */
  12736. this._sortProperty = 'z';
  12737. /**
  12738. * A small internal cache:
  12739. * 0 = previous position.x
  12740. * 1 = previous position.y
  12741. * 2 = previous rotation
  12742. * 3 = renderID
  12743. * 4 = fresh? (0 = no, 1 = yes)
  12744. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  12745. * 6 = exists (0 = no, 1 = yes)
  12746. * 7 = fixed to camera (0 = no, 1 = yes)
  12747. * 8 = cursor index
  12748. * 9 = sort order
  12749. * @property {Array} _cache
  12750. * @private
  12751. */
  12752. this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0 ];
  12753. };
  12754. Phaser.Group.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
  12755. Phaser.Group.prototype.constructor = Phaser.Group;
  12756. /**
  12757. * @constant
  12758. * @type {number}
  12759. */
  12760. Phaser.Group.RETURN_NONE = 0;
  12761. /**
  12762. * @constant
  12763. * @type {number}
  12764. */
  12765. Phaser.Group.RETURN_TOTAL = 1;
  12766. /**
  12767. * @constant
  12768. * @type {number}
  12769. */
  12770. Phaser.Group.RETURN_CHILD = 2;
  12771. /**
  12772. * @constant
  12773. * @type {number}
  12774. */
  12775. Phaser.Group.SORT_ASCENDING = -1;
  12776. /**
  12777. * @constant
  12778. * @type {number}
  12779. */
  12780. Phaser.Group.SORT_DESCENDING = 1;
  12781. /**
  12782. * Adds an existing object to this Group. The object can be an instance of Phaser.Sprite, Phaser.Button or any other display object.
  12783. * The child is automatically added to the top of the Group, so renders on-top of everything else within the Group. If you need to control
  12784. * that then see the addAt method.
  12785. *
  12786. * @see Phaser.Group#create
  12787. * @see Phaser.Group#addAt
  12788. * @method Phaser.Group#add
  12789. * @param {*} child - An instance of Phaser.Sprite, Phaser.Button or any other display object..
  12790. * @return {*} The child that was added to the Group.
  12791. */
  12792. Phaser.Group.prototype.add = function (child) {
  12793. if (child.parent !== this)
  12794. {
  12795. if (this.enableBody)
  12796. {
  12797. this.game.physics.enable(child, this.physicsBodyType);
  12798. }
  12799. this.addChild(child);
  12800. child.z = this.children.length;
  12801. if (child.events)
  12802. {
  12803. child.events.onAddedToGroup.dispatch(child, this);
  12804. }
  12805. if (this.cursor === null)
  12806. {
  12807. this.cursor = child;
  12808. }
  12809. }
  12810. return child;
  12811. };
  12812. /**
  12813. * Adds an existing object to this Group. The object can be an instance of Phaser.Sprite, Phaser.Button or any other display object.
  12814. * The child is added to the Group at the location specified by the index value, this allows you to control child ordering.
  12815. *
  12816. * @method Phaser.Group#addAt
  12817. * @param {*} child - An instance of Phaser.Sprite, Phaser.Button or any other display object..
  12818. * @param {number} index - The index within the Group to insert the child to.
  12819. * @return {*} The child that was added to the Group.
  12820. */
  12821. Phaser.Group.prototype.addAt = function (child, index) {
  12822. if (child.parent !== this)
  12823. {
  12824. if (this.enableBody)
  12825. {
  12826. this.game.physics.enable(child, this.physicsBodyType);
  12827. }
  12828. this.addChildAt(child, index);
  12829. this.updateZ();
  12830. if (child.events)
  12831. {
  12832. child.events.onAddedToGroup.dispatch(child, this);
  12833. }
  12834. if (this.cursor === null)
  12835. {
  12836. this.cursor = child;
  12837. }
  12838. }
  12839. return child;
  12840. };
  12841. /**
  12842. * Returns the child found at the given index within this Group.
  12843. *
  12844. * @method Phaser.Group#getAt
  12845. * @param {number} index - The index to return the child from.
  12846. * @return {*} The child that was found at the given index. If the index was out of bounds then this will return -1.
  12847. */
  12848. Phaser.Group.prototype.getAt = function (index) {
  12849. if (index < 0 || index >= this.children.length)
  12850. {
  12851. return -1;
  12852. }
  12853. else
  12854. {
  12855. return this.getChildAt(index);
  12856. }
  12857. };
  12858. /**
  12859. * Automatically creates a new Phaser.Sprite object and adds it to the top of this Group.
  12860. * Useful if you don't need to create the Sprite instances before-hand.
  12861. *
  12862. * @method Phaser.Group#create
  12863. * @param {number} x - The x coordinate to display the newly created Sprite at. The value is in relation to the Group.x point.
  12864. * @param {number} y - The y coordinate to display the newly created Sprite at. The value is in relation to the Group.y point.
  12865. * @param {string} key - The Game.cache key of the image that this Sprite will use.
  12866. * @param {number|string} [frame] - If the Sprite image contains multiple frames you can specify which one to use here.
  12867. * @param {boolean} [exists=true] - The default exists state of the Sprite.
  12868. * @return {Phaser.Sprite} The child that was created.
  12869. */
  12870. Phaser.Group.prototype.create = function (x, y, key, frame, exists) {
  12871. if (typeof exists === 'undefined') { exists = true; }
  12872. var child = new Phaser.Sprite(this.game, x, y, key, frame);
  12873. if (this.enableBody)
  12874. {
  12875. this.game.physics.enable(child, this.physicsBodyType);
  12876. }
  12877. child.exists = exists;
  12878. child.visible = exists;
  12879. child.alive = exists;
  12880. this.addChild(child);
  12881. child.z = this.children.length;
  12882. if (child.events)
  12883. {
  12884. child.events.onAddedToGroup.dispatch(child, this);
  12885. }
  12886. if (this.cursor === null)
  12887. {
  12888. this.cursor = child;
  12889. }
  12890. return child;
  12891. };
  12892. /**
  12893. * Automatically creates multiple Phaser.Sprite objects and adds them to the top of this Group.
  12894. * Useful if you need to quickly generate a pool of identical sprites, such as bullets. By default the sprites will be set to not exist
  12895. * and will be positioned at 0, 0 (relative to the Group.x/y)
  12896. *
  12897. * @method Phaser.Group#createMultiple
  12898. * @param {number} quantity - The number of Sprites to create.
  12899. * @param {string} key - The Game.cache key of the image that this Sprite will use.
  12900. * @param {number|string} [frame] - If the Sprite image contains multiple frames you can specify which one to use here.
  12901. * @param {boolean} [exists=false] - The default exists state of the Sprite.
  12902. */
  12903. Phaser.Group.prototype.createMultiple = function (quantity, key, frame, exists) {
  12904. if (typeof exists === 'undefined') { exists = false; }
  12905. for (var i = 0; i < quantity; i++)
  12906. {
  12907. this.create(0, 0, key, frame, exists);
  12908. }
  12909. };
  12910. /**
  12911. * Internal method that re-applies all of the childrens Z values.
  12912. *
  12913. * @method Phaser.Group#updateZ
  12914. * @protected
  12915. */
  12916. Phaser.Group.prototype.updateZ = function () {
  12917. var i = this.children.length;
  12918. while (i--)
  12919. {
  12920. this.children[i].z = i;
  12921. }
  12922. };
  12923. /**
  12924. * Advances the Group cursor to the next object in the Group. If it's at the end of the Group it wraps around to the first object.
  12925. *
  12926. * @method Phaser.Group#next
  12927. * @return {*} The child the cursor now points to.
  12928. */
  12929. Phaser.Group.prototype.next = function () {
  12930. if (this.cursor)
  12931. {
  12932. // Wrap the cursor?
  12933. if (this._cache[8] >= this.children.length - 1)
  12934. {
  12935. this._cache[8] = 0;
  12936. }
  12937. else
  12938. {
  12939. this._cache[8]++;
  12940. }
  12941. this.cursor = this.children[this._cache[8]];
  12942. return this.cursor;
  12943. }
  12944. };
  12945. /**
  12946. * Moves the Group cursor to the previous object in the Group. If it's at the start of the Group it wraps around to the last object.
  12947. *
  12948. * @method Phaser.Group#previous
  12949. * @return {*} The child the cursor now points to.
  12950. */
  12951. Phaser.Group.prototype.previous = function () {
  12952. if (this.cursor)
  12953. {
  12954. // Wrap the cursor?
  12955. if (this._cache[8] === 0)
  12956. {
  12957. this._cache[8] = this.children.length - 1;
  12958. }
  12959. else
  12960. {
  12961. this._cache[8]--;
  12962. }
  12963. this.cursor = this.children[this._cache[8]];
  12964. return this.cursor;
  12965. }
  12966. };
  12967. /**
  12968. * Swaps the position of two children in this Group. Both children must be in this Group.
  12969. * You cannot swap a child with itself, or swap un-parented children, doing so will return false.
  12970. *
  12971. * @method Phaser.Group#swap
  12972. * @param {*} child1 - The first child to swap.
  12973. * @param {*} child2 - The second child to swap.
  12974. */
  12975. Phaser.Group.prototype.swap = function (child1, child2) {
  12976. var result = this.swapChildren(child1, child2);
  12977. if (result)
  12978. {
  12979. this.updateZ();
  12980. }
  12981. return result;
  12982. };
  12983. /**
  12984. * Brings the given child to the top of this Group so it renders above all other children.
  12985. *
  12986. * @method Phaser.Group#bringToTop
  12987. * @param {*} child - The child to bring to the top of this Group.
  12988. * @return {*} The child that was moved.
  12989. */
  12990. Phaser.Group.prototype.bringToTop = function (child) {
  12991. if (child.parent === this && this.getIndex(child) < this.children.length)
  12992. {
  12993. this.remove(child);
  12994. this.add(child);
  12995. }
  12996. return child;
  12997. };
  12998. /**
  12999. * Sends the given child to the bottom of this Group so it renders below all other children.
  13000. *
  13001. * @method Phaser.Group#sendToBack
  13002. * @param {*} child - The child to send to the bottom of this Group.
  13003. * @return {*} The child that was moved.
  13004. */
  13005. Phaser.Group.prototype.sendToBack = function (child) {
  13006. if (child.parent === this && this.getIndex(child) > 0)
  13007. {
  13008. this.remove(child);
  13009. this.addAt(child, 0);
  13010. }
  13011. return child;
  13012. };
  13013. /**
  13014. * Moves the given child up one place in this Group unless it's already at the top.
  13015. *
  13016. * @method Phaser.Group#moveUp
  13017. * @param {*} child - The child to move up in the Group.
  13018. * @return {*} The child that was moved.
  13019. */
  13020. Phaser.Group.prototype.moveUp = function (child) {
  13021. if (child.parent === this && this.getIndex(child) < this.children.length - 1)
  13022. {
  13023. var a = this.getIndex(child);
  13024. var b = this.getAt(a + 1);
  13025. if (b)
  13026. {
  13027. this.swap(child, b);
  13028. }
  13029. }
  13030. return child;
  13031. };
  13032. /**
  13033. * Moves the given child down one place in this Group unless it's already at the top.
  13034. *
  13035. * @method Phaser.Group#moveDown
  13036. * @param {*} child - The child to move down in the Group.
  13037. * @return {*} The child that was moved.
  13038. */
  13039. Phaser.Group.prototype.moveDown = function (child) {
  13040. if (child.parent === this && this.getIndex(child) > 0)
  13041. {
  13042. var a = this.getIndex(child);
  13043. var b = this.getAt(a - 1);
  13044. if (b)
  13045. {
  13046. this.swap(child, b);
  13047. }
  13048. }
  13049. return child;
  13050. };
  13051. /**
  13052. * Positions the child found at the given index within this Group to the given x and y coordinates.
  13053. *
  13054. * @method Phaser.Group#xy
  13055. * @param {number} index - The index of the child in the Group to set the position of.
  13056. * @param {number} x - The new x position of the child.
  13057. * @param {number} y - The new y position of the child.
  13058. */
  13059. Phaser.Group.prototype.xy = function (index, x, y) {
  13060. if (index < 0 || index > this.children.length)
  13061. {
  13062. return -1;
  13063. }
  13064. else
  13065. {
  13066. this.getChildAt(index).x = x;
  13067. this.getChildAt(index).y = y;
  13068. }
  13069. };
  13070. /**
  13071. * Reverses all children in this Group. Note that this does not propagate, only direct children are re-ordered.
  13072. *
  13073. * @method Phaser.Group#reverse
  13074. */
  13075. Phaser.Group.prototype.reverse = function () {
  13076. this.children.reverse();
  13077. this.updateZ();
  13078. };
  13079. /**
  13080. * Get the index position of the given child in this Group. This should always match the childs z property.
  13081. *
  13082. * @method Phaser.Group#getIndex
  13083. * @param {*} child - The child to get the index for.
  13084. * @return {number} The index of the child or -1 if it's not a member of this Group.
  13085. */
  13086. Phaser.Group.prototype.getIndex = function (child) {
  13087. return this.children.indexOf(child);
  13088. };
  13089. /**
  13090. * Replaces a child of this Group with the given newChild. The newChild cannot be a member of this Group.
  13091. *
  13092. * @method Phaser.Group#replace
  13093. * @param {*} oldChild - The child in this Group that will be replaced.
  13094. * @param {*} newChild - The child to be inserted into this Group.
  13095. * @return {*} Returns the oldChild that was replaced within this Group.
  13096. */
  13097. Phaser.Group.prototype.replace = function (oldChild, newChild) {
  13098. var index = this.getIndex(oldChild);
  13099. if (index !== -1)
  13100. {
  13101. if (newChild.parent !== undefined)
  13102. {
  13103. newChild.events.onRemovedFromGroup.dispatch(newChild, this);
  13104. newChild.parent.removeChild(newChild);
  13105. if (newChild.parent instanceof Phaser.Group)
  13106. {
  13107. newChild.parent.updateZ();
  13108. }
  13109. }
  13110. var temp = oldChild;
  13111. this.remove(temp);
  13112. this.addAt(newChild, index);
  13113. return temp;
  13114. }
  13115. };
  13116. /**
  13117. * Sets the given property to the given value on the child. The operation controls the assignment of the value.
  13118. *
  13119. * @method Phaser.Group#setProperty
  13120. * @param {*} child - The child to set the property value on.
  13121. * @param {array} key - An array of strings that make up the property that will be set.
  13122. * @param {*} value - The value that will be set.
  13123. * @param {number} [operation=0] - Controls how the value is assigned. A value of 0 replaces the value with the new one. A value of 1 adds it, 2 subtracts it, 3 multiplies it and 4 divides it.
  13124. */
  13125. Phaser.Group.prototype.setProperty = function (child, key, value, operation) {
  13126. operation = operation || 0;
  13127. // As ugly as this approach looks, and although it's limited to a depth of only 4, it's extremely fast.
  13128. // Much faster than a for loop or object iteration. There are no checks, so if the key isn't valid then it'll fail
  13129. // but as you are likely to call this from inner loops that have to perform well, I'll take that trade off.
  13130. // 0 = Equals
  13131. // 1 = Add
  13132. // 2 = Subtract
  13133. // 3 = Multiply
  13134. // 4 = Divide
  13135. var len = key.length;
  13136. if (len == 1)
  13137. {
  13138. if (operation === 0) { child[key[0]] = value; }
  13139. else if (operation == 1) { child[key[0]] += value; }
  13140. else if (operation == 2) { child[key[0]] -= value; }
  13141. else if (operation == 3) { child[key[0]] *= value; }
  13142. else if (operation == 4) { child[key[0]] /= value; }
  13143. }
  13144. else if (len == 2)
  13145. {
  13146. if (operation === 0) { child[key[0]][key[1]] = value; }
  13147. else if (operation == 1) { child[key[0]][key[1]] += value; }
  13148. else if (operation == 2) { child[key[0]][key[1]] -= value; }
  13149. else if (operation == 3) { child[key[0]][key[1]] *= value; }
  13150. else if (operation == 4) { child[key[0]][key[1]] /= value; }
  13151. }
  13152. else if (len == 3)
  13153. {
  13154. if (operation === 0) { child[key[0]][key[1]][key[2]] = value; }
  13155. else if (operation == 1) { child[key[0]][key[1]][key[2]] += value; }
  13156. else if (operation == 2) { child[key[0]][key[1]][key[2]] -= value; }
  13157. else if (operation == 3) { child[key[0]][key[1]][key[2]] *= value; }
  13158. else if (operation == 4) { child[key[0]][key[1]][key[2]] /= value; }
  13159. }
  13160. else if (len == 4)
  13161. {
  13162. if (operation === 0) { child[key[0]][key[1]][key[2]][key[3]] = value; }
  13163. else if (operation == 1) { child[key[0]][key[1]][key[2]][key[3]] += value; }
  13164. else if (operation == 2) { child[key[0]][key[1]][key[2]][key[3]] -= value; }
  13165. else if (operation == 3) { child[key[0]][key[1]][key[2]][key[3]] *= value; }
  13166. else if (operation == 4) { child[key[0]][key[1]][key[2]][key[3]] /= value; }
  13167. }
  13168. };
  13169. /**
  13170. * This function allows you to quickly set a property on a single child of this Group to a new value.
  13171. * The operation parameter controls how the new value is assigned to the property, from simple replacement to addition and multiplication.
  13172. *
  13173. * @method Phaser.Group#set
  13174. * @param {Phaser.Sprite} child - The child to set the property on.
  13175. * @param {string} key - The property, as a string, to be set. For example: 'body.velocity.x'
  13176. * @param {*} value - The value that will be set.
  13177. * @param {boolean} [checkAlive=false] - If set then the child will only be updated if alive=true.
  13178. * @param {boolean} [checkVisible=false] - If set then the child will only be updated if visible=true.
  13179. * @param {number} [operation=0] - Controls how the value is assigned. A value of 0 replaces the value with the new one. A value of 1 adds it, 2 subtracts it, 3 multiplies it and 4 divides it.
  13180. */
  13181. Phaser.Group.prototype.set = function (child, key, value, checkAlive, checkVisible, operation) {
  13182. key = key.split('.');
  13183. if (typeof checkAlive === 'undefined') { checkAlive = false; }
  13184. if (typeof checkVisible === 'undefined') { checkVisible = false; }
  13185. if ((checkAlive === false || (checkAlive && child.alive)) && (checkVisible === false || (checkVisible && child.visible)))
  13186. {
  13187. this.setProperty(child, key, value, operation);
  13188. }
  13189. };
  13190. /**
  13191. * This function allows you to quickly set the same property across all children of this Group to a new value.
  13192. * This call doesn't descend down children, so if you have a Group inside of this Group, the property will be set on the Group but not its children.
  13193. * If you need that ability please see `Group.setAllChildren`.
  13194. *
  13195. * The operation parameter controls how the new value is assigned to the property, from simple replacement to addition and multiplication.
  13196. *
  13197. * @method Phaser.Group#setAll
  13198. * @param {string} key - The property, as a string, to be set. For example: 'body.velocity.x'
  13199. * @param {*} value - The value that will be set.
  13200. * @param {boolean} [checkAlive=false] - If set then only children with alive=true will be updated. This includes any Groups that are children.
  13201. * @param {boolean} [checkVisible=false] - If set then only children with visible=true will be updated. This includes any Groups that are children.
  13202. * @param {number} [operation=0] - Controls how the value is assigned. A value of 0 replaces the value with the new one. A value of 1 adds it, 2 subtracts it, 3 multiplies it and 4 divides it.
  13203. */
  13204. Phaser.Group.prototype.setAll = function (key, value, checkAlive, checkVisible, operation) {
  13205. key = key.split('.');
  13206. if (typeof checkAlive === 'undefined') { checkAlive = false; }
  13207. if (typeof checkVisible === 'undefined') { checkVisible = false; }
  13208. operation = operation || 0;
  13209. for (var i = 0, len = this.children.length; i < len; i++)
  13210. {
  13211. if ((!checkAlive || (checkAlive && this.children[i].alive)) && (!checkVisible || (checkVisible && this.children[i].visible)))
  13212. {
  13213. this.setProperty(this.children[i], key, value, operation);
  13214. }
  13215. }
  13216. };
  13217. /**
  13218. * This function allows you to quickly set the same property across all children of this Group, and any child Groups, to a new value.
  13219. *
  13220. * If this Group contains other Groups then the same property is set across their children as well, iterating down until it reaches the bottom.
  13221. * Unlike with Group.setAll the property is NOT set on child Groups itself.
  13222. *
  13223. * The operation parameter controls how the new value is assigned to the property, from simple replacement to addition and multiplication.
  13224. *
  13225. * @method Phaser.Group#setAllChildren
  13226. * @param {string} key - The property, as a string, to be set. For example: 'body.velocity.x'
  13227. * @param {*} value - The value that will be set.
  13228. * @param {boolean} [checkAlive=false] - If set then only children with alive=true will be updated. This includes any Groups that are children.
  13229. * @param {boolean} [checkVisible=false] - If set then only children with visible=true will be updated. This includes any Groups that are children.
  13230. * @param {number} [operation=0] - Controls how the value is assigned. A value of 0 replaces the value with the new one. A value of 1 adds it, 2 subtracts it, 3 multiplies it and 4 divides it.
  13231. */
  13232. Phaser.Group.prototype.setAllChildren = function (key, value, checkAlive, checkVisible, operation) {
  13233. if (typeof checkAlive === 'undefined') { checkAlive = false; }
  13234. if (typeof checkVisible === 'undefined') { checkVisible = false; }
  13235. operation = operation || 0;
  13236. for (var i = 0, len = this.children.length; i < len; i++)
  13237. {
  13238. if ((!checkAlive || (checkAlive && this.children[i].alive)) && (!checkVisible || (checkVisible && this.children[i].visible)))
  13239. {
  13240. if (this.children[i] instanceof Phaser.Group)
  13241. {
  13242. this.children[i].setAllChildren(key, value, checkAlive, checkVisible, operation);
  13243. }
  13244. else
  13245. {
  13246. this.setProperty(this.children[i], key.split('.'), value, operation);
  13247. }
  13248. }
  13249. }
  13250. };
  13251. /**
  13252. * Adds the amount to the given property on all children in this Group.
  13253. * Group.addAll('x', 10) will add 10 to the child.x value.
  13254. *
  13255. * @method Phaser.Group#addAll
  13256. * @param {string} property - The property to increment, for example 'body.velocity.x' or 'angle'.
  13257. * @param {number} amount - The amount to increment the property by. If child.x = 10 then addAll('x', 40) would make child.x = 50.
  13258. * @param {boolean} checkAlive - If true the property will only be changed if the child is alive.
  13259. * @param {boolean} checkVisible - If true the property will only be changed if the child is visible.
  13260. */
  13261. Phaser.Group.prototype.addAll = function (property, amount, checkAlive, checkVisible) {
  13262. this.setAll(property, amount, checkAlive, checkVisible, 1);
  13263. };
  13264. /**
  13265. * Subtracts the amount from the given property on all children in this Group.
  13266. * Group.subAll('x', 10) will minus 10 from the child.x value.
  13267. *
  13268. * @method Phaser.Group#subAll
  13269. * @param {string} property - The property to decrement, for example 'body.velocity.x' or 'angle'.
  13270. * @param {number} amount - The amount to subtract from the property. If child.x = 50 then subAll('x', 40) would make child.x = 10.
  13271. * @param {boolean} checkAlive - If true the property will only be changed if the child is alive.
  13272. * @param {boolean} checkVisible - If true the property will only be changed if the child is visible.
  13273. */
  13274. Phaser.Group.prototype.subAll = function (property, amount, checkAlive, checkVisible) {
  13275. this.setAll(property, amount, checkAlive, checkVisible, 2);
  13276. };
  13277. /**
  13278. * Multiplies the given property by the amount on all children in this Group.
  13279. * Group.multiplyAll('x', 2) will x2 the child.x value.
  13280. *
  13281. * @method Phaser.Group#multiplyAll
  13282. * @param {string} property - The property to multiply, for example 'body.velocity.x' or 'angle'.
  13283. * @param {number} amount - The amount to multiply the property by. If child.x = 10 then multiplyAll('x', 2) would make child.x = 20.
  13284. * @param {boolean} checkAlive - If true the property will only be changed if the child is alive.
  13285. * @param {boolean} checkVisible - If true the property will only be changed if the child is visible.
  13286. */
  13287. Phaser.Group.prototype.multiplyAll = function (property, amount, checkAlive, checkVisible) {
  13288. this.setAll(property, amount, checkAlive, checkVisible, 3);
  13289. };
  13290. /**
  13291. * Divides the given property by the amount on all children in this Group.
  13292. * Group.divideAll('x', 2) will half the child.x value.
  13293. *
  13294. * @method Phaser.Group#divideAll
  13295. * @param {string} property - The property to divide, for example 'body.velocity.x' or 'angle'.
  13296. * @param {number} amount - The amount to divide the property by. If child.x = 100 then divideAll('x', 2) would make child.x = 50.
  13297. * @param {boolean} checkAlive - If true the property will only be changed if the child is alive.
  13298. * @param {boolean} checkVisible - If true the property will only be changed if the child is visible.
  13299. */
  13300. Phaser.Group.prototype.divideAll = function (property, amount, checkAlive, checkVisible) {
  13301. this.setAll(property, amount, checkAlive, checkVisible, 4);
  13302. };
  13303. /**
  13304. * Calls a function on all of the children that have exists=true in this Group.
  13305. * After the existsValue parameter you can add as many parameters as you like, which will all be passed to the child callback.
  13306. *
  13307. * @method Phaser.Group#callAllExists
  13308. * @param {function} callback - The function that exists on the children that will be called.
  13309. * @param {boolean} existsValue - Only children with exists=existsValue will be called.
  13310. * @param {...*} parameter - Additional parameters that will be passed to the callback.
  13311. */
  13312. Phaser.Group.prototype.callAllExists = function (callback, existsValue) {
  13313. var args = Array.prototype.splice.call(arguments, 2);
  13314. for (var i = 0, len = this.children.length; i < len; i++)
  13315. {
  13316. if (this.children[i].exists === existsValue && this.children[i][callback])
  13317. {
  13318. this.children[i][callback].apply(this.children[i], args);
  13319. }
  13320. }
  13321. };
  13322. /**
  13323. * Returns a reference to a function that exists on a child of the Group based on the given callback array.
  13324. *
  13325. * @method Phaser.Group#callbackFromArray
  13326. * @param {object} child - The object to inspect.
  13327. * @param {array} callback - The array of function names.
  13328. * @param {number} length - The size of the array (pre-calculated in callAll).
  13329. * @protected
  13330. */
  13331. Phaser.Group.prototype.callbackFromArray = function (child, callback, length) {
  13332. // Kinda looks like a Christmas tree
  13333. if (length == 1)
  13334. {
  13335. if (child[callback[0]])
  13336. {
  13337. return child[callback[0]];
  13338. }
  13339. }
  13340. else if (length == 2)
  13341. {
  13342. if (child[callback[0]][callback[1]])
  13343. {
  13344. return child[callback[0]][callback[1]];
  13345. }
  13346. }
  13347. else if (length == 3)
  13348. {
  13349. if (child[callback[0]][callback[1]][callback[2]])
  13350. {
  13351. return child[callback[0]][callback[1]][callback[2]];
  13352. }
  13353. }
  13354. else if (length == 4)
  13355. {
  13356. if (child[callback[0]][callback[1]][callback[2]][callback[3]])
  13357. {
  13358. return child[callback[0]][callback[1]][callback[2]][callback[3]];
  13359. }
  13360. }
  13361. else
  13362. {
  13363. if (child[callback])
  13364. {
  13365. return child[callback];
  13366. }
  13367. }
  13368. return false;
  13369. };
  13370. /**
  13371. * Calls a function on all of the children regardless if they are dead or alive (see callAllExists if you need control over that)
  13372. * After the method parameter and context you can add as many extra parameters as you like, which will all be passed to the child.
  13373. *
  13374. * @method Phaser.Group#callAll
  13375. * @param {string} method - A string containing the name of the function that will be called. The function must exist on the child.
  13376. * @param {string} [context=null] - A string containing the context under which the method will be executed. Set to null to default to the child.
  13377. * @param {...*} parameter - Additional parameters that will be passed to the method.
  13378. */
  13379. Phaser.Group.prototype.callAll = function (method, context) {
  13380. if (typeof method === 'undefined')
  13381. {
  13382. return;
  13383. }
  13384. // Extract the method into an array
  13385. method = method.split('.');
  13386. var methodLength = method.length;
  13387. if (typeof context === 'undefined' || context === null || context === '')
  13388. {
  13389. context = null;
  13390. }
  13391. else
  13392. {
  13393. // Extract the context into an array
  13394. if (typeof context === 'string')
  13395. {
  13396. context = context.split('.');
  13397. var contextLength = context.length;
  13398. }
  13399. }
  13400. var args = Array.prototype.splice.call(arguments, 2);
  13401. var callback = null;
  13402. var callbackContext = null;
  13403. for (var i = 0, len = this.children.length; i < len; i++)
  13404. {
  13405. callback = this.callbackFromArray(this.children[i], method, methodLength);
  13406. if (context && callback)
  13407. {
  13408. callbackContext = this.callbackFromArray(this.children[i], context, contextLength);
  13409. if (callback)
  13410. {
  13411. callback.apply(callbackContext, args);
  13412. }
  13413. }
  13414. else if (callback)
  13415. {
  13416. callback.apply(this.children[i], args);
  13417. }
  13418. }
  13419. };
  13420. /**
  13421. * The core preUpdate - as called by World.
  13422. * @method Phaser.Group#preUpdate
  13423. * @protected
  13424. */
  13425. Phaser.Group.prototype.preUpdate = function () {
  13426. if (!this.exists || !this.parent.exists)
  13427. {
  13428. this.renderOrderID = -1;
  13429. return false;
  13430. }
  13431. var i = this.children.length;
  13432. while (i--)
  13433. {
  13434. this.children[i].preUpdate();
  13435. }
  13436. return true;
  13437. };
  13438. /**
  13439. * The core update - as called by World.
  13440. * @method Phaser.Group#update
  13441. * @protected
  13442. */
  13443. Phaser.Group.prototype.update = function () {
  13444. var i = this.children.length;
  13445. while (i--)
  13446. {
  13447. this.children[i].update();
  13448. }
  13449. };
  13450. /**
  13451. * The core postUpdate - as called by World.
  13452. * @method Phaser.Group#postUpdate
  13453. * @protected
  13454. */
  13455. Phaser.Group.prototype.postUpdate = function () {
  13456. // Fixed to Camera?
  13457. if (this._cache[7] === 1)
  13458. {
  13459. this.x = this.game.camera.view.x + this.cameraOffset.x;
  13460. this.y = this.game.camera.view.y + this.cameraOffset.y;
  13461. }
  13462. var i = this.children.length;
  13463. while (i--)
  13464. {
  13465. this.children[i].postUpdate();
  13466. }
  13467. };
  13468. /**
  13469. * Allows you to call your own function on each member of this Group. You must pass the callback and context in which it will run.
  13470. * After the checkExists parameter you can add as many parameters as you like, which will all be passed to the callback along with the child.
  13471. * For example: Group.forEach(awardBonusGold, this, true, 100, 500)
  13472. * Note: Currently this will skip any children which are Groups themselves.
  13473. *
  13474. * @method Phaser.Group#forEach
  13475. * @param {function} callback - The function that will be called. Each child of the Group will be passed to it as its first parameter.
  13476. * @param {Object} callbackContext - The context in which the function should be called (usually 'this').
  13477. * @param {boolean} [checkExists=false] - If set only children with exists=true will be passed to the callback, otherwise all children will be passed.
  13478. */
  13479. Phaser.Group.prototype.forEach = function (callback, callbackContext, checkExists) {
  13480. if (typeof checkExists === 'undefined') { checkExists = false; }
  13481. var args = Array.prototype.splice.call(arguments, 3);
  13482. args.unshift(null);
  13483. for (var i = 0, len = this.children.length; i < len; i++)
  13484. {
  13485. if (!checkExists || (checkExists && this.children[i].exists))
  13486. {
  13487. args[0] = this.children[i];
  13488. callback.apply(callbackContext, args);
  13489. }
  13490. }
  13491. };
  13492. /**
  13493. * Allows you to call your own function on each member of this Group where child.exists=true. You must pass the callback and context in which it will run.
  13494. * You can add as many parameters as you like, which will all be passed to the callback along with the child.
  13495. * For example: Group.forEachExists(causeDamage, this, 500)
  13496. *
  13497. * @method Phaser.Group#forEachExists
  13498. * @param {function} callback - The function that will be called. Each child of the Group will be passed to it as its first parameter.
  13499. * @param {Object} callbackContext - The context in which the function should be called (usually 'this').
  13500. */
  13501. Phaser.Group.prototype.forEachExists = function (callback, callbackContext) {
  13502. var args = Array.prototype.splice.call(arguments, 2);
  13503. args.unshift(null);
  13504. this.iterate('exists', true, Phaser.Group.RETURN_TOTAL, callback, callbackContext, args);
  13505. };
  13506. /**
  13507. * Allows you to call your own function on each alive member of this Group (where child.alive=true). You must pass the callback and context in which it will run.
  13508. * You can add as many parameters as you like, which will all be passed to the callback along with the child.
  13509. * For example: Group.forEachAlive(causeDamage, this, 500)
  13510. *
  13511. * @method Phaser.Group#forEachAlive
  13512. * @param {function} callback - The function that will be called. Each child of the Group will be passed to it as its first parameter.
  13513. * @param {Object} callbackContext - The context in which the function should be called (usually 'this').
  13514. */
  13515. Phaser.Group.prototype.forEachAlive = function (callback, callbackContext) {
  13516. var args = Array.prototype.splice.call(arguments, 2);
  13517. args.unshift(null);
  13518. this.iterate('alive', true, Phaser.Group.RETURN_TOTAL, callback, callbackContext, args);
  13519. };
  13520. /**
  13521. * Allows you to call your own function on each dead member of this Group (where alive=false). You must pass the callback and context in which it will run.
  13522. * You can add as many parameters as you like, which will all be passed to the callback along with the child.
  13523. * For example: Group.forEachDead(bringToLife, this)
  13524. *
  13525. * @method Phaser.Group#forEachDead
  13526. * @param {function} callback - The function that will be called. Each child of the Group will be passed to it as its first parameter.
  13527. * @param {Object} callbackContext - The context in which the function should be called (usually 'this').
  13528. */
  13529. Phaser.Group.prototype.forEachDead = function (callback, callbackContext) {
  13530. var args = Array.prototype.splice.call(arguments, 2);
  13531. args.unshift(null);
  13532. this.iterate('alive', false, Phaser.Group.RETURN_TOTAL, callback, callbackContext, args);
  13533. };
  13534. /**
  13535. * Call this function to sort the group according to a particular value and order.
  13536. * For example to depth sort Sprites for Zelda-style game you might call `group.sort('y', Phaser.Group.SORT_ASCENDING)` at the bottom of your `State.update()`.
  13537. *
  13538. * @method Phaser.Group#sort
  13539. * @param {string} [index='z'] - The `string` name of the property you want to sort on. Defaults to the objects z-depth value.
  13540. * @param {number} [order=Phaser.Group.SORT_ASCENDING] - The `Group` constant that defines the sort order. Possible values are Phaser.Group.SORT_ASCENDING and Phaser.Group.SORT_DESCENDING.
  13541. */
  13542. Phaser.Group.prototype.sort = function (index, order) {
  13543. if (this.children.length < 2)
  13544. {
  13545. // Nothing to swap
  13546. return;
  13547. }
  13548. if (typeof index === 'undefined') { index = 'z'; }
  13549. if (typeof order === 'undefined') { order = Phaser.Group.SORT_ASCENDING; }
  13550. this._sortProperty = index;
  13551. if (order === Phaser.Group.SORT_ASCENDING)
  13552. {
  13553. this.children.sort(this.ascendingSortHandler.bind(this));
  13554. }
  13555. else
  13556. {
  13557. this.children.sort(this.descendingSortHandler.bind(this));
  13558. }
  13559. this.updateZ();
  13560. };
  13561. /**
  13562. * This allows you to use your own sort handler function.
  13563. * It will be sent two parameters: the two children involved in the comparison (a and b). It should return -1 if a > b, 1 if a < b or 0 if a === b.
  13564. *
  13565. * @method Phaser.Group#customSort
  13566. * @param {function} sortHandler - Your sort handler function. It will be sent two parameters: the two children involved in the comparison. It must return -1, 1 or 0.
  13567. * @param {object} context - The scope in which the sortHandler is called.
  13568. */
  13569. Phaser.Group.prototype.customSort = function (sortHandler, context) {
  13570. if (this.children.length < 2)
  13571. {
  13572. // Nothing to swap
  13573. return;
  13574. }
  13575. this.children.sort(sortHandler.bind(context));
  13576. this.updateZ();
  13577. };
  13578. /**
  13579. * An internal helper function for the sort process.
  13580. *
  13581. * @method Phaser.Group#ascendingSortHandler
  13582. * @param {object} a - The first object being sorted.
  13583. * @param {object} b - The second object being sorted.
  13584. */
  13585. Phaser.Group.prototype.ascendingSortHandler = function (a, b) {
  13586. if (a[this._sortProperty] < b[this._sortProperty])
  13587. {
  13588. return -1;
  13589. }
  13590. else if (a[this._sortProperty] > b[this._sortProperty])
  13591. {
  13592. return 1;
  13593. }
  13594. else
  13595. {
  13596. if (a.z < b.z)
  13597. {
  13598. return -1;
  13599. }
  13600. else
  13601. {
  13602. return 1;
  13603. }
  13604. }
  13605. };
  13606. /**
  13607. * An internal helper function for the sort process.
  13608. *
  13609. * @method Phaser.Group#descendingSortHandler
  13610. * @param {object} a - The first object being sorted.
  13611. * @param {object} b - The second object being sorted.
  13612. */
  13613. Phaser.Group.prototype.descendingSortHandler = function (a, b) {
  13614. if (a[this._sortProperty] < b[this._sortProperty])
  13615. {
  13616. return 1;
  13617. }
  13618. else if (a[this._sortProperty] > b[this._sortProperty])
  13619. {
  13620. return -1;
  13621. }
  13622. else
  13623. {
  13624. return 0;
  13625. }
  13626. };
  13627. /**
  13628. * Iterates over the children of the Group. When a child has a property matching key that equals the given value, it is considered as a match.
  13629. * Matched children can be sent to the optional callback, or simply returned or counted.
  13630. * You can add as many callback parameters as you like, which will all be passed to the callback along with the child, after the callbackContext parameter.
  13631. *
  13632. * @method Phaser.Group#iterate
  13633. * @param {string} key - The child property to check, i.e. 'exists', 'alive', 'health'
  13634. * @param {any} value - If child.key === this value it will be considered a match. Note that a strict comparison is used.
  13635. * @param {number} returnType - How to return the data from this method. Either Phaser.Group.RETURN_NONE, Phaser.Group.RETURN_TOTAL or Phaser.Group.RETURN_CHILD.
  13636. * @param {function} [callback=null] - Optional function that will be called on each matching child. Each child of the Group will be passed to it as its first parameter.
  13637. * @param {Object} [callbackContext] - The context in which the function should be called (usually 'this').
  13638. * @return {any} Returns either a numeric total (if RETURN_TOTAL was specified) or the child object.
  13639. */
  13640. Phaser.Group.prototype.iterate = function (key, value, returnType, callback, callbackContext, args) {
  13641. if (returnType === Phaser.Group.RETURN_TOTAL && this.children.length === 0)
  13642. {
  13643. return 0;
  13644. }
  13645. if (typeof callback === 'undefined')
  13646. {
  13647. callback = false;
  13648. }
  13649. var total = 0;
  13650. for (var i = 0, len = this.children.length; i < len; i++)
  13651. {
  13652. if (this.children[i][key] === value)
  13653. {
  13654. total++;
  13655. if (callback)
  13656. {
  13657. args[0] = this.children[i];
  13658. callback.apply(callbackContext, args);
  13659. }
  13660. if (returnType === Phaser.Group.RETURN_CHILD)
  13661. {
  13662. return this.children[i];
  13663. }
  13664. }
  13665. }
  13666. if (returnType === Phaser.Group.RETURN_TOTAL)
  13667. {
  13668. return total;
  13669. }
  13670. else if (returnType === Phaser.Group.RETURN_CHILD)
  13671. {
  13672. return null;
  13673. }
  13674. };
  13675. /**
  13676. * Call this function to retrieve the first object with exists == (the given state) in the Group.
  13677. *
  13678. * @method Phaser.Group#getFirstExists
  13679. * @param {boolean} state - True or false.
  13680. * @return {Any} The first child, or null if none found.
  13681. */
  13682. Phaser.Group.prototype.getFirstExists = function (state) {
  13683. if (typeof state !== 'boolean')
  13684. {
  13685. state = true;
  13686. }
  13687. return this.iterate('exists', state, Phaser.Group.RETURN_CHILD);
  13688. };
  13689. /**
  13690. * Call this function to retrieve the first object with alive === true in the group.
  13691. * This is handy for checking if everything has been wiped out, or choosing a squad leader, etc.
  13692. *
  13693. * @method Phaser.Group#getFirstAlive
  13694. * @return {Any} The first alive child, or null if none found.
  13695. */
  13696. Phaser.Group.prototype.getFirstAlive = function () {
  13697. return this.iterate('alive', true, Phaser.Group.RETURN_CHILD);
  13698. };
  13699. /**
  13700. * Call this function to retrieve the first object with alive === false in the group.
  13701. * This is handy for checking if everything has been wiped out, or choosing a squad leader, etc.
  13702. *
  13703. * @method Phaser.Group#getFirstDead
  13704. * @return {Any} The first dead child, or null if none found.
  13705. */
  13706. Phaser.Group.prototype.getFirstDead = function () {
  13707. return this.iterate('alive', false, Phaser.Group.RETURN_CHILD);
  13708. };
  13709. /**
  13710. * Returns the child at the top of this Group. The top is the one being displayed (rendered) above every other child.
  13711. *
  13712. * @method Phaser.Group#getTop
  13713. * @return {Any} The child at the top of the Group.
  13714. */
  13715. Phaser.Group.prototype.getTop = function () {
  13716. if (this.children.length > 0)
  13717. {
  13718. return this.children[this.children.length - 1];
  13719. }
  13720. };
  13721. /**
  13722. * Returns the child at the bottom of this Group. The bottom is the one being displayed (rendered) below every other child.
  13723. *
  13724. * @method Phaser.Group#getBottom
  13725. * @return {Any} The child at the bottom of the Group.
  13726. */
  13727. Phaser.Group.prototype.getBottom = function () {
  13728. if (this.children.length > 0)
  13729. {
  13730. return this.children[0];
  13731. }
  13732. };
  13733. /**
  13734. * Call this function to find out how many members of the group are alive.
  13735. *
  13736. * @method Phaser.Group#countLiving
  13737. * @return {number} The number of children flagged as alive.
  13738. */
  13739. Phaser.Group.prototype.countLiving = function () {
  13740. return this.iterate('alive', true, Phaser.Group.RETURN_TOTAL);
  13741. };
  13742. /**
  13743. * Call this function to find out how many members of the group are dead.
  13744. *
  13745. * @method Phaser.Group#countDead
  13746. * @return {number} The number of children flagged as dead.
  13747. */
  13748. Phaser.Group.prototype.countDead = function () {
  13749. return this.iterate('alive', false, Phaser.Group.RETURN_TOTAL);
  13750. };
  13751. /**
  13752. * Returns a member at random from the group.
  13753. *
  13754. * @method Phaser.Group#getRandom
  13755. * @param {number} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
  13756. * @param {number} length - Optional restriction on the number of values you want to randomly select from.
  13757. * @return {Any} A random child of this Group.
  13758. */
  13759. Phaser.Group.prototype.getRandom = function (startIndex, length) {
  13760. if (this.children.length === 0)
  13761. {
  13762. return null;
  13763. }
  13764. startIndex = startIndex || 0;
  13765. length = length || this.children.length;
  13766. return this.game.math.getRandom(this.children, startIndex, length);
  13767. };
  13768. /**
  13769. * Removes the given child from this Group and sets its group property to null.
  13770. *
  13771. * @method Phaser.Group#remove
  13772. * @param {Any} child - The child to remove.
  13773. * @param {boolean} [destroy=false] - You can optionally call destroy on the child that was removed.
  13774. * @return {boolean} true if the child was removed from this Group, otherwise false.
  13775. */
  13776. Phaser.Group.prototype.remove = function (child, destroy) {
  13777. if (typeof destroy === 'undefined') { destroy = false; }
  13778. if (this.children.length === 0)
  13779. {
  13780. return false;
  13781. }
  13782. if (child.events)
  13783. {
  13784. child.events.onRemovedFromGroup.dispatch(child, this);
  13785. }
  13786. this.removeChild(child);
  13787. this.updateZ();
  13788. if (this.cursor === child)
  13789. {
  13790. this.next();
  13791. }
  13792. if (destroy)
  13793. {
  13794. child.destroy();
  13795. }
  13796. return true;
  13797. };
  13798. /**
  13799. * Removes all children from this Group, setting all group properties to null.
  13800. * The Group container remains on the display list.
  13801. *
  13802. * @method Phaser.Group#removeAll
  13803. * @param {boolean} [destroy=false] - You can optionally call destroy on the child that was removed.
  13804. */
  13805. Phaser.Group.prototype.removeAll = function (destroy) {
  13806. if (typeof destroy === 'undefined') { destroy = false; }
  13807. if (this.children.length === 0)
  13808. {
  13809. return;
  13810. }
  13811. do
  13812. {
  13813. if (this.children[0].events)
  13814. {
  13815. this.children[0].events.onRemovedFromGroup.dispatch(this.children[0], this);
  13816. }
  13817. this.removeChild(this.children[0]);
  13818. if (destroy)
  13819. {
  13820. this.children[0].destroy();
  13821. }
  13822. }
  13823. while (this.children.length > 0);
  13824. this.cursor = null;
  13825. };
  13826. /**
  13827. * Removes all children from this Group whos index falls beteen the given startIndex and endIndex values.
  13828. *
  13829. * @method Phaser.Group#removeBetween
  13830. * @param {number} startIndex - The index to start removing children from.
  13831. * @param {number} [endIndex] - The index to stop removing children at. Must be higher than startIndex. If undefined this method will remove all children between startIndex and the end of the Group.
  13832. * @param {boolean} [destroy=false] - You can optionally call destroy on the child that was removed.
  13833. */
  13834. Phaser.Group.prototype.removeBetween = function (startIndex, endIndex, destroy) {
  13835. if (typeof endIndex === 'undefined') { endIndex = this.children.length; }
  13836. if (typeof destroy === 'undefined') { destroy = false; }
  13837. if (this.children.length === 0)
  13838. {
  13839. return;
  13840. }
  13841. if (startIndex > endIndex || startIndex < 0 || endIndex > this.children.length)
  13842. {
  13843. return false;
  13844. }
  13845. var i = endIndex;
  13846. while (i >= startIndex)
  13847. {
  13848. if (this.children[i].events)
  13849. {
  13850. this.children[i].events.onRemovedFromGroup.dispatch(this.children[i], this);
  13851. }
  13852. this.removeChild(this.children[i]);
  13853. if (destroy)
  13854. {
  13855. this.children[i].destroy();
  13856. }
  13857. if (this.cursor === this.children[i])
  13858. {
  13859. this.cursor = null;
  13860. }
  13861. i--;
  13862. }
  13863. this.updateZ();
  13864. };
  13865. /**
  13866. * Destroys this Group. Removes all children, then removes the container from the display list and nulls references.
  13867. *
  13868. * @method Phaser.Group#destroy
  13869. * @param {boolean} [destroyChildren=true] - Should every child of this Group have its destroy method called?
  13870. * @param {boolean} [soft=false] - A 'soft destroy' (set to true) doesn't remove this Group from its parent or null the game reference. Set to false and it does.
  13871. */
  13872. Phaser.Group.prototype.destroy = function (destroyChildren, soft) {
  13873. if (this.game === null) { return; }
  13874. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  13875. if (typeof soft === 'undefined') { soft = false; }
  13876. if (destroyChildren)
  13877. {
  13878. if (this.children.length > 0)
  13879. {
  13880. do
  13881. {
  13882. if (this.children[0].parent)
  13883. {
  13884. this.children[0].destroy(destroyChildren);
  13885. }
  13886. }
  13887. while (this.children.length > 0);
  13888. }
  13889. }
  13890. else
  13891. {
  13892. this.removeAll();
  13893. }
  13894. this.cursor = null;
  13895. if (!soft)
  13896. {
  13897. this.parent.removeChild(this);
  13898. this.game = null;
  13899. this.exists = false;
  13900. }
  13901. };
  13902. /**
  13903. * @name Phaser.Group#total
  13904. * @property {number} total - The total number of children in this Group who have a state of exists = true.
  13905. * @readonly
  13906. */
  13907. Object.defineProperty(Phaser.Group.prototype, "total", {
  13908. get: function () {
  13909. return this.iterate('exists', true, Phaser.Group.RETURN_TOTAL);
  13910. }
  13911. });
  13912. /**
  13913. * @name Phaser.Group#length
  13914. * @property {number} length - The total number of children in this Group, regardless of their exists/alive status.
  13915. * @readonly
  13916. */
  13917. Object.defineProperty(Phaser.Group.prototype, "length", {
  13918. get: function () {
  13919. return this.children.length;
  13920. }
  13921. });
  13922. /**
  13923. * The angle of rotation of the Group container. This will adjust the Group container itself by modifying its rotation.
  13924. * This will have no impact on the rotation value of its children, but it will update their worldTransform and on-screen position.
  13925. * @name Phaser.Group#angle
  13926. * @property {number} angle - The angle of rotation given in degrees, where 0 degrees = to the right.
  13927. */
  13928. Object.defineProperty(Phaser.Group.prototype, "angle", {
  13929. get: function() {
  13930. return Phaser.Math.radToDeg(this.rotation);
  13931. },
  13932. set: function(value) {
  13933. this.rotation = Phaser.Math.degToRad(value);
  13934. }
  13935. });
  13936. /**
  13937. * A Group that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in Group.cameraOffset.
  13938. * Note that the cameraOffset values are in addition to any parent in the display list.
  13939. * So if this Group was in a Group that has x: 200, then this will be added to the cameraOffset.x
  13940. *
  13941. * @name Phaser.Group#fixedToCamera
  13942. * @property {boolean} fixedToCamera - Set to true to fix this Group to the Camera at its current world coordinates.
  13943. */
  13944. Object.defineProperty(Phaser.Group.prototype, "fixedToCamera", {
  13945. get: function () {
  13946. return !!this._cache[7];
  13947. },
  13948. set: function (value) {
  13949. if (value)
  13950. {
  13951. this._cache[7] = 1;
  13952. this.cameraOffset.set(this.x, this.y);
  13953. }
  13954. else
  13955. {
  13956. this._cache[7] = 0;
  13957. }
  13958. }
  13959. });
  13960. // Documentation stubs
  13961. /**
  13962. * The x coordinate of the Group container. You can adjust the Group container itself by modifying its coordinates.
  13963. * This will have no impact on the x/y coordinates of its children, but it will update their worldTransform and on-screen position.
  13964. * @name Phaser.Group#x
  13965. * @property {number} x - The x coordinate of the Group container.
  13966. */
  13967. /**
  13968. * The y coordinate of the Group container. You can adjust the Group container itself by modifying its coordinates.
  13969. * This will have no impact on the x/y coordinates of its children, but it will update their worldTransform and on-screen position.
  13970. * @name Phaser.Group#y
  13971. * @property {number} y - The y coordinate of the Group container.
  13972. */
  13973. /**
  13974. * The angle of rotation of the Group container. This will adjust the Group container itself by modifying its rotation.
  13975. * This will have no impact on the rotation value of its children, but it will update their worldTransform and on-screen position.
  13976. * @name Phaser.Group#rotation
  13977. * @property {number} rotation - The angle of rotation given in radians.
  13978. */
  13979. /**
  13980. * @name Phaser.Group#visible
  13981. * @property {boolean} visible - The visible state of the Group. Non-visible Groups and all of their children are not rendered.
  13982. */
  13983. /**
  13984. * @name Phaser.Group#alpha
  13985. * @property {number} alpha - The alpha value of the Group container.
  13986. */
  13987. /**
  13988. * @author Richard Davey <rich@photonstorm.com>
  13989. * @copyright 2014 Photon Storm Ltd.
  13990. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  13991. */
  13992. /**
  13993. * "This world is but a canvas to our imagination." - Henry David Thoreau
  13994. *
  13995. * A game has only one world. The world is an abstract place in which all game objects live. It is not bound
  13996. * by stage limits and can be any size. You look into the world via cameras. All game objects live within
  13997. * the world at world-based coordinates. By default a world is created the same size as your Stage.
  13998. *
  13999. * @class Phaser.World
  14000. * @extends Phaser.Group
  14001. * @constructor
  14002. * @param {Phaser.Game} game - Reference to the current game instance.
  14003. */
  14004. Phaser.World = function (game) {
  14005. Phaser.Group.call(this, game, null, '__world', false);
  14006. /**
  14007. * The World has no fixed size, but it does have a bounds outside of which objects are no longer considered as being "in world" and you should use this to clean-up the display list and purge dead objects.
  14008. * By default we set the Bounds to be from 0,0 to Game.width,Game.height. I.e. it will match the size given to the game constructor with 0,0 representing the top-left of the display.
  14009. * However 0,0 is actually the center of the world, and if you rotate or scale the world all of that will happen from 0,0.
  14010. * So if you want to make a game in which the world itself will rotate you should adjust the bounds so that 0,0 is the center point, i.e. set them to -1000,-1000,2000,2000 for a 2000x2000 sized world centered around 0,0.
  14011. * @property {Phaser.Rectangle} bounds - Bound of this world that objects can not escape from.
  14012. */
  14013. this.bounds = new Phaser.Rectangle(0, 0, game.width, game.height);
  14014. /**
  14015. * @property {Phaser.Camera} camera - Camera instance.
  14016. */
  14017. this.camera = null;
  14018. };
  14019. Phaser.World.prototype = Object.create(Phaser.Group.prototype);
  14020. Phaser.World.prototype.constructor = Phaser.World;
  14021. /**
  14022. * Initialises the game world.
  14023. *
  14024. * @method Phaser.World#boot
  14025. * @protected
  14026. */
  14027. Phaser.World.prototype.boot = function () {
  14028. this.camera = new Phaser.Camera(this.game, 0, 0, 0, this.game.width, this.game.height);
  14029. this.camera.displayObject = this;
  14030. this.camera.scale = this.scale;
  14031. this.game.camera = this.camera;
  14032. this.game.stage.addChild(this);
  14033. };
  14034. /**
  14035. * Updates the size of this world. Note that this doesn't modify the world x/y coordinates, just the width and height.
  14036. *
  14037. * @method Phaser.World#setBounds
  14038. * @param {number} x - Top left most corner of the world.
  14039. * @param {number} y - Top left most corner of the world.
  14040. * @param {number} width - New width of the world. Can never be smaller than the Game.width.
  14041. * @param {number} height - New height of the world. Can never be smaller than the Game.height.
  14042. */
  14043. Phaser.World.prototype.setBounds = function (x, y, width, height) {
  14044. if (width < this.game.width)
  14045. {
  14046. width = this.game.width;
  14047. }
  14048. if (height < this.game.height)
  14049. {
  14050. height = this.game.height;
  14051. }
  14052. this.bounds.setTo(x, y, width, height);
  14053. if (this.camera.bounds)
  14054. {
  14055. // The Camera can never be smaller than the game size
  14056. this.camera.bounds.setTo(x, y, width, height);
  14057. }
  14058. this.game.physics.setBoundsToWorld();
  14059. };
  14060. /**
  14061. * Destroyer of worlds.
  14062. *
  14063. * @method Phaser.World#shutdown
  14064. */
  14065. Phaser.World.prototype.shutdown = function () {
  14066. // World is a Group, so run a soft destruction on this and all children.
  14067. this.destroy(true, true);
  14068. };
  14069. /**
  14070. * @name Phaser.World#width
  14071. * @property {number} width - Gets or sets the current width of the game world.
  14072. */
  14073. Object.defineProperty(Phaser.World.prototype, "width", {
  14074. get: function () {
  14075. return this.bounds.width;
  14076. },
  14077. set: function (value) {
  14078. this.bounds.width = value;
  14079. }
  14080. });
  14081. /**
  14082. * @name Phaser.World#height
  14083. * @property {number} height - Gets or sets the current height of the game world.
  14084. */
  14085. Object.defineProperty(Phaser.World.prototype, "height", {
  14086. get: function () {
  14087. return this.bounds.height;
  14088. },
  14089. set: function (value) {
  14090. this.bounds.height = value;
  14091. }
  14092. });
  14093. /**
  14094. * @name Phaser.World#centerX
  14095. * @property {number} centerX - Gets the X position corresponding to the center point of the world.
  14096. * @readonly
  14097. */
  14098. Object.defineProperty(Phaser.World.prototype, "centerX", {
  14099. get: function () {
  14100. return this.bounds.halfWidth;
  14101. }
  14102. });
  14103. /**
  14104. * @name Phaser.World#centerY
  14105. * @property {number} centerY - Gets the Y position corresponding to the center point of the world.
  14106. * @readonly
  14107. */
  14108. Object.defineProperty(Phaser.World.prototype, "centerY", {
  14109. get: function () {
  14110. return this.bounds.halfHeight;
  14111. }
  14112. });
  14113. /**
  14114. * @name Phaser.World#randomX
  14115. * @property {number} randomX - Gets a random integer which is lesser than or equal to the current width of the game world.
  14116. * @readonly
  14117. */
  14118. Object.defineProperty(Phaser.World.prototype, "randomX", {
  14119. get: function () {
  14120. if (this.bounds.x < 0)
  14121. {
  14122. return this.game.rnd.integerInRange(this.bounds.x, (this.bounds.width - Math.abs(this.bounds.x)));
  14123. }
  14124. else
  14125. {
  14126. return this.game.rnd.integerInRange(this.bounds.x, this.bounds.width);
  14127. }
  14128. }
  14129. });
  14130. /**
  14131. * @name Phaser.World#randomY
  14132. * @property {number} randomY - Gets a random integer which is lesser than or equal to the current height of the game world.
  14133. * @readonly
  14134. */
  14135. Object.defineProperty(Phaser.World.prototype, "randomY", {
  14136. get: function () {
  14137. if (this.bounds.y < 0)
  14138. {
  14139. return this.game.rnd.integerInRange(this.bounds.y, (this.bounds.height - Math.abs(this.bounds.y)));
  14140. }
  14141. else
  14142. {
  14143. return this.game.rnd.integerInRange(this.bounds.y, this.bounds.height);
  14144. }
  14145. }
  14146. });
  14147. /**
  14148. * @author Richard Davey <rich@photonstorm.com>
  14149. * @copyright 2014 Photon Storm Ltd.
  14150. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  14151. */
  14152. /**
  14153. * The ScaleManager object is responsible for helping you manage the scaling, resizing and alignment of your game within the browser.
  14154. *
  14155. * @class Phaser.ScaleManager
  14156. * @constructor
  14157. * @param {Phaser.Game} game - A reference to the currently running game.
  14158. * @param {number} width - The native width of the game.
  14159. * @param {number} height - The native height of the game.
  14160. */
  14161. Phaser.ScaleManager = function (game, width, height) {
  14162. /**
  14163. * @property {Phaser.Game} game - A reference to the currently running game.
  14164. */
  14165. this.game = game;
  14166. /**
  14167. * @property {number} width - Width of the stage after calculation.
  14168. */
  14169. this.width = width;
  14170. /**
  14171. * @property {number} height - Height of the stage after calculation.
  14172. */
  14173. this.height = height;
  14174. /**
  14175. * @property {number} minWidth - Minimum width the canvas should be scaled to (in pixels).
  14176. */
  14177. this.minWidth = null;
  14178. /**
  14179. * @property {number} maxWidth - Maximum width the canvas should be scaled to (in pixels). If null it will scale to whatever width the browser can handle.
  14180. */
  14181. this.maxWidth = null;
  14182. /**
  14183. * @property {number} minHeight - Minimum height the canvas should be scaled to (in pixels).
  14184. */
  14185. this.minHeight = null;
  14186. /**
  14187. * @property {number} maxHeight - Maximum height the canvas should be scaled to (in pixels). If null it will scale to whatever height the browser can handle.
  14188. */
  14189. this.maxHeight = null;
  14190. /**
  14191. * @property {boolean} forceLandscape - If the game should be forced to use Landscape mode, this is set to true by Game.Stage
  14192. * @default
  14193. */
  14194. this.forceLandscape = false;
  14195. /**
  14196. * @property {boolean} forcePortrait - If the game should be forced to use Portrait mode, this is set to true by Game.Stage
  14197. * @default
  14198. */
  14199. this.forcePortrait = false;
  14200. /**
  14201. * @property {boolean} incorrectOrientation - If the game should be forced to use a specific orientation and the device currently isn't in that orientation this is set to true.
  14202. * @default
  14203. */
  14204. this.incorrectOrientation = false;
  14205. /**
  14206. * @property {boolean} pageAlignHorizontally - If you wish to align your game in the middle of the page then you can set this value to true.
  14207. * It will place a re-calculated margin-left pixel value onto the canvas element which is updated on orientation/resizing.
  14208. * It doesn't care about any other DOM element that may be on the page, it literally just sets the margin.
  14209. * @default
  14210. */
  14211. this.pageAlignHorizontally = false;
  14212. /**
  14213. * @property {boolean} pageAlignVertically - If you wish to align your game in the middle of the page then you can set this value to true.
  14214. * It will place a re-calculated margin-left pixel value onto the canvas element which is updated on orientation/resizing.
  14215. * It doesn't care about any other DOM element that may be on the page, it literally just sets the margin.
  14216. * @default
  14217. */
  14218. this.pageAlignVertically = false;
  14219. /**
  14220. * @property {number} maxIterations - The maximum number of times it will try to resize the canvas to fill the browser.
  14221. * @default
  14222. */
  14223. this.maxIterations = 5;
  14224. /**
  14225. * @property {PIXI.Sprite} orientationSprite - The Sprite that is optionally displayed if the browser enters an unsupported orientation.
  14226. */
  14227. this.orientationSprite = null;
  14228. /**
  14229. * @property {Phaser.Signal} enterLandscape - The event that is dispatched when the browser enters landscape orientation.
  14230. */
  14231. this.enterLandscape = new Phaser.Signal();
  14232. /**
  14233. * @property {Phaser.Signal} enterPortrait - The event that is dispatched when the browser enters horizontal orientation.
  14234. */
  14235. this.enterPortrait = new Phaser.Signal();
  14236. /**
  14237. * @property {Phaser.Signal} enterIncorrectOrientation - The event that is dispatched when the browser enters an incorrect orientation, as defined by forceOrientation.
  14238. */
  14239. this.enterIncorrectOrientation = new Phaser.Signal();
  14240. /**
  14241. * @property {Phaser.Signal} leaveIncorrectOrientation - The event that is dispatched when the browser leaves an incorrect orientation, as defined by forceOrientation.
  14242. */
  14243. this.leaveIncorrectOrientation = new Phaser.Signal();
  14244. /**
  14245. * @property {Phaser.Signal} hasResized - The event that is dispatched when the game scale changes.
  14246. */
  14247. this.hasResized = new Phaser.Signal();
  14248. /**
  14249. * This is the DOM element that will have the Full Screen mode called on it. It defaults to the game canvas, but can be retargetted to any valid DOM element.
  14250. * If you adjust this property it's up to you to see it has the correct CSS applied, and that you have contained the game canvas correctly.
  14251. * Note that if you use a scale property of EXACT_FIT then fullScreenTarget will have its width and height style set to 100%.
  14252. * @property {any} fullScreenTarget
  14253. */
  14254. this.fullScreenTarget = this.game.canvas;
  14255. /**
  14256. * @property {Phaser.Signal} enterFullScreen - The event that is dispatched when the browser enters full screen mode (if it supports the FullScreen API).
  14257. */
  14258. this.enterFullScreen = new Phaser.Signal();
  14259. /**
  14260. * @property {Phaser.Signal} leaveFullScreen - The event that is dispatched when the browser leaves full screen mode (if it supports the FullScreen API).
  14261. */
  14262. this.leaveFullScreen = new Phaser.Signal();
  14263. /**
  14264. * @property {number} orientation - The orientation value of the game (as defined by window.orientation if set). 90 = landscape. 0 = portrait.
  14265. */
  14266. this.orientation = 0;
  14267. if (window['orientation'])
  14268. {
  14269. this.orientation = window['orientation'];
  14270. }
  14271. else
  14272. {
  14273. if (window.outerWidth > window.outerHeight)
  14274. {
  14275. this.orientation = 90;
  14276. }
  14277. }
  14278. /**
  14279. * @property {Phaser.Point} scaleFactor - The scale factor based on the game dimensions vs. the scaled dimensions.
  14280. * @readonly
  14281. */
  14282. this.scaleFactor = new Phaser.Point(1, 1);
  14283. /**
  14284. * @property {Phaser.Point} scaleFactorInversed - The inversed scale factor. The displayed dimensions divided by the game dimensions.
  14285. * @readonly
  14286. */
  14287. this.scaleFactorInversed = new Phaser.Point(1, 1);
  14288. /**
  14289. * @property {Phaser.Point} margin - If the game canvas is seto to align by adjusting the margin, the margin calculation values are stored in this Point.
  14290. * @readonly
  14291. */
  14292. this.margin = new Phaser.Point(0, 0);
  14293. /**
  14294. * @property {number} aspectRatio - The aspect ratio of the scaled game.
  14295. * @readonly
  14296. */
  14297. this.aspectRatio = 0;
  14298. /**
  14299. * @property {number} sourceAspectRatio - The aspect ratio (width / height) of the original game dimensions.
  14300. * @readonly
  14301. */
  14302. this.sourceAspectRatio = width / height;
  14303. /**
  14304. * @property {any} event- The native browser events from full screen API changes.
  14305. */
  14306. this.event = null;
  14307. /**
  14308. * @property {number} scaleMode - The current scaleMode.
  14309. */
  14310. this.scaleMode = Phaser.ScaleManager.NO_SCALE;
  14311. /*
  14312. * @property {number} fullScreenScaleMode - Scale mode to be used in fullScreen
  14313. */
  14314. this.fullScreenScaleMode = Phaser.ScaleManager.NO_SCALE;
  14315. /**
  14316. * @property {number} _startHeight - Internal cache var. Stage height when starting the game.
  14317. * @private
  14318. */
  14319. this._startHeight = 0;
  14320. /**
  14321. * @property {number} _width - Cached stage width for full screen mode.
  14322. * @private
  14323. */
  14324. this._width = 0;
  14325. /**
  14326. * @property {number} _height - Cached stage height for full screen mode.
  14327. * @private
  14328. */
  14329. this._height = 0;
  14330. var _this = this;
  14331. window.addEventListener('orientationchange', function (event) {
  14332. return _this.checkOrientation(event);
  14333. }, false);
  14334. window.addEventListener('resize', function (event) {
  14335. return _this.checkResize(event);
  14336. }, false);
  14337. document.addEventListener('webkitfullscreenchange', function (event) {
  14338. return _this.fullScreenChange(event);
  14339. }, false);
  14340. document.addEventListener('mozfullscreenchange', function (event) {
  14341. return _this.fullScreenChange(event);
  14342. }, false);
  14343. document.addEventListener('fullscreenchange', function (event) {
  14344. return _this.fullScreenChange(event);
  14345. }, false);
  14346. };
  14347. /**
  14348. * @constant
  14349. * @type {number}
  14350. */
  14351. Phaser.ScaleManager.EXACT_FIT = 0;
  14352. /**
  14353. * @constant
  14354. * @type {number}
  14355. */
  14356. Phaser.ScaleManager.NO_SCALE = 1;
  14357. /**
  14358. * @constant
  14359. * @type {number}
  14360. */
  14361. Phaser.ScaleManager.SHOW_ALL = 2;
  14362. Phaser.ScaleManager.prototype = {
  14363. /**
  14364. * Tries to enter the browser into full screen mode.
  14365. * Please note that this needs to be supported by the web browser and isn't the same thing as setting your game to fill the browser.
  14366. * @method Phaser.ScaleManager#startFullScreen
  14367. * @param {boolean} antialias - You can toggle the anti-alias feature of the canvas before jumping in to full screen (false = retain pixel art, true = smooth art)
  14368. */
  14369. startFullScreen: function (antialias) {
  14370. if (this.isFullScreen || !this.game.device.fullscreen)
  14371. {
  14372. return;
  14373. }
  14374. if (typeof antialias !== 'undefined' && this.game.renderType === Phaser.CANVAS)
  14375. {
  14376. this.game.stage.smoothed = antialias;
  14377. }
  14378. this._width = this.width;
  14379. this._height = this.height;
  14380. if (this.game.device.fullscreenKeyboard)
  14381. {
  14382. this.fullScreenTarget[this.game.device.requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);
  14383. }
  14384. else
  14385. {
  14386. this.fullScreenTarget[this.game.device.requestFullscreen]();
  14387. }
  14388. },
  14389. /**
  14390. * Stops full screen mode if the browser is in it.
  14391. * @method Phaser.ScaleManager#stopFullScreen
  14392. */
  14393. stopFullScreen: function () {
  14394. this.fullScreenTarget[this.game.device.cancelFullscreen]();
  14395. },
  14396. /**
  14397. * Called automatically when the browser enters of leaves full screen mode.
  14398. * @method Phaser.ScaleManager#fullScreenChange
  14399. * @param {Event} event - The fullscreenchange event
  14400. * @protected
  14401. */
  14402. fullScreenChange: function (event) {
  14403. this.event = event;
  14404. if (this.isFullScreen)
  14405. {
  14406. if (this.fullScreenScaleMode === Phaser.ScaleManager.EXACT_FIT)
  14407. {
  14408. this.fullScreenTarget.style['width'] = '100%';
  14409. this.fullScreenTarget.style['height'] = '100%';
  14410. this.width = window.outerWidth;
  14411. this.height = window.outerHeight;
  14412. this.game.input.scale.setTo(this.game.width / this.width, this.game.height / this.height);
  14413. this.aspectRatio = this.width / this.height;
  14414. this.scaleFactor.x = this.game.width / this.width;
  14415. this.scaleFactor.y = this.game.height / this.height;
  14416. this.checkResize();
  14417. }
  14418. else if (this.fullScreenScaleMode === Phaser.ScaleManager.SHOW_ALL)
  14419. {
  14420. this.setShowAll();
  14421. this.refresh();
  14422. }
  14423. this.enterFullScreen.dispatch(this.width, this.height);
  14424. }
  14425. else
  14426. {
  14427. this.fullScreenTarget.style['width'] = this.game.width + 'px';
  14428. this.fullScreenTarget.style['height'] = this.game.height + 'px';
  14429. this.width = this._width;
  14430. this.height = this._height;
  14431. this.game.input.scale.setTo(this.game.width / this.width, this.game.height / this.height);
  14432. this.aspectRatio = this.width / this.height;
  14433. this.scaleFactor.x = this.game.width / this.width;
  14434. this.scaleFactor.y = this.game.height / this.height;
  14435. this.leaveFullScreen.dispatch(this.width, this.height);
  14436. }
  14437. },
  14438. /**
  14439. * If you need your game to run in only one orientation you can force that to happen.
  14440. * The optional orientationImage is displayed when the game is in the incorrect orientation.
  14441. * @method Phaser.ScaleManager#forceOrientation
  14442. * @param {boolean} forceLandscape - true if the game should run in landscape mode only.
  14443. * @param {boolean} [forcePortrait=false] - true if the game should run in portrait mode only.
  14444. * @param {string} [orientationImage=''] - The string of an image in the Phaser.Cache to display when this game is in the incorrect orientation.
  14445. */
  14446. forceOrientation: function (forceLandscape, forcePortrait, orientationImage) {
  14447. if (typeof forcePortrait === 'undefined') { forcePortrait = false; }
  14448. this.forceLandscape = forceLandscape;
  14449. this.forcePortrait = forcePortrait;
  14450. if (typeof orientationImage !== 'undefined')
  14451. {
  14452. if (orientationImage == null || this.game.cache.checkImageKey(orientationImage) === false)
  14453. {
  14454. orientationImage = '__default';
  14455. }
  14456. this.orientationSprite = new Phaser.Image(this.game, this.game.width / 2, this.game.height / 2, PIXI.TextureCache[orientationImage]);
  14457. this.orientationSprite.anchor.set(0.5);
  14458. this.checkOrientationState();
  14459. if (this.incorrectOrientation)
  14460. {
  14461. this.orientationSprite.visible = true;
  14462. this.game.world.visible = false;
  14463. }
  14464. else
  14465. {
  14466. this.orientationSprite.visible = false;
  14467. this.game.world.visible = true;
  14468. }
  14469. this.game.stage.addChild(this.orientationSprite);
  14470. }
  14471. },
  14472. /**
  14473. * Checks if the browser is in the correct orientation for your game (if forceLandscape or forcePortrait have been set)
  14474. * @method Phaser.ScaleManager#checkOrientationState
  14475. */
  14476. checkOrientationState: function () {
  14477. // They are in the wrong orientation
  14478. if (this.incorrectOrientation)
  14479. {
  14480. if ((this.forceLandscape && window.innerWidth > window.innerHeight) || (this.forcePortrait && window.innerHeight > window.innerWidth))
  14481. {
  14482. // Back to normal
  14483. this.incorrectOrientation = false;
  14484. this.leaveIncorrectOrientation.dispatch();
  14485. if (this.orientationSprite)
  14486. {
  14487. this.orientationSprite.visible = false;
  14488. this.game.world.visible = true;
  14489. }
  14490. if (this.scaleMode !== Phaser.ScaleManager.NO_SCALE)
  14491. {
  14492. this.refresh();
  14493. }
  14494. }
  14495. }
  14496. else
  14497. {
  14498. if ((this.forceLandscape && window.innerWidth < window.innerHeight) || (this.forcePortrait && window.innerHeight < window.innerWidth))
  14499. {
  14500. // Show orientation screen
  14501. this.incorrectOrientation = true;
  14502. this.enterIncorrectOrientation.dispatch();
  14503. if (this.orientationSprite && this.orientationSprite.visible === false)
  14504. {
  14505. this.orientationSprite.visible = true;
  14506. this.game.world.visible = false;
  14507. }
  14508. if (this.scaleMode !== Phaser.ScaleManager.NO_SCALE)
  14509. {
  14510. this.refresh();
  14511. }
  14512. }
  14513. }
  14514. },
  14515. /**
  14516. * Handle window.orientationchange events
  14517. * @method Phaser.ScaleManager#checkOrientation
  14518. * @param {Event} event - The orientationchange event data.
  14519. */
  14520. checkOrientation: function (event) {
  14521. this.event = event;
  14522. this.orientation = window['orientation'];
  14523. if (this.isLandscape)
  14524. {
  14525. this.enterLandscape.dispatch(this.orientation, true, false);
  14526. }
  14527. else
  14528. {
  14529. this.enterPortrait.dispatch(this.orientation, false, true);
  14530. }
  14531. if (this.scaleMode !== Phaser.ScaleManager.NO_SCALE)
  14532. {
  14533. this.refresh();
  14534. }
  14535. },
  14536. /**
  14537. * Handle window.resize events
  14538. * @method Phaser.ScaleManager#checkResize
  14539. * @param {Event} event - The resize event data.
  14540. */
  14541. checkResize: function (event) {
  14542. this.event = event;
  14543. if (window.outerWidth > window.outerHeight)
  14544. {
  14545. this.orientation = 90;
  14546. }
  14547. else
  14548. {
  14549. this.orientation = 0;
  14550. }
  14551. if (this.isLandscape)
  14552. {
  14553. this.enterLandscape.dispatch(this.orientation, true, false);
  14554. }
  14555. else
  14556. {
  14557. this.enterPortrait.dispatch(this.orientation, false, true);
  14558. }
  14559. if (this.scaleMode !== Phaser.ScaleManager.NO_SCALE)
  14560. {
  14561. this.refresh();
  14562. }
  14563. this.checkOrientationState();
  14564. },
  14565. /**
  14566. * Re-calculate scale mode and update screen size.
  14567. * @method Phaser.ScaleManager#refresh
  14568. */
  14569. refresh: function () {
  14570. // We can't do anything about the status bars in iPads, web apps or desktops
  14571. if (this.game.device.iPad === false && this.game.device.webApp === false && this.game.device.desktop === false)
  14572. {
  14573. if (this.game.device.android && this.game.device.chrome === false)
  14574. {
  14575. window.scrollTo(0, 1);
  14576. }
  14577. else
  14578. {
  14579. window.scrollTo(0, 0);
  14580. }
  14581. }
  14582. if (this._check == null && this.maxIterations > 0)
  14583. {
  14584. this._iterations = this.maxIterations;
  14585. var _this = this;
  14586. this._check = window.setInterval(function () {
  14587. return _this.setScreenSize();
  14588. }, 10);
  14589. this.setScreenSize();
  14590. }
  14591. },
  14592. /**
  14593. * Set screen size automatically based on the scaleMode.
  14594. * @param {boolean} force - If force is true it will try to resize the game regardless of the document dimensions.
  14595. */
  14596. setScreenSize: function (force) {
  14597. if (typeof force == 'undefined')
  14598. {
  14599. force = false;
  14600. }
  14601. if (this.game.device.iPad === false && this.game.device.webApp === false && this.game.device.desktop === false)
  14602. {
  14603. if (this.game.device.android && this.game.device.chrome === false)
  14604. {
  14605. window.scrollTo(0, 1);
  14606. }
  14607. else
  14608. {
  14609. window.scrollTo(0, 0);
  14610. }
  14611. }
  14612. this._iterations--;
  14613. if (force || window.innerHeight > this._startHeight || this._iterations < 0)
  14614. {
  14615. // Set minimum height of content to new window height
  14616. document.documentElement['style'].minHeight = window.innerHeight + 'px';
  14617. if (this.incorrectOrientation === true)
  14618. {
  14619. this.setMaximum();
  14620. }
  14621. else if (!this.isFullScreen)
  14622. {
  14623. if (this.scaleMode == Phaser.ScaleManager.EXACT_FIT)
  14624. {
  14625. this.setExactFit();
  14626. }
  14627. else if (this.scaleMode == Phaser.ScaleManager.SHOW_ALL)
  14628. {
  14629. this.setShowAll();
  14630. }
  14631. }
  14632. else
  14633. {
  14634. if (this.fullScreenScaleMode == Phaser.ScaleManager.EXACT_FIT)
  14635. {
  14636. this.setExactFit();
  14637. }
  14638. else if (this.fullScreenScaleMode == Phaser.ScaleManager.SHOW_ALL)
  14639. {
  14640. this.setShowAll();
  14641. }
  14642. }
  14643. this.setSize();
  14644. clearInterval(this._check);
  14645. this._check = null;
  14646. }
  14647. },
  14648. /**
  14649. * Sets the canvas style width and height values based on minWidth/Height and maxWidth/Height.
  14650. * @method Phaser.ScaleManager#setSize
  14651. */
  14652. setSize: function () {
  14653. if (this.incorrectOrientation === false)
  14654. {
  14655. if (this.maxWidth && this.width > this.maxWidth)
  14656. {
  14657. this.width = this.maxWidth;
  14658. }
  14659. if (this.maxHeight && this.height > this.maxHeight)
  14660. {
  14661. this.height = this.maxHeight;
  14662. }
  14663. if (this.minWidth && this.width < this.minWidth)
  14664. {
  14665. this.width = this.minWidth;
  14666. }
  14667. if (this.minHeight && this.height < this.minHeight)
  14668. {
  14669. this.height = this.minHeight;
  14670. }
  14671. }
  14672. this.game.canvas.style.width = this.width + 'px';
  14673. this.game.canvas.style.height = this.height + 'px';
  14674. this.game.input.scale.setTo(this.game.width / this.width, this.game.height / this.height);
  14675. if (this.pageAlignHorizontally)
  14676. {
  14677. if (this.width < window.innerWidth && this.incorrectOrientation === false)
  14678. {
  14679. this.margin.x = Math.round((window.innerWidth - this.width) / 2);
  14680. this.game.canvas.style.marginLeft = this.margin.x + 'px';
  14681. }
  14682. else
  14683. {
  14684. this.margin.x = 0;
  14685. this.game.canvas.style.marginLeft = '0px';
  14686. }
  14687. }
  14688. if (this.pageAlignVertically)
  14689. {
  14690. if (this.height < window.innerHeight && this.incorrectOrientation === false)
  14691. {
  14692. this.margin.y = Math.round((window.innerHeight - this.height) / 2);
  14693. this.game.canvas.style.marginTop = this.margin.y + 'px';
  14694. }
  14695. else
  14696. {
  14697. this.margin.y = 0;
  14698. this.game.canvas.style.marginTop = '0px';
  14699. }
  14700. }
  14701. Phaser.Canvas.getOffset(this.game.canvas, this.game.stage.offset);
  14702. this.aspectRatio = this.width / this.height;
  14703. this.scaleFactor.x = this.game.width / this.width;
  14704. this.scaleFactor.y = this.game.height / this.height;
  14705. this.scaleFactorInversed.x = this.width / this.game.width;
  14706. this.scaleFactorInversed.y = this.height / this.game.height;
  14707. this.hasResized.dispatch(this.width, this.height);
  14708. this.checkOrientationState();
  14709. },
  14710. /**
  14711. * Sets this.width equal to window.innerWidth and this.height equal to window.innerHeight
  14712. * @method Phaser.ScaleManager#setMaximum
  14713. */
  14714. setMaximum: function () {
  14715. this.width = window.innerWidth;
  14716. this.height = window.innerHeight;
  14717. },
  14718. /**
  14719. * Calculates the multiplier needed to scale the game proportionally.
  14720. * @method Phaser.ScaleManager#setShowAll
  14721. */
  14722. setShowAll: function () {
  14723. var multiplier = Math.min((window.innerHeight / this.game.height), (window.innerWidth / this.game.width));
  14724. this.width = Math.round(this.game.width * multiplier);
  14725. this.height = Math.round(this.game.height * multiplier);
  14726. },
  14727. /**
  14728. * Sets the width and height values of the canvas, no larger than the maxWidth/Height.
  14729. * @method Phaser.ScaleManager#setExactFit
  14730. */
  14731. setExactFit: function () {
  14732. var availableWidth = window.innerWidth;
  14733. var availableHeight = window.innerHeight;
  14734. if (this.maxWidth && availableWidth > this.maxWidth)
  14735. {
  14736. this.width = this.maxWidth;
  14737. }
  14738. else
  14739. {
  14740. this.width = availableWidth;
  14741. }
  14742. if (this.maxHeight && availableHeight > this.maxHeight)
  14743. {
  14744. this.height = this.maxHeight;
  14745. }
  14746. else
  14747. {
  14748. this.height = availableHeight;
  14749. }
  14750. }
  14751. };
  14752. Phaser.ScaleManager.prototype.constructor = Phaser.ScaleManager;
  14753. /**
  14754. * @name Phaser.ScaleManager#isFullScreen
  14755. * @property {boolean} isFullScreen - Returns true if the browser is in full screen mode, otherwise false.
  14756. * @readonly
  14757. */
  14758. Object.defineProperty(Phaser.ScaleManager.prototype, "isFullScreen", {
  14759. get: function () {
  14760. return (document['fullscreenElement'] || document['mozFullScreenElement'] || document['webkitFullscreenElement']);
  14761. }
  14762. });
  14763. /**
  14764. * @name Phaser.ScaleManager#isPortrait
  14765. * @property {boolean} isPortrait - Returns true if the browser dimensions match a portrait display.
  14766. * @readonly
  14767. */
  14768. Object.defineProperty(Phaser.ScaleManager.prototype, "isPortrait", {
  14769. get: function () {
  14770. return this.orientation === 0 || this.orientation == 180;
  14771. }
  14772. });
  14773. /**
  14774. * @name Phaser.ScaleManager#isLandscape
  14775. * @property {boolean} isLandscape - Returns true if the browser dimensions match a landscape display.
  14776. * @readonly
  14777. */
  14778. Object.defineProperty(Phaser.ScaleManager.prototype, "isLandscape", {
  14779. get: function () {
  14780. return this.orientation === 90 || this.orientation === -90;
  14781. }
  14782. });
  14783. /**
  14784. * @author Richard Davey <rich@photonstorm.com>
  14785. * @copyright 2014 Photon Storm Ltd.
  14786. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  14787. */
  14788. /**
  14789. * Game constructor
  14790. *
  14791. * Instantiate a new <code>Phaser.Game</code> object.
  14792. * @class Phaser.Game
  14793. * @classdesc This is where the magic happens. The Game object is the heart of your game,
  14794. * providing quick access to common functions and handling the boot process.
  14795. * "Hell, there are no rules here - we're trying to accomplish something."
  14796. * Thomas A. Edison
  14797. * @constructor
  14798. * @param {number} [width=800] - The width of your game in game pixels.
  14799. * @param {number} [height=600] - The height of your game in game pixels.
  14800. * @param {number} [renderer=Phaser.AUTO] - Which renderer to use: Phaser.AUTO will auto-detect, Phaser.WEBGL, Phaser.CANVAS or Phaser.HEADLESS (no rendering at all).
  14801. * @param {string|HTMLElement} [parent=''] - The DOM element into which this games canvas will be injected. Either a DOM ID (string) or the element itself.
  14802. * @param {object} [state=null] - The default state object. A object consisting of Phaser.State functions (preload, create, update, render) or null.
  14803. * @param {boolean} [transparent=false] - Use a transparent canvas background or not.
  14804. * @param {boolean} [antialias=true] - Draw all image textures anti-aliased or not. The default is for smooth textures, but disable if your game features pixel art.
  14805. * @param {object} [physicsConfig=null] - A physics configuration object to pass to the Physics world on creation.
  14806. */
  14807. Phaser.Game = function (width, height, renderer, parent, state, transparent, antialias, physicsConfig) {
  14808. /**
  14809. * @property {number} id - Phaser Game ID (for when Pixi supports multiple instances).
  14810. */
  14811. this.id = Phaser.GAMES.push(this) - 1;
  14812. /**
  14813. * @property {object} config - The Phaser.Game configuration object.
  14814. */
  14815. this.config = null;
  14816. /**
  14817. * @property {object} physicsConfig - The Phaser.Physics.World configuration object.
  14818. */
  14819. this.physicsConfig = physicsConfig;
  14820. /**
  14821. * @property {string|HTMLElement} parent - The Games DOM parent.
  14822. * @default
  14823. */
  14824. this.parent = '';
  14825. /**
  14826. * @property {number} width - The Game width (in pixels).
  14827. * @default
  14828. */
  14829. this.width = 800;
  14830. /**
  14831. * @property {number} height - The Game height (in pixels).
  14832. * @default
  14833. */
  14834. this.height = 600;
  14835. /**
  14836. * @property {boolean} transparent - Use a transparent canvas background or not.
  14837. * @default
  14838. */
  14839. this.transparent = false;
  14840. /**
  14841. * @property {boolean} antialias - Anti-alias graphics. By default scaled images are smoothed in Canvas and WebGL, set anti-alias to false to disable this globally.
  14842. * @default
  14843. */
  14844. this.antialias = true;
  14845. /**
  14846. * @property {PIXI.CanvasRenderer|PIXI.WebGLRenderer} renderer - The Pixi Renderer.
  14847. */
  14848. this.renderer = null;
  14849. /**
  14850. * @property {number} renderType - The Renderer this game will use. Either Phaser.AUTO, Phaser.CANVAS or Phaser.WEBGL.
  14851. */
  14852. this.renderType = Phaser.AUTO;
  14853. /**
  14854. * @property {Phaser.StateManager} state - The StateManager.
  14855. */
  14856. this.state = null;
  14857. /**
  14858. * @property {boolean} isBooted - Whether the game engine is booted, aka available.
  14859. * @default
  14860. */
  14861. this.isBooted = false;
  14862. /**
  14863. * @property {boolean} id -Is game running or paused?
  14864. * @default
  14865. */
  14866. this.isRunning = false;
  14867. /**
  14868. * @property {Phaser.RequestAnimationFrame} raf - Automatically handles the core game loop via requestAnimationFrame or setTimeout
  14869. */
  14870. this.raf = null;
  14871. /**
  14872. * @property {Phaser.GameObjectFactory} add - Reference to the Phaser.GameObjectFactory.
  14873. */
  14874. this.add = null;
  14875. /**
  14876. * @property {Phaser.GameObjectCreator} make - Reference to the GameObject Creator.
  14877. */
  14878. this.make = null;
  14879. /**
  14880. * @property {Phaser.Cache} cache - Reference to the assets cache.
  14881. */
  14882. this.cache = null;
  14883. /**
  14884. * @property {Phaser.Input} input - Reference to the input manager
  14885. */
  14886. this.input = null;
  14887. /**
  14888. * @property {Phaser.Loader} load - Reference to the assets loader.
  14889. */
  14890. this.load = null;
  14891. /**
  14892. * @property {Phaser.Math} math - Reference to the math helper.
  14893. */
  14894. this.math = null;
  14895. /**
  14896. * @property {Phaser.Net} net - Reference to the network class.
  14897. */
  14898. this.net = null;
  14899. /**
  14900. * @property {Phaser.ScaleManager} scale - The game scale manager.
  14901. */
  14902. this.scale = null;
  14903. /**
  14904. * @property {Phaser.SoundManager} sound - Reference to the sound manager.
  14905. */
  14906. this.sound = null;
  14907. /**
  14908. * @property {Phaser.Stage} stage - Reference to the stage.
  14909. */
  14910. this.stage = null;
  14911. /**
  14912. * @property {Phaser.Time} time - Reference to the core game clock.
  14913. */
  14914. this.time = null;
  14915. /**
  14916. * @property {Phaser.TweenManager} tweens - Reference to the tween manager.
  14917. */
  14918. this.tweens = null;
  14919. /**
  14920. * @property {Phaser.World} world - Reference to the world.
  14921. */
  14922. this.world = null;
  14923. /**
  14924. * @property {Phaser.Physics} physics - Reference to the physics manager.
  14925. */
  14926. this.physics = null;
  14927. /**
  14928. * @property {Phaser.RandomDataGenerator} rnd - Instance of repeatable random data generator helper.
  14929. */
  14930. this.rnd = null;
  14931. /**
  14932. * @property {Phaser.Device} device - Contains device information and capabilities.
  14933. */
  14934. this.device = null;
  14935. /**
  14936. * @property {Phaser.Camera} camera - A handy reference to world.camera.
  14937. */
  14938. this.camera = null;
  14939. /**
  14940. * @property {HTMLCanvasElement} canvas - A handy reference to renderer.view, the canvas that the game is being rendered in to.
  14941. */
  14942. this.canvas = null;
  14943. /**
  14944. * @property {CanvasRenderingContext2D} context - A handy reference to renderer.context (only set for CANVAS games, not WebGL)
  14945. */
  14946. this.context = null;
  14947. /**
  14948. * @property {Phaser.Utils.Debug} debug - A set of useful debug utilitie.
  14949. */
  14950. this.debug = null;
  14951. /**
  14952. * @property {Phaser.Particles} particles - The Particle Manager.
  14953. */
  14954. this.particles = null;
  14955. /**
  14956. * @property {boolean} stepping - Enable core loop stepping with Game.enableStep().
  14957. * @default
  14958. * @readonly
  14959. */
  14960. this.stepping = false;
  14961. /**
  14962. * @property {boolean} pendingStep - An internal property used by enableStep, but also useful to query from your own game objects.
  14963. * @default
  14964. * @readonly
  14965. */
  14966. this.pendingStep = false;
  14967. /**
  14968. * @property {number} stepCount - When stepping is enabled this contains the current step cycle.
  14969. * @default
  14970. * @readonly
  14971. */
  14972. this.stepCount = 0;
  14973. /**
  14974. * @property {Phaser.Signal} onPause - This event is fired when the game pauses.
  14975. */
  14976. this.onPause = null;
  14977. /**
  14978. * @property {Phaser.Signal} onResume - This event is fired when the game resumes from a paused state.
  14979. */
  14980. this.onResume = null;
  14981. /**
  14982. * @property {Phaser.Signal} onBlur - This event is fired when the game no longer has focus (typically on page hide).
  14983. */
  14984. this.onBlur = null;
  14985. /**
  14986. * @property {Phaser.Signal} onFocus - This event is fired when the game has focus (typically on page show).
  14987. */
  14988. this.onFocus = null;
  14989. /**
  14990. * @property {boolean} _paused - Is game paused?
  14991. * @private
  14992. */
  14993. this._paused = false;
  14994. /**
  14995. * @property {boolean} _codePaused - Was the game paused via code or a visibility change?
  14996. * @private
  14997. */
  14998. this._codePaused = false;
  14999. // Parse the configuration object (if any)
  15000. if (arguments.length === 1 && typeof arguments[0] === 'object')
  15001. {
  15002. this.parseConfig(arguments[0]);
  15003. }
  15004. else
  15005. {
  15006. if (typeof width !== 'undefined')
  15007. {
  15008. this.width = width;
  15009. }
  15010. if (typeof height !== 'undefined')
  15011. {
  15012. this.height = height;
  15013. }
  15014. if (typeof renderer !== 'undefined')
  15015. {
  15016. this.renderer = renderer;
  15017. this.renderType = renderer;
  15018. }
  15019. if (typeof parent !== 'undefined')
  15020. {
  15021. this.parent = parent;
  15022. }
  15023. if (typeof transparent !== 'undefined')
  15024. {
  15025. this.transparent = transparent;
  15026. }
  15027. if (typeof antialias !== 'undefined')
  15028. {
  15029. this.antialias = antialias;
  15030. }
  15031. this.rnd = new Phaser.RandomDataGenerator([(Date.now() * Math.random()).toString()]);
  15032. this.state = new Phaser.StateManager(this, state);
  15033. }
  15034. var _this = this;
  15035. this._onBoot = function () {
  15036. return _this.boot();
  15037. };
  15038. if (document.readyState === 'complete' || document.readyState === 'interactive')
  15039. {
  15040. window.setTimeout(this._onBoot, 0);
  15041. }
  15042. else
  15043. {
  15044. document.addEventListener('DOMContentLoaded', this._onBoot, false);
  15045. window.addEventListener('load', this._onBoot, false);
  15046. }
  15047. return this;
  15048. };
  15049. Phaser.Game.prototype = {
  15050. /**
  15051. * Parses a Game configuration object.
  15052. *
  15053. * @method Phaser.Game#parseConfig
  15054. * @protected
  15055. */
  15056. parseConfig: function (config) {
  15057. this.config = config;
  15058. if (config['width'])
  15059. {
  15060. this.width = Phaser.Utils.parseDimension(config['width'], 0);
  15061. }
  15062. if (config['height'])
  15063. {
  15064. this.height = Phaser.Utils.parseDimension(config['height'], 1);
  15065. }
  15066. if (config['renderer'])
  15067. {
  15068. this.renderer = config['renderer'];
  15069. this.renderType = config['renderer'];
  15070. }
  15071. if (config['parent'])
  15072. {
  15073. this.parent = config['parent'];
  15074. }
  15075. if (config['transparent'])
  15076. {
  15077. this.transparent = config['transparent'];
  15078. }
  15079. if (config['antialias'])
  15080. {
  15081. this.antialias = config['antialias'];
  15082. }
  15083. if (config['physicsConfig'])
  15084. {
  15085. this.physicsConfig = config['physicsConfig'];
  15086. }
  15087. var seed = [(Date.now() * Math.random()).toString()];
  15088. if (config['seed'])
  15089. {
  15090. seed = config['seed'];
  15091. }
  15092. this.rnd = new Phaser.RandomDataGenerator(seed);
  15093. var state = null;
  15094. if (config['state'])
  15095. {
  15096. state = config['state'];
  15097. }
  15098. this.state = new Phaser.StateManager(this, state);
  15099. },
  15100. /**
  15101. * Initialize engine sub modules and start the game.
  15102. *
  15103. * @method Phaser.Game#boot
  15104. * @protected
  15105. */
  15106. boot: function () {
  15107. if (this.isBooted)
  15108. {
  15109. return;
  15110. }
  15111. if (!document.body)
  15112. {
  15113. window.setTimeout(this._onBoot, 20);
  15114. }
  15115. else
  15116. {
  15117. document.removeEventListener('DOMContentLoaded', this._onBoot);
  15118. window.removeEventListener('load', this._onBoot);
  15119. this.onPause = new Phaser.Signal();
  15120. this.onResume = new Phaser.Signal();
  15121. this.onBlur = new Phaser.Signal();
  15122. this.onFocus = new Phaser.Signal();
  15123. this.isBooted = true;
  15124. this.device = new Phaser.Device(this);
  15125. this.math = Phaser.Math;
  15126. this.stage = new Phaser.Stage(this, this.width, this.height);
  15127. this.scale = new Phaser.ScaleManager(this, this.width, this.height);
  15128. this.setUpRenderer();
  15129. this.device.checkFullScreenSupport();
  15130. this.world = new Phaser.World(this);
  15131. this.add = new Phaser.GameObjectFactory(this);
  15132. this.make = new Phaser.GameObjectCreator(this);
  15133. this.cache = new Phaser.Cache(this);
  15134. this.load = new Phaser.Loader(this);
  15135. this.time = new Phaser.Time(this);
  15136. this.tweens = new Phaser.TweenManager(this);
  15137. this.input = new Phaser.Input(this);
  15138. this.sound = new Phaser.SoundManager(this);
  15139. this.physics = new Phaser.Physics(this, this.physicsConfig);
  15140. this.particles = new Phaser.Particles(this);
  15141. this.plugins = new Phaser.PluginManager(this);
  15142. this.net = new Phaser.Net(this);
  15143. this.debug = new Phaser.Utils.Debug(this);
  15144. this.time.boot();
  15145. this.stage.boot();
  15146. this.world.boot();
  15147. this.input.boot();
  15148. this.sound.boot();
  15149. this.state.boot();
  15150. this.debug.boot();
  15151. this.showDebugHeader();
  15152. this.isRunning = true;
  15153. if (this.config && this.config['forceSetTimeOut'])
  15154. {
  15155. this.raf = new Phaser.RequestAnimationFrame(this, this.config['forceSetTimeOut']);
  15156. }
  15157. else
  15158. {
  15159. this.raf = new Phaser.RequestAnimationFrame(this, false);
  15160. }
  15161. this.raf.start();
  15162. }
  15163. },
  15164. /**
  15165. * Displays a Phaser version debug header in the console.
  15166. *
  15167. * @method Phaser.Game#showDebugHeader
  15168. * @protected
  15169. */
  15170. showDebugHeader: function () {
  15171. var v = Phaser.DEV_VERSION;
  15172. var r = 'Canvas';
  15173. var a = 'HTML Audio';
  15174. var c = 1;
  15175. if (this.renderType === Phaser.WEBGL)
  15176. {
  15177. r = 'WebGL';
  15178. c++;
  15179. }
  15180. else if (this.renderType == Phaser.HEADLESS)
  15181. {
  15182. r = 'Headless';
  15183. }
  15184. if (this.device.webAudio)
  15185. {
  15186. a = 'WebAudio';
  15187. c++;
  15188. }
  15189. if (this.device.chrome)
  15190. {
  15191. var args = [
  15192. '%c %c %c Phaser v' + v + ' - ' + r + ' - ' + a + ' %c %c ' + ' http://phaser.io %c %c ♥%c♥%c♥ ',
  15193. 'background: #0cf300',
  15194. 'background: #00bc17',
  15195. 'color: #ffffff; background: #00711f;',
  15196. 'background: #00bc17',
  15197. 'background: #0cf300',
  15198. 'background: #00bc17'
  15199. ];
  15200. for (var i = 0; i < 3; i++)
  15201. {
  15202. if (i < c)
  15203. {
  15204. args.push('color: #ff2424; background: #fff');
  15205. }
  15206. else
  15207. {
  15208. args.push('color: #959595; background: #fff');
  15209. }
  15210. }
  15211. console.log.apply(console, args);
  15212. }
  15213. else
  15214. {
  15215. console.log('Phaser v' + v + ' - Renderer: ' + r + ' - Audio: ' + a + ' - http://phaser.io');
  15216. }
  15217. },
  15218. /**
  15219. * Checks if the device is capable of using the requested renderer and sets it up or an alternative if not.
  15220. *
  15221. * @method Phaser.Game#setUpRenderer
  15222. * @protected
  15223. */
  15224. setUpRenderer: function () {
  15225. if (this.device.trident)
  15226. {
  15227. // Pixi WebGL renderer on IE11 doesn't work correctly at the moment, the pre-multiplied alpha gets all washed out.
  15228. // So we're forcing canvas for now until this is fixed, sorry. It's got to be better than no game appearing at all, right?
  15229. this.renderType = Phaser.CANVAS;
  15230. }
  15231. if (this.renderType === Phaser.HEADLESS || this.renderType === Phaser.CANVAS || (this.renderType === Phaser.AUTO && this.device.webGL === false))
  15232. {
  15233. if (this.device.canvas)
  15234. {
  15235. if (this.renderType === Phaser.AUTO)
  15236. {
  15237. this.renderType = Phaser.CANVAS;
  15238. }
  15239. this.renderer = new PIXI.CanvasRenderer(this.width, this.height, this.canvas, this.transparent);
  15240. this.context = this.renderer.context;
  15241. }
  15242. else
  15243. {
  15244. throw new Error('Phaser.Game - cannot create Canvas or WebGL context, aborting.');
  15245. }
  15246. }
  15247. else
  15248. {
  15249. // They requested WebGL, and their browser supports it
  15250. this.renderType = Phaser.WEBGL;
  15251. this.renderer = new PIXI.WebGLRenderer(this.width, this.height, this.canvas, this.transparent, this.antialias);
  15252. this.context = null;
  15253. }
  15254. if (this.renderType !== Phaser.HEADLESS)
  15255. {
  15256. this.stage.smoothed = this.antialias;
  15257. Phaser.Canvas.addToDOM(this.canvas, this.parent, true);
  15258. Phaser.Canvas.setTouchAction(this.canvas);
  15259. }
  15260. },
  15261. /**
  15262. * The core game loop when in a paused state.
  15263. *
  15264. * @method Phaser.Game#update
  15265. * @protected
  15266. * @param {number} time - The current time as provided by RequestAnimationFrame.
  15267. */
  15268. update: function (time) {
  15269. this.time.update(time);
  15270. if (!this._paused && !this.pendingStep)
  15271. {
  15272. if (this.stepping)
  15273. {
  15274. this.pendingStep = true;
  15275. }
  15276. this.debug.preUpdate();
  15277. this.physics.preUpdate();
  15278. this.state.preUpdate();
  15279. this.plugins.preUpdate();
  15280. this.stage.preUpdate();
  15281. this.state.update();
  15282. this.stage.update();
  15283. this.tweens.update();
  15284. this.sound.update();
  15285. this.input.update();
  15286. // this.state.update();
  15287. this.physics.update();
  15288. this.particles.update();
  15289. this.plugins.update();
  15290. this.stage.postUpdate();
  15291. this.plugins.postUpdate();
  15292. }
  15293. else
  15294. {
  15295. this.debug.preUpdate();
  15296. }
  15297. if (this.renderType != Phaser.HEADLESS)
  15298. {
  15299. this.renderer.render(this.stage);
  15300. this.plugins.render();
  15301. this.state.render();
  15302. this.plugins.postRender();
  15303. }
  15304. },
  15305. /**
  15306. * Enable core game loop stepping. When enabled you must call game.step() directly (perhaps via a DOM button?)
  15307. * Calling step will advance the game loop by one frame. This is extremely useful for hard to track down errors!
  15308. *
  15309. * @method Phaser.Game#enableStep
  15310. */
  15311. enableStep: function () {
  15312. this.stepping = true;
  15313. this.pendingStep = false;
  15314. this.stepCount = 0;
  15315. },
  15316. /**
  15317. * Disables core game loop stepping.
  15318. *
  15319. * @method Phaser.Game#disableStep
  15320. */
  15321. disableStep: function () {
  15322. this.stepping = false;
  15323. this.pendingStep = false;
  15324. },
  15325. /**
  15326. * When stepping is enabled you must call this function directly (perhaps via a DOM button?) to advance the game loop by one frame.
  15327. * This is extremely useful to hard to track down errors! Use the internal stepCount property to monitor progress.
  15328. *
  15329. * @method Phaser.Game#step
  15330. */
  15331. step: function () {
  15332. this.pendingStep = false;
  15333. this.stepCount++;
  15334. },
  15335. /**
  15336. * Nuke the entire game from orbit
  15337. *
  15338. * @method Phaser.Game#destroy
  15339. */
  15340. destroy: function () {
  15341. this.raf.stop();
  15342. this.input.destroy();
  15343. this.state.destroy();
  15344. this.physics.destroy();
  15345. this.state = null;
  15346. this.cache = null;
  15347. this.input = null;
  15348. this.load = null;
  15349. this.sound = null;
  15350. this.stage = null;
  15351. this.time = null;
  15352. this.world = null;
  15353. this.isBooted = false;
  15354. },
  15355. /**
  15356. * Called by the Stage visibility handler.
  15357. *
  15358. * @method Phaser.Game#gamePaused
  15359. * @param {object} event - The DOM event that caused the game to pause, if any.
  15360. * @protected
  15361. */
  15362. gamePaused: function (event) {
  15363. // If the game is already paused it was done via game code, so don't re-pause it
  15364. if (!this._paused)
  15365. {
  15366. this._paused = true;
  15367. this.time.gamePaused();
  15368. this.sound.setMute();
  15369. this.onPause.dispatch(event);
  15370. }
  15371. },
  15372. /**
  15373. * Called by the Stage visibility handler.
  15374. *
  15375. * @method Phaser.Game#gameResumed
  15376. * @param {object} event - The DOM event that caused the game to pause, if any.
  15377. * @protected
  15378. */
  15379. gameResumed: function (event) {
  15380. // Game is paused, but wasn't paused via code, so resume it
  15381. if (this._paused && !this._codePaused)
  15382. {
  15383. this._paused = false;
  15384. this.time.gameResumed();
  15385. this.input.reset();
  15386. this.sound.unsetMute();
  15387. this.onResume.dispatch(event);
  15388. }
  15389. },
  15390. /**
  15391. * Called by the Stage visibility handler.
  15392. *
  15393. * @method Phaser.Game#focusLoss
  15394. * @param {object} event - The DOM event that caused the game to pause, if any.
  15395. * @protected
  15396. */
  15397. focusLoss: function (event) {
  15398. this.onBlur.dispatch(event);
  15399. this.gamePaused(event);
  15400. },
  15401. /**
  15402. * Called by the Stage visibility handler.
  15403. *
  15404. * @method Phaser.Game#focusGain
  15405. * @param {object} event - The DOM event that caused the game to pause, if any.
  15406. * @protected
  15407. */
  15408. focusGain: function (event) {
  15409. this.onFocus.dispatch(event);
  15410. this.gameResumed(event);
  15411. }
  15412. };
  15413. Phaser.Game.prototype.constructor = Phaser.Game;
  15414. /**
  15415. * The paused state of the Game. A paused game doesn't update any of its subsystems.
  15416. * When a game is paused the onPause event is dispatched. When it is resumed the onResume event is dispatched.
  15417. * @name Phaser.Game#paused
  15418. * @property {boolean} paused - Gets and sets the paused state of the Game.
  15419. */
  15420. Object.defineProperty(Phaser.Game.prototype, "paused", {
  15421. get: function () {
  15422. return this._paused;
  15423. },
  15424. set: function (value) {
  15425. if (value === true)
  15426. {
  15427. if (this._paused === false)
  15428. {
  15429. this._paused = true;
  15430. this._codePaused = true;
  15431. this.sound.mute = true;
  15432. this.time.gamePaused();
  15433. this.onPause.dispatch(this);
  15434. }
  15435. }
  15436. else
  15437. {
  15438. if (this._paused)
  15439. {
  15440. this._paused = false;
  15441. this._codePaused = false;
  15442. this.input.reset();
  15443. this.sound.mute = false;
  15444. this.time.gameResumed();
  15445. this.onResume.dispatch(this);
  15446. }
  15447. }
  15448. }
  15449. });
  15450. /**
  15451. * "Deleted code is debugged code." - Jeff Sickel
  15452. */
  15453. /**
  15454. * @author Richard Davey <rich@photonstorm.com>
  15455. * @copyright 2014 Photon Storm Ltd.
  15456. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  15457. */
  15458. /**
  15459. * Phaser.Input is the Input Manager for all types of Input across Phaser, including mouse, keyboard, touch and MSPointer.
  15460. * The Input manager is updated automatically by the core game loop.
  15461. *
  15462. * @class Phaser.Input
  15463. * @constructor
  15464. * @param {Phaser.Game} game - Current game instance.
  15465. */
  15466. Phaser.Input = function (game) {
  15467. /**
  15468. * @property {Phaser.Game} game - A reference to the currently running game.
  15469. */
  15470. this.game = game;
  15471. /**
  15472. * @property {HTMLCanvasElement} hitCanvas - The canvas to which single pixels are drawn in order to perform pixel-perfect hit detection.
  15473. * @default
  15474. */
  15475. this.hitCanvas = null;
  15476. /**
  15477. * @property {CanvasRenderingContext2D} hitContext - The context of the pixel perfect hit canvas.
  15478. * @default
  15479. */
  15480. this.hitContext = null;
  15481. /**
  15482. * @property {function} moveCallback - An optional callback that will be fired every time the activePointer receives a move event from the DOM. Set to null to disable.
  15483. */
  15484. this.moveCallback = null;
  15485. /**
  15486. * @property {object} moveCallbackContext - The context in which the moveCallback will be sent. Defaults to Phaser.Input but can be set to any valid JS object.
  15487. */
  15488. this.moveCallbackContext = this;
  15489. /**
  15490. * @property {number} pollRate - How often should the input pointers be checked for updates? A value of 0 means every single frame (60fps); a value of 1 means every other frame (30fps) and so on.
  15491. * @default
  15492. */
  15493. this.pollRate = 0;
  15494. /**
  15495. * You can disable all Input by setting Input.disabled = true. While set all new input related events will be ignored.
  15496. * If you need to disable just one type of input; for example mouse; use Input.mouse.disabled = true instead
  15497. * @property {boolean} disabled
  15498. * @default
  15499. */
  15500. this.disabled = false;
  15501. /**
  15502. * @property {number} multiInputOverride - Controls the expected behaviour when using a mouse and touch together on a multi-input device.
  15503. * @default
  15504. */
  15505. this.multiInputOverride = Phaser.Input.MOUSE_TOUCH_COMBINE;
  15506. /**
  15507. * @property {Phaser.Point} position - A point object representing the current position of the Pointer.
  15508. * @default
  15509. */
  15510. this.position = null;
  15511. /**
  15512. * @property {Phaser.Point} speed - A point object representing the speed of the Pointer. Only really useful in single Pointer games; otherwise see the Pointer objects directly.
  15513. */
  15514. this.speed = null;
  15515. /**
  15516. * A Circle object centered on the x/y screen coordinates of the Input.
  15517. * Default size of 44px (Apples recommended "finger tip" size) but can be changed to anything.
  15518. * @property {Phaser.Circle} circle
  15519. */
  15520. this.circle = null;
  15521. /**
  15522. * @property {Phaser.Point} scale - The scale by which all input coordinates are multiplied; calculated by the ScaleManager. In an un-scaled game the values will be x = 1 and y = 1.
  15523. */
  15524. this.scale = null;
  15525. /**
  15526. * @property {number} maxPointers - The maximum number of Pointers allowed to be active at any one time. For lots of games it's useful to set this to 1.
  15527. * @default
  15528. */
  15529. this.maxPointers = 10;
  15530. /**
  15531. * @property {number} currentPointers - The current number of active Pointers.
  15532. * @default
  15533. */
  15534. this.currentPointers = 0;
  15535. /**
  15536. * @property {number} tapRate - The number of milliseconds that the Pointer has to be pressed down and then released to be considered a tap or click.
  15537. * @default
  15538. */
  15539. this.tapRate = 200;
  15540. /**
  15541. * @property {number} doubleTapRate - The number of milliseconds between taps of the same Pointer for it to be considered a double tap / click.
  15542. * @default
  15543. */
  15544. this.doubleTapRate = 300;
  15545. /**
  15546. * @property {number} holdRate - The number of milliseconds that the Pointer has to be pressed down for it to fire a onHold event.
  15547. * @default
  15548. */
  15549. this.holdRate = 2000;
  15550. /**
  15551. * @property {number} justPressedRate - The number of milliseconds below which the Pointer is considered justPressed.
  15552. * @default
  15553. */
  15554. this.justPressedRate = 200;
  15555. /**
  15556. * @property {number} justReleasedRate - The number of milliseconds below which the Pointer is considered justReleased .
  15557. * @default
  15558. */
  15559. this.justReleasedRate = 200;
  15560. /**
  15561. * Sets if the Pointer objects should record a history of x/y coordinates they have passed through.
  15562. * The history is cleared each time the Pointer is pressed down.
  15563. * The history is updated at the rate specified in Input.pollRate
  15564. * @property {boolean} recordPointerHistory
  15565. * @default
  15566. */
  15567. this.recordPointerHistory = false;
  15568. /**
  15569. * @property {number} recordRate - The rate in milliseconds at which the Pointer objects should update their tracking history.
  15570. * @default
  15571. */
  15572. this.recordRate = 100;
  15573. /**
  15574. * The total number of entries that can be recorded into the Pointer objects tracking history.
  15575. * If the Pointer is tracking one event every 100ms; then a trackLimit of 100 would store the last 10 seconds worth of history.
  15576. * @property {number} recordLimit
  15577. * @default
  15578. */
  15579. this.recordLimit = 100;
  15580. /**
  15581. * @property {Phaser.Pointer} pointer1 - A Pointer object.
  15582. */
  15583. this.pointer1 = null;
  15584. /**
  15585. * @property {Phaser.Pointer} pointer2 - A Pointer object.
  15586. */
  15587. this.pointer2 = null;
  15588. /**
  15589. * @property {Phaser.Pointer} pointer3 - A Pointer object.
  15590. */
  15591. this.pointer3 = null;
  15592. /**
  15593. * @property {Phaser.Pointer} pointer4 - A Pointer object.
  15594. */
  15595. this.pointer4 = null;
  15596. /**
  15597. * @property {Phaser.Pointer} pointer5 - A Pointer object.
  15598. */
  15599. this.pointer5 = null;
  15600. /**
  15601. * @property {Phaser.Pointer} pointer6 - A Pointer object.
  15602. */
  15603. this.pointer6 = null;
  15604. /**
  15605. * @property {Phaser.Pointer} pointer7 - A Pointer object.
  15606. */
  15607. this.pointer7 = null;
  15608. /**
  15609. * @property {Phaser.Pointer} pointer8 - A Pointer object.
  15610. */
  15611. this.pointer8 = null;
  15612. /**
  15613. * @property {Phaser.Pointer} pointer9 - A Pointer object.
  15614. */
  15615. this.pointer9 = null;
  15616. /**
  15617. * @property {Phaser.Pointer} pointer10 - A Pointer object.
  15618. */
  15619. this.pointer10 = null;
  15620. /**
  15621. * The most recently active Pointer object.
  15622. * When you've limited max pointers to 1 this will accurately be either the first finger touched or mouse.
  15623. * @property {Phaser.Pointer} activePointer
  15624. */
  15625. this.activePointer = null;
  15626. /**
  15627. * @property {Pointer} mousePointer - The mouse has its own unique Phaser.Pointer object which you can use if making a desktop specific game.
  15628. */
  15629. this.mousePointer = null;
  15630. /**
  15631. * @property {Phaser.Mouse} mouse - The Mouse Input manager.
  15632. */
  15633. this.mouse = null;
  15634. /**
  15635. * @property {Phaser.Keyboard} keyboard - The Keyboard Input manager.
  15636. */
  15637. this.keyboard = null;
  15638. /**
  15639. * @property {Phaser.Touch} touch - the Touch Input manager.
  15640. */
  15641. this.touch = null;
  15642. /**
  15643. * @property {Phaser.MSPointer} mspointer - The MSPointer Input manager.
  15644. */
  15645. this.mspointer = null;
  15646. /**
  15647. * @property {Phaser.Gamepad} gamepad - The Gamepad Input manager.
  15648. */
  15649. this.gamepad = null;
  15650. /**
  15651. * @property {Phaser.Gestures} gestures - The Gestures manager.
  15652. */
  15653. // this.gestures = null;
  15654. /**
  15655. * @property {Phaser.Signal} onDown - A Signal that is dispatched each time a pointer is pressed down.
  15656. */
  15657. this.onDown = null;
  15658. /**
  15659. * @property {Phaser.Signal} onUp - A Signal that is dispatched each time a pointer is released.
  15660. */
  15661. this.onUp = null;
  15662. /**
  15663. * @property {Phaser.Signal} onTap - A Signal that is dispatched each time a pointer is tapped.
  15664. */
  15665. this.onTap = null;
  15666. /**
  15667. * @property {Phaser.Signal} onHold - A Signal that is dispatched each time a pointer is held down.
  15668. */
  15669. this.onHold = null;
  15670. /**
  15671. * A linked list of interactive objects; the InputHandler components (belonging to Sprites) register themselves with this.
  15672. * @property {Phaser.LinkedList} interactiveItems
  15673. */
  15674. this.interactiveItems = new Phaser.LinkedList();
  15675. /**
  15676. * @property {Phaser.Point} _localPoint - Internal cache var.
  15677. * @private
  15678. */
  15679. this._localPoint = new Phaser.Point();
  15680. /**
  15681. * @property {number} _pollCounter - Internal var holding the current poll counter.
  15682. * @private
  15683. */
  15684. this._pollCounter = 0;
  15685. /**
  15686. * @property {Phaser.Point} _oldPosition - A point object representing the previous position of the Pointer.
  15687. * @private
  15688. */
  15689. this._oldPosition = null;
  15690. /**
  15691. * @property {number} _x - x coordinate of the most recent Pointer event
  15692. * @private
  15693. */
  15694. this._x = 0;
  15695. /**
  15696. * @property {number} _y - Y coordinate of the most recent Pointer event
  15697. * @private
  15698. */
  15699. this._y = 0;
  15700. };
  15701. /**
  15702. * @constant
  15703. * @type {number}
  15704. */
  15705. Phaser.Input.MOUSE_OVERRIDES_TOUCH = 0;
  15706. /**
  15707. * @constant
  15708. * @type {number}
  15709. */
  15710. Phaser.Input.TOUCH_OVERRIDES_MOUSE = 1;
  15711. /**
  15712. * @constant
  15713. * @type {number}
  15714. */
  15715. Phaser.Input.MOUSE_TOUCH_COMBINE = 2;
  15716. Phaser.Input.prototype = {
  15717. /**
  15718. * Starts the Input Manager running.
  15719. * @method Phaser.Input#boot
  15720. * @protected
  15721. */
  15722. boot: function () {
  15723. this.mousePointer = new Phaser.Pointer(this.game, 0);
  15724. this.pointer1 = new Phaser.Pointer(this.game, 1);
  15725. this.pointer2 = new Phaser.Pointer(this.game, 2);
  15726. this.mouse = new Phaser.Mouse(this.game);
  15727. this.keyboard = new Phaser.Keyboard(this.game);
  15728. this.touch = new Phaser.Touch(this.game);
  15729. this.mspointer = new Phaser.MSPointer(this.game);
  15730. this.gamepad = new Phaser.Gamepad(this.game);
  15731. // this.gestures = new Phaser.Gestures(this.game);
  15732. this.onDown = new Phaser.Signal();
  15733. this.onUp = new Phaser.Signal();
  15734. this.onTap = new Phaser.Signal();
  15735. this.onHold = new Phaser.Signal();
  15736. this.scale = new Phaser.Point(1, 1);
  15737. this.speed = new Phaser.Point();
  15738. this.position = new Phaser.Point();
  15739. this._oldPosition = new Phaser.Point();
  15740. this.circle = new Phaser.Circle(0, 0, 44);
  15741. this.activePointer = this.mousePointer;
  15742. this.currentPointers = 0;
  15743. this.hitCanvas = document.createElement('canvas');
  15744. this.hitCanvas.width = 1;
  15745. this.hitCanvas.height = 1;
  15746. this.hitContext = this.hitCanvas.getContext('2d');
  15747. this.mouse.start();
  15748. this.keyboard.start();
  15749. this.touch.start();
  15750. this.mspointer.start();
  15751. this.mousePointer.active = true;
  15752. },
  15753. /**
  15754. * Stops all of the Input Managers from running.
  15755. * @method Phaser.Input#destroy
  15756. */
  15757. destroy: function () {
  15758. this.mouse.stop();
  15759. this.keyboard.stop();
  15760. this.touch.stop();
  15761. this.mspointer.stop();
  15762. this.gamepad.stop();
  15763. // this.gestures.stop();
  15764. this.moveCallback = null;
  15765. },
  15766. /**
  15767. * Sets a callback that is fired every time the activePointer receives a DOM move event such as a mousemove or touchmove.
  15768. * It will be called every time the activePointer moves, which in a multi-touch game can be a lot of times, so this is best
  15769. * to only use if you've limited input to a single pointer (i.e. mouse or touch)
  15770. * @method Phaser.Input#setMoveCallback
  15771. * @param {function} callback - The callback that will be called each time the activePointer receives a DOM move event.
  15772. * @param {object} callbackContext - The context in which the callback will be called.
  15773. */
  15774. setMoveCallback: function (callback, callbackContext) {
  15775. this.moveCallback = callback;
  15776. this.moveCallbackContext = callbackContext;
  15777. },
  15778. /**
  15779. * Add a new Pointer object to the Input Manager. By default Input creates 3 pointer objects: mousePointer, pointer1 and pointer2.
  15780. * If you need more then use this to create a new one, up to a maximum of 10.
  15781. * @method Phaser.Input#addPointer
  15782. * @return {Phaser.Pointer} A reference to the new Pointer object that was created.
  15783. */
  15784. addPointer: function () {
  15785. var next = 0;
  15786. for (var i = 10; i > 0; i--)
  15787. {
  15788. if (this['pointer' + i] === null)
  15789. {
  15790. next = i;
  15791. }
  15792. }
  15793. if (next === 0)
  15794. {
  15795. console.warn("You can only have 10 Pointer objects");
  15796. return null;
  15797. }
  15798. else
  15799. {
  15800. this['pointer' + next] = new Phaser.Pointer(this.game, next);
  15801. return this['pointer' + next];
  15802. }
  15803. },
  15804. /**
  15805. * Updates the Input Manager. Called by the core Game loop.
  15806. * @method Phaser.Input#update
  15807. * @protected
  15808. */
  15809. update: function () {
  15810. this.keyboard.update();
  15811. if (this.pollRate > 0 && this._pollCounter < this.pollRate)
  15812. {
  15813. this._pollCounter++;
  15814. return;
  15815. }
  15816. this.speed.x = this.position.x - this._oldPosition.x;
  15817. this.speed.y = this.position.y - this._oldPosition.y;
  15818. this._oldPosition.copyFrom(this.position);
  15819. this.mousePointer.update();
  15820. if (this.gamepad.active) { this.gamepad.update(); }
  15821. this.pointer1.update();
  15822. this.pointer2.update();
  15823. if (this.pointer3) { this.pointer3.update(); }
  15824. if (this.pointer4) { this.pointer4.update(); }
  15825. if (this.pointer5) { this.pointer5.update(); }
  15826. if (this.pointer6) { this.pointer6.update(); }
  15827. if (this.pointer7) { this.pointer7.update(); }
  15828. if (this.pointer8) { this.pointer8.update(); }
  15829. if (this.pointer9) { this.pointer9.update(); }
  15830. if (this.pointer10) { this.pointer10.update(); }
  15831. this._pollCounter = 0;
  15832. // if (this.gestures.active) { this.gestures.update(); }
  15833. },
  15834. /**
  15835. * Reset all of the Pointers and Input states
  15836. * @method Phaser.Input#reset
  15837. * @param {boolean} hard - A soft reset (hard = false) won't reset any Signals that might be bound. A hard reset will.
  15838. */
  15839. reset: function (hard) {
  15840. if (this.game.isBooted === false)
  15841. {
  15842. return;
  15843. }
  15844. if (typeof hard == 'undefined') { hard = false; }
  15845. this.keyboard.reset();
  15846. this.mousePointer.reset();
  15847. this.gamepad.reset();
  15848. for (var i = 1; i <= 10; i++)
  15849. {
  15850. if (this['pointer' + i])
  15851. {
  15852. this['pointer' + i].reset();
  15853. }
  15854. }
  15855. this.currentPointers = 0;
  15856. if (this.game.canvas.style.cursor !== 'none')
  15857. {
  15858. this.game.canvas.style.cursor = 'inherit';
  15859. }
  15860. if (hard === true)
  15861. {
  15862. this.onDown.dispose();
  15863. this.onUp.dispose();
  15864. this.onTap.dispose();
  15865. this.onHold.dispose();
  15866. this.onDown = new Phaser.Signal();
  15867. this.onUp = new Phaser.Signal();
  15868. this.onTap = new Phaser.Signal();
  15869. this.onHold = new Phaser.Signal();
  15870. this.interactiveItems.callAll('reset');
  15871. }
  15872. this._pollCounter = 0;
  15873. },
  15874. /**
  15875. * Resets the speed and old position properties.
  15876. * @method Phaser.Input#resetSpeed
  15877. * @param {number} x - Sets the oldPosition.x value.
  15878. * @param {number} y - Sets the oldPosition.y value.
  15879. */
  15880. resetSpeed: function (x, y) {
  15881. this._oldPosition.setTo(x, y);
  15882. this.speed.setTo(0, 0);
  15883. },
  15884. /**
  15885. * Find the first free Pointer object and start it, passing in the event data. This is called automatically by Phaser.Touch and Phaser.MSPointer.
  15886. * @method Phaser.Input#startPointer
  15887. * @param {Any} event - The event data from the Touch event.
  15888. * @return {Phaser.Pointer} The Pointer object that was started or null if no Pointer object is available.
  15889. */
  15890. startPointer: function (event) {
  15891. if (this.maxPointers < 10 && this.totalActivePointers == this.maxPointers)
  15892. {
  15893. return null;
  15894. }
  15895. if (this.pointer1.active === false)
  15896. {
  15897. return this.pointer1.start(event);
  15898. }
  15899. else if (this.pointer2.active === false)
  15900. {
  15901. return this.pointer2.start(event);
  15902. }
  15903. else
  15904. {
  15905. for (var i = 3; i <= 10; i++)
  15906. {
  15907. if (this['pointer' + i] && this['pointer' + i].active === false)
  15908. {
  15909. return this['pointer' + i].start(event);
  15910. }
  15911. }
  15912. }
  15913. return null;
  15914. },
  15915. /**
  15916. * Updates the matching Pointer object, passing in the event data. This is called automatically and should not normally need to be invoked.
  15917. * @method Phaser.Input#updatePointer
  15918. * @param {Any} event - The event data from the Touch event.
  15919. * @return {Phaser.Pointer} The Pointer object that was updated or null if no Pointer object is available.
  15920. */
  15921. updatePointer: function (event) {
  15922. if (this.pointer1.active && this.pointer1.identifier == event.identifier)
  15923. {
  15924. return this.pointer1.move(event);
  15925. }
  15926. else if (this.pointer2.active && this.pointer2.identifier == event.identifier)
  15927. {
  15928. return this.pointer2.move(event);
  15929. }
  15930. else
  15931. {
  15932. for (var i = 3; i <= 10; i++)
  15933. {
  15934. if (this['pointer' + i] && this['pointer' + i].active && this['pointer' + i].identifier == event.identifier)
  15935. {
  15936. return this['pointer' + i].move(event);
  15937. }
  15938. }
  15939. }
  15940. return null;
  15941. },
  15942. /**
  15943. * Stops the matching Pointer object, passing in the event data.
  15944. * @method Phaser.Input#stopPointer
  15945. * @param {Any} event - The event data from the Touch event.
  15946. * @return {Phaser.Pointer} The Pointer object that was stopped or null if no Pointer object is available.
  15947. */
  15948. stopPointer: function (event) {
  15949. if (this.pointer1.active && this.pointer1.identifier == event.identifier)
  15950. {
  15951. return this.pointer1.stop(event);
  15952. }
  15953. else if (this.pointer2.active && this.pointer2.identifier == event.identifier)
  15954. {
  15955. return this.pointer2.stop(event);
  15956. }
  15957. else
  15958. {
  15959. for (var i = 3; i <= 10; i++)
  15960. {
  15961. if (this['pointer' + i] && this['pointer' + i].active && this['pointer' + i].identifier == event.identifier)
  15962. {
  15963. return this['pointer' + i].stop(event);
  15964. }
  15965. }
  15966. }
  15967. return null;
  15968. },
  15969. /**
  15970. * Get the next Pointer object whos active property matches the given state
  15971. * @method Phaser.Input#getPointer
  15972. * @param {boolean} state - The state the Pointer should be in (false for inactive, true for active).
  15973. * @return {Phaser.Pointer} A Pointer object or null if no Pointer object matches the requested state.
  15974. */
  15975. getPointer: function (state) {
  15976. state = state || false;
  15977. if (this.pointer1.active == state)
  15978. {
  15979. return this.pointer1;
  15980. }
  15981. else if (this.pointer2.active == state)
  15982. {
  15983. return this.pointer2;
  15984. }
  15985. else
  15986. {
  15987. for (var i = 3; i <= 10; i++)
  15988. {
  15989. if (this['pointer' + i] && this['pointer' + i].active == state)
  15990. {
  15991. return this['pointer' + i];
  15992. }
  15993. }
  15994. }
  15995. return null;
  15996. },
  15997. /**
  15998. * Get the Pointer object whos identified property matches the given identifier value.
  15999. * @method Phaser.Input#getPointerFromIdentifier
  16000. * @param {number} identifier - The Pointer.identifier value to search for.
  16001. * @return {Phaser.Pointer} A Pointer object or null if no Pointer object matches the requested identifier.
  16002. */
  16003. getPointerFromIdentifier: function (identifier) {
  16004. if (this.pointer1.identifier == identifier)
  16005. {
  16006. return this.pointer1;
  16007. }
  16008. else if (this.pointer2.identifier == identifier)
  16009. {
  16010. return this.pointer2;
  16011. }
  16012. else
  16013. {
  16014. for (var i = 3; i <= 10; i++)
  16015. {
  16016. if (this['pointer' + i] && this['pointer' + i].identifier == identifier)
  16017. {
  16018. return this['pointer' + i];
  16019. }
  16020. }
  16021. }
  16022. return null;
  16023. },
  16024. /**
  16025. * This will return the local coordinates of the specified displayObject based on the given Pointer.
  16026. * @method Phaser.Input#getLocalPosition
  16027. * @param {Phaser.Sprite|Phaser.Image} displayObject - The DisplayObject to get the local coordinates for.
  16028. * @param {Phaser.Pointer} pointer - The Pointer to use in the check against the displayObject.
  16029. * @return {Phaser.Point} A point containing the coordinates of the Pointer position relative to the DisplayObject.
  16030. */
  16031. getLocalPosition: function (displayObject, pointer, output) {
  16032. if (typeof output === 'undefined') { output = new Phaser.Point(); }
  16033. var wt = displayObject.worldTransform;
  16034. var id = 1 / (wt.a * wt.d + wt.b * -wt.c);
  16035. return output.setTo(
  16036. wt.d * id * pointer.x + -wt.b * id * pointer.y + (wt.ty * wt.b - wt.tx * wt.d) * id,
  16037. wt.a * id * pointer.y + -wt.c * id * pointer.x + (-wt.ty * wt.a + wt.tx * wt.c) * id
  16038. );
  16039. },
  16040. /**
  16041. * Tests if the pointer hits the given object.
  16042. *
  16043. * @method Phaser.Input#hitTest
  16044. * @param {DisplayObject} displayObject - The displayObject to test for a hit.
  16045. * @param {Phaser.Pointer} pointer - The pointer to use for the test.
  16046. * @param {Phaser.Point} localPoint - The local translated point.
  16047. */
  16048. hitTest: function (displayObject, pointer, localPoint) {
  16049. if (!displayObject.worldVisible)
  16050. {
  16051. return false;
  16052. }
  16053. this.getLocalPosition(displayObject, pointer, this._localPoint);
  16054. localPoint.copyFrom(this._localPoint);
  16055. if (displayObject.hitArea && displayObject.hitArea.contains)
  16056. {
  16057. if (displayObject.hitArea.contains(this._localPoint.x, this._localPoint.y))
  16058. {
  16059. return true;
  16060. }
  16061. return false;
  16062. }
  16063. else if (displayObject instanceof Phaser.TileSprite)
  16064. {
  16065. var width = displayObject.width;
  16066. var height = displayObject.height;
  16067. var x1 = -width * displayObject.anchor.x;
  16068. if (this._localPoint.x > x1 && this._localPoint.x < x1 + width)
  16069. {
  16070. var y1 = -height * displayObject.anchor.y;
  16071. if (this._localPoint.y > y1 && this._localPoint.y < y1 + height)
  16072. {
  16073. return true;
  16074. }
  16075. }
  16076. }
  16077. else if (displayObject instanceof PIXI.Sprite)
  16078. {
  16079. var width = displayObject.texture.frame.width;
  16080. var height = displayObject.texture.frame.height;
  16081. var x1 = -width * displayObject.anchor.x;
  16082. if (this._localPoint.x > x1 && this._localPoint.x < x1 + width)
  16083. {
  16084. var y1 = -height * displayObject.anchor.y;
  16085. if (this._localPoint.y > y1 && this._localPoint.y < y1 + height)
  16086. {
  16087. return true;
  16088. }
  16089. }
  16090. }
  16091. for (var i = 0, len = displayObject.children.length; i < len; i++)
  16092. {
  16093. if (this.hitTest(displayObject.children[i], pointer, localPoint))
  16094. {
  16095. return true;
  16096. }
  16097. }
  16098. return false;
  16099. }
  16100. };
  16101. Phaser.Input.prototype.constructor = Phaser.Input;
  16102. /**
  16103. * The X coordinate of the most recently active pointer. This value takes game scaling into account automatically. See Pointer.screenX/clientX for source values.
  16104. * @name Phaser.Input#x
  16105. * @property {number} x - The X coordinate of the most recently active pointer.
  16106. */
  16107. Object.defineProperty(Phaser.Input.prototype, "x", {
  16108. get: function () {
  16109. return this._x;
  16110. },
  16111. set: function (value) {
  16112. this._x = Math.floor(value);
  16113. }
  16114. });
  16115. /**
  16116. * The Y coordinate of the most recently active pointer. This value takes game scaling into account automatically. See Pointer.screenY/clientY for source values.
  16117. * @name Phaser.Input#y
  16118. * @property {number} y - The Y coordinate of the most recently active pointer.
  16119. */
  16120. Object.defineProperty(Phaser.Input.prototype, "y", {
  16121. get: function () {
  16122. return this._y;
  16123. },
  16124. set: function (value) {
  16125. this._y = Math.floor(value);
  16126. }
  16127. });
  16128. /**
  16129. * @name Phaser.Input#pollLocked
  16130. * @property {boolean} pollLocked - True if the Input is currently poll rate locked.
  16131. * @readonly
  16132. */
  16133. Object.defineProperty(Phaser.Input.prototype, "pollLocked", {
  16134. get: function () {
  16135. return (this.pollRate > 0 && this._pollCounter < this.pollRate);
  16136. }
  16137. });
  16138. /**
  16139. * The total number of inactive Pointers
  16140. * @name Phaser.Input#totalInactivePointers
  16141. * @property {number} totalInactivePointers - The total number of inactive Pointers.
  16142. * @readonly
  16143. */
  16144. Object.defineProperty(Phaser.Input.prototype, "totalInactivePointers", {
  16145. get: function () {
  16146. return 10 - this.currentPointers;
  16147. }
  16148. });
  16149. /**
  16150. * The total number of active Pointers
  16151. * @name Phaser.Input#totalActivePointers
  16152. * @property {number} totalActivePointers - The total number of active Pointers.
  16153. * @readonly
  16154. */
  16155. Object.defineProperty(Phaser.Input.prototype, "totalActivePointers", {
  16156. get: function () {
  16157. this.currentPointers = 0;
  16158. for (var i = 1; i <= 10; i++)
  16159. {
  16160. if (this['pointer' + i] && this['pointer' + i].active)
  16161. {
  16162. this.currentPointers++;
  16163. }
  16164. }
  16165. return this.currentPointers;
  16166. }
  16167. });
  16168. /**
  16169. * The world X coordinate of the most recently active pointer.
  16170. * @name Phaser.Input#worldX
  16171. * @property {number} worldX - The world X coordinate of the most recently active pointer.
  16172. */
  16173. Object.defineProperty(Phaser.Input.prototype, "worldX", {
  16174. get: function () {
  16175. return this.game.camera.view.x + this.x;
  16176. }
  16177. });
  16178. /**
  16179. * The world Y coordinate of the most recently active pointer.
  16180. * @name Phaser.Input#worldY
  16181. * @property {number} worldY - The world Y coordinate of the most recently active pointer.
  16182. */
  16183. Object.defineProperty(Phaser.Input.prototype, "worldY", {
  16184. get: function () {
  16185. return this.game.camera.view.y + this.y;
  16186. }
  16187. });
  16188. /**
  16189. * @author Richard Davey <rich@photonstorm.com>
  16190. * @copyright 2014 Photon Storm Ltd.
  16191. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  16192. */
  16193. /**
  16194. * @class Phaser.Key
  16195. * @classdesc If you need more fine-grained control over the handling of specific keys you can create and use Phaser.Key objects.
  16196. * @constructor
  16197. * @param {Phaser.Game} game - Current game instance.
  16198. * @param {number} keycode - The key code this Key is responsible for.
  16199. */
  16200. Phaser.Key = function (game, keycode) {
  16201. /**
  16202. * @property {Phaser.Game} game - A reference to the currently running game.
  16203. */
  16204. this.game = game;
  16205. /**
  16206. * @property {boolean} enabled - An enabled key processes its update and dispatches events. You can toggle this at run-time to disable a key without deleting it.
  16207. * @default
  16208. */
  16209. this.enabled = true;
  16210. /**
  16211. * @property {object} event - Stores the most recent DOM event.
  16212. * @readonly
  16213. */
  16214. this.event = null;
  16215. /**
  16216. * @property {boolean} isDown - The "down" state of the key.
  16217. * @default
  16218. */
  16219. this.isDown = false;
  16220. /**
  16221. * @property {boolean} isUp - The "up" state of the key.
  16222. * @default
  16223. */
  16224. this.isUp = true;
  16225. /**
  16226. * @property {boolean} altKey - The down state of the ALT key, if pressed at the same time as this key.
  16227. * @default
  16228. */
  16229. this.altKey = false;
  16230. /**
  16231. * @property {boolean} ctrlKey - The down state of the CTRL key, if pressed at the same time as this key.
  16232. * @default
  16233. */
  16234. this.ctrlKey = false;
  16235. /**
  16236. * @property {boolean} shiftKey - The down state of the SHIFT key, if pressed at the same time as this key.
  16237. * @default
  16238. */
  16239. this.shiftKey = false;
  16240. /**
  16241. * @property {number} timeDown - The timestamp when the key was last pressed down. This is based on Game.time.now.
  16242. */
  16243. this.timeDown = 0;
  16244. /**
  16245. * If the key is down this value holds the duration of that key press and is constantly updated.
  16246. * If the key is up it holds the duration of the previous down session.
  16247. * @property {number} duration - The number of milliseconds this key has been held down for.
  16248. * @default
  16249. */
  16250. this.duration = 0;
  16251. /**
  16252. * @property {number} timeUp - The timestamp when the key was last released. This is based on Game.time.now.
  16253. * @default
  16254. */
  16255. this.timeUp = -2500;
  16256. /**
  16257. * @property {number} repeats - If a key is held down this holds down the number of times the key has 'repeated'.
  16258. * @default
  16259. */
  16260. this.repeats = 0;
  16261. /**
  16262. * @property {number} keyCode - The keycode of this key.
  16263. */
  16264. this.keyCode = keycode;
  16265. /**
  16266. * @property {Phaser.Signal} onDown - This Signal is dispatched every time this Key is pressed down. It is only dispatched once (until the key is released again).
  16267. */
  16268. this.onDown = new Phaser.Signal();
  16269. /**
  16270. * @property {function} onHoldCallback - A callback that is called while this Key is held down. Warning: Depending on refresh rate that could be 60+ times per second.
  16271. */
  16272. this.onHoldCallback = null;
  16273. /**
  16274. * @property {object} onHoldContext - The context under which the onHoldCallback will be called.
  16275. */
  16276. this.onHoldContext = null;
  16277. /**
  16278. * @property {Phaser.Signal} onUp - This Signal is dispatched every time this Key is pressed down. It is only dispatched once (until the key is released again).
  16279. */
  16280. this.onUp = new Phaser.Signal();
  16281. };
  16282. Phaser.Key.prototype = {
  16283. update: function () {
  16284. if (!this.enabled) { return; }
  16285. if (this.isDown)
  16286. {
  16287. this.duration = this.game.time.now - this.timeDown;
  16288. this.repeats++;
  16289. if (this.onHoldCallback)
  16290. {
  16291. this.onHoldCallback.call(this.onHoldContext, this);
  16292. }
  16293. }
  16294. },
  16295. /**
  16296. * Called automatically by Phaser.Keyboard.
  16297. * @method Phaser.Key#processKeyDown
  16298. * @param {KeyboardEvent} event.
  16299. * @protected
  16300. */
  16301. processKeyDown: function (event) {
  16302. if (!this.enabled) { return; }
  16303. this.event = event;
  16304. if (this.isDown)
  16305. {
  16306. return;
  16307. }
  16308. this.altKey = event.altKey;
  16309. this.ctrlKey = event.ctrlKey;
  16310. this.shiftKey = event.shiftKey;
  16311. this.isDown = true;
  16312. this.isUp = false;
  16313. this.timeDown = this.game.time.now;
  16314. this.duration = 0;
  16315. this.repeats = 0;
  16316. this.onDown.dispatch(this);
  16317. },
  16318. /**
  16319. * Called automatically by Phaser.Keyboard.
  16320. * @method Phaser.Key#processKeyUp
  16321. * @param {KeyboardEvent} event.
  16322. * @protected
  16323. */
  16324. processKeyUp: function (event) {
  16325. if (!this.enabled) { return; }
  16326. this.event = event;
  16327. if (this.isUp)
  16328. {
  16329. return;
  16330. }
  16331. this.isDown = false;
  16332. this.isUp = true;
  16333. this.timeUp = this.game.time.now;
  16334. this.duration = this.game.time.now - this.timeDown;
  16335. this.onUp.dispatch(this);
  16336. },
  16337. /**
  16338. * Resets the state of this Key. This sets isDown to false, isUp to true, resets the time to be the current time and clears any callbacks
  16339. * associated with the onDown and onUp events and nulls the onHoldCallback if set.
  16340. *
  16341. * @method Phaser.Key#reset
  16342. */
  16343. reset: function () {
  16344. this.isDown = false;
  16345. this.isUp = true;
  16346. this.timeUp = this.game.time.now;
  16347. this.duration = this.game.time.now - this.timeDown;
  16348. this.enabled = true;
  16349. this.onDown.removeAll();
  16350. this.onUp.removeAll();
  16351. this.onHoldCallback = null;
  16352. this.onHoldContext = null;
  16353. },
  16354. /**
  16355. * Returns the "just pressed" state of the Key. Just pressed is considered true if the key was pressed down within the duration given (default 250ms)
  16356. * @method Phaser.Key#justPressed
  16357. * @param {number} [duration=250] - The duration below which the key is considered as being just pressed.
  16358. * @return {boolean} True if the key is just pressed otherwise false.
  16359. */
  16360. justPressed: function (duration) {
  16361. if (typeof duration === "undefined") { duration = 2500; }
  16362. return (this.isDown && this.duration < duration);
  16363. },
  16364. /**
  16365. * Returns the "just released" state of the Key. Just released is considered as being true if the key was released within the duration given (default 250ms)
  16366. * @method Phaser.Key#justReleased
  16367. * @param {number} [duration=250] - The duration below which the key is considered as being just released.
  16368. * @return {boolean} True if the key is just released otherwise false.
  16369. */
  16370. justReleased: function (duration) {
  16371. if (typeof duration === "undefined") { duration = 2500; }
  16372. return (!this.isDown && ((this.game.time.now - this.timeUp) < duration));
  16373. }
  16374. };
  16375. Phaser.Key.prototype.constructor = Phaser.Key;
  16376. /**
  16377. * @author Richard Davey <rich@photonstorm.com>
  16378. * @copyright 2014 Photon Storm Ltd.
  16379. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  16380. */
  16381. /**
  16382. * The Keyboard class handles looking after keyboard input for your game. It will recognise and respond to key presses and dispatch the required events.
  16383. *
  16384. * @class Phaser.Keyboard
  16385. * @constructor
  16386. * @param {Phaser.Game} game - A reference to the currently running game.
  16387. */
  16388. Phaser.Keyboard = function (game) {
  16389. /**
  16390. * @property {Phaser.Game} game - Local reference to game.
  16391. */
  16392. this.game = game;
  16393. /**
  16394. * You can disable all Keyboard Input by setting disabled to true. While true all new input related events will be ignored.
  16395. * @property {boolean} disabled - The disabled state of the Keyboard.
  16396. * @default
  16397. */
  16398. this.disabled = false;
  16399. /**
  16400. * @property {Object} event - The most recent DOM event. This is updated every time a new key is pressed or released.
  16401. */
  16402. this.event = null;
  16403. /**
  16404. * @property {Object} callbackContext - The context under which the callbacks are run.
  16405. */
  16406. this.callbackContext = this;
  16407. /**
  16408. * @property {function} onDownCallback - This callback is invoked every time a key is pressed down.
  16409. */
  16410. this.onDownCallback = null;
  16411. /**
  16412. * @property {function} onUpCallback - This callback is invoked every time a key is released.
  16413. */
  16414. this.onUpCallback = null;
  16415. /**
  16416. * @property {array<Phaser.Key>} _keys - The array the Phaser.Key objects are stored in.
  16417. * @private
  16418. */
  16419. this._keys = [];
  16420. /**
  16421. * @property {array} _capture - The array the key capture values are stored in.
  16422. * @private
  16423. */
  16424. this._capture = [];
  16425. /**
  16426. * @property {function} _onKeyDown
  16427. * @private
  16428. * @default
  16429. */
  16430. this._onKeyDown = null;
  16431. /**
  16432. * @property {function} _onKeyUp
  16433. * @private
  16434. * @default
  16435. */
  16436. this._onKeyUp = null;
  16437. /**
  16438. * @property {number} _i - Internal cache var
  16439. * @private
  16440. */
  16441. this._i = 0;
  16442. };
  16443. Phaser.Keyboard.prototype = {
  16444. /**
  16445. * Add callbacks to the Keyboard handler so that each time a key is pressed down or released the callbacks are activated.
  16446. *
  16447. * @method Phaser.Keyboard#addCallbacks
  16448. * @param {Object} context - The context under which the callbacks are run.
  16449. * @param {function} onDown - This callback is invoked every time a key is pressed down.
  16450. * @param {function} [onUp=null] - This callback is invoked every time a key is released.
  16451. */
  16452. addCallbacks: function (context, onDown, onUp) {
  16453. this.callbackContext = context;
  16454. this.onDownCallback = onDown;
  16455. if (typeof onUp !== 'undefined')
  16456. {
  16457. this.onUpCallback = onUp;
  16458. }
  16459. },
  16460. /**
  16461. * If you need more fine-grained control over a Key you can create a new Phaser.Key object via this method.
  16462. * The Key object can then be polled, have events attached to it, etc.
  16463. *
  16464. * @method Phaser.Keyboard#addKey
  16465. * @param {number} keycode - The keycode of the key, i.e. Phaser.Keyboard.UP or Phaser.Keyboard.SPACEBAR
  16466. * @return {Phaser.Key} The Key object which you can store locally and reference directly.
  16467. */
  16468. addKey: function (keycode) {
  16469. if (!this._keys[keycode])
  16470. {
  16471. this._keys[keycode] = new Phaser.Key(this.game, keycode);
  16472. this.addKeyCapture(keycode);
  16473. }
  16474. return this._keys[keycode];
  16475. },
  16476. /**
  16477. * Removes a Key object from the Keyboard manager.
  16478. *
  16479. * @method Phaser.Keyboard#removeKey
  16480. * @param {number} keycode - The keycode of the key to remove, i.e. Phaser.Keyboard.UP or Phaser.Keyboard.SPACEBAR
  16481. */
  16482. removeKey: function (keycode) {
  16483. if (this._keys[keycode])
  16484. {
  16485. this._keys[keycode] = null;
  16486. this.removeKeyCapture(keycode);
  16487. }
  16488. },
  16489. /**
  16490. * Creates and returns an object containing 4 hotkeys for Up, Down, Left and Right.
  16491. *
  16492. * @method Phaser.Keyboard#createCursorKeys
  16493. * @return {object} An object containing properties: up, down, left and right. Which can be polled like any other Phaser.Key object.
  16494. */
  16495. createCursorKeys: function () {
  16496. return {
  16497. up: this.addKey(Phaser.Keyboard.UP),
  16498. down: this.addKey(Phaser.Keyboard.DOWN),
  16499. left: this.addKey(Phaser.Keyboard.LEFT),
  16500. right: this.addKey(Phaser.Keyboard.RIGHT)
  16501. };
  16502. },
  16503. /**
  16504. * Starts the Keyboard event listeners running (keydown and keyup). They are attached to the window.
  16505. * This is called automatically by Phaser.Input and should not normally be invoked directly.
  16506. *
  16507. * @method Phaser.Keyboard#start
  16508. */
  16509. start: function () {
  16510. if (this._onKeyDown !== null)
  16511. {
  16512. // Avoid setting multiple listeners
  16513. return;
  16514. }
  16515. var _this = this;
  16516. this._onKeyDown = function (event) {
  16517. return _this.processKeyDown(event);
  16518. };
  16519. this._onKeyUp = function (event) {
  16520. return _this.processKeyUp(event);
  16521. };
  16522. window.addEventListener('keydown', this._onKeyDown, false);
  16523. window.addEventListener('keyup', this._onKeyUp, false);
  16524. },
  16525. /**
  16526. * Stops the Keyboard event listeners from running (keydown and keyup). They are removed from the window.
  16527. *
  16528. * @method Phaser.Keyboard#stop
  16529. */
  16530. stop: function () {
  16531. window.removeEventListener('keydown', this._onKeyDown);
  16532. window.removeEventListener('keyup', this._onKeyUp);
  16533. this._onKeyDown = null;
  16534. this._onKeyUp = null;
  16535. },
  16536. /**
  16537. * Stops the Keyboard event listeners from running (keydown and keyup). They are removed from the window.
  16538. * Also clears all key captures and currently created Key objects.
  16539. *
  16540. * @method Phaser.Keyboard#destroy
  16541. */
  16542. destroy: function () {
  16543. this.stop();
  16544. this.clearCaptures();
  16545. this._keys.length = 0;
  16546. this._i = 0;
  16547. },
  16548. /**
  16549. * By default when a key is pressed Phaser will not stop the event from propagating up to the browser.
  16550. * There are some keys this can be annoying for, like the arrow keys or space bar, which make the browser window scroll.
  16551. * You can use addKeyCapture to consume the keyboard event for specific keys so it doesn't bubble up to the the browser.
  16552. * Pass in either a single keycode or an array/hash of keycodes.
  16553. *
  16554. * @method Phaser.Keyboard#addKeyCapture
  16555. * @param {Any} keycode - Either a single numeric keycode or an array/hash of keycodes: [65, 67, 68].
  16556. */
  16557. addKeyCapture: function (keycode) {
  16558. if (typeof keycode === 'object')
  16559. {
  16560. for (var key in keycode)
  16561. {
  16562. this._capture[keycode[key]] = true;
  16563. }
  16564. }
  16565. else
  16566. {
  16567. this._capture[keycode] = true;
  16568. }
  16569. },
  16570. /**
  16571. * Removes an existing key capture.
  16572. *
  16573. * @method Phaser.Keyboard#removeKeyCapture
  16574. * @param {number} keycode
  16575. */
  16576. removeKeyCapture: function (keycode) {
  16577. delete this._capture[keycode];
  16578. },
  16579. /**
  16580. * Clear all set key captures.
  16581. *
  16582. * @method Phaser.Keyboard#clearCaptures
  16583. */
  16584. clearCaptures: function () {
  16585. this._capture = {};
  16586. },
  16587. /**
  16588. * Updates all currently defined keys.
  16589. *
  16590. * @method Phaser.Keyboard#update
  16591. */
  16592. update: function () {
  16593. this._i = this._keys.length;
  16594. while (this._i--)
  16595. {
  16596. if (this._keys[this._i])
  16597. {
  16598. this._keys[this._i].update();
  16599. }
  16600. }
  16601. },
  16602. /**
  16603. * Process the keydown event.
  16604. *
  16605. * @method Phaser.Keyboard#processKeyDown
  16606. * @param {KeyboardEvent} event
  16607. * @protected
  16608. */
  16609. processKeyDown: function (event) {
  16610. this.event = event;
  16611. if (this.game.input.disabled || this.disabled)
  16612. {
  16613. return;
  16614. }
  16615. // The event is being captured but another hotkey may need it
  16616. if (this._capture[event.keyCode])
  16617. {
  16618. event.preventDefault();
  16619. }
  16620. if (this.onDownCallback)
  16621. {
  16622. this.onDownCallback.call(this.callbackContext, event);
  16623. }
  16624. if (!this._keys[event.keyCode])
  16625. {
  16626. this._keys[event.keyCode] = new Phaser.Key(this.game, event.keyCode);
  16627. }
  16628. this._keys[event.keyCode].processKeyDown(event);
  16629. },
  16630. /**
  16631. * Process the keyup event.
  16632. *
  16633. * @method Phaser.Keyboard#processKeyUp
  16634. * @param {KeyboardEvent} event
  16635. * @protected
  16636. */
  16637. processKeyUp: function (event) {
  16638. this.event = event;
  16639. if (this.game.input.disabled || this.disabled)
  16640. {
  16641. return;
  16642. }
  16643. if (this._capture[event.keyCode])
  16644. {
  16645. event.preventDefault();
  16646. }
  16647. if (this.onUpCallback)
  16648. {
  16649. this.onUpCallback.call(this.callbackContext, event);
  16650. }
  16651. if (!this._keys[event.keyCode])
  16652. {
  16653. this._keys[event.keyCode] = new Phaser.Key(this.game, event.keyCode);
  16654. }
  16655. this._keys[event.keyCode].processKeyUp(event);
  16656. },
  16657. /**
  16658. * Resets all Keys.
  16659. *
  16660. * @method Phaser.Keyboard#reset
  16661. */
  16662. reset: function () {
  16663. this.event = null;
  16664. var i = this._keys.length;
  16665. while (i--)
  16666. {
  16667. if (this._keys[i])
  16668. {
  16669. this._keys[i].reset();
  16670. }
  16671. }
  16672. },
  16673. /**
  16674. * Returns the "just pressed" state of the key. Just pressed is considered true if the key was pressed down within the duration given (default 250ms)
  16675. *
  16676. * @method Phaser.Keyboard#justPressed
  16677. * @param {number} keycode - The keycode of the key to remove, i.e. Phaser.Keyboard.UP or Phaser.Keyboard.SPACEBAR
  16678. * @param {number} [duration=250] - The duration below which the key is considered as being just pressed.
  16679. * @return {boolean} True if the key is just pressed otherwise false.
  16680. */
  16681. justPressed: function (keycode, duration) {
  16682. if (this._keys[keycode])
  16683. {
  16684. return this._keys[keycode].justPressed(duration);
  16685. }
  16686. else
  16687. {
  16688. return false;
  16689. }
  16690. },
  16691. /**
  16692. * Returns the "just released" state of the Key. Just released is considered as being true if the key was released within the duration given (default 250ms)
  16693. *
  16694. * @method Phaser.Keyboard#justReleased
  16695. * @param {number} keycode - The keycode of the key to remove, i.e. Phaser.Keyboard.UP or Phaser.Keyboard.SPACEBAR
  16696. * @param {number} [duration=250] - The duration below which the key is considered as being just released.
  16697. * @return {boolean} True if the key is just released otherwise false.
  16698. */
  16699. justReleased: function (keycode, duration) {
  16700. if (this._keys[keycode])
  16701. {
  16702. return this._keys[keycode].justReleased(duration);
  16703. }
  16704. else
  16705. {
  16706. return false;
  16707. }
  16708. },
  16709. /**
  16710. * Returns true of the key is currently pressed down. Note that it can only detect key presses on the web browser.
  16711. *
  16712. * @method Phaser.Keyboard#isDown
  16713. * @param {number} keycode - The keycode of the key to remove, i.e. Phaser.Keyboard.UP or Phaser.Keyboard.SPACEBAR
  16714. * @return {boolean} True if the key is currently down.
  16715. */
  16716. isDown: function (keycode) {
  16717. if (this._keys[keycode])
  16718. {
  16719. return this._keys[keycode].isDown;
  16720. }
  16721. return false;
  16722. }
  16723. };
  16724. Phaser.Keyboard.prototype.constructor = Phaser.Keyboard;
  16725. Phaser.Keyboard.A = "A".charCodeAt(0);
  16726. Phaser.Keyboard.B = "B".charCodeAt(0);
  16727. Phaser.Keyboard.C = "C".charCodeAt(0);
  16728. Phaser.Keyboard.D = "D".charCodeAt(0);
  16729. Phaser.Keyboard.E = "E".charCodeAt(0);
  16730. Phaser.Keyboard.F = "F".charCodeAt(0);
  16731. Phaser.Keyboard.G = "G".charCodeAt(0);
  16732. Phaser.Keyboard.H = "H".charCodeAt(0);
  16733. Phaser.Keyboard.I = "I".charCodeAt(0);
  16734. Phaser.Keyboard.J = "J".charCodeAt(0);
  16735. Phaser.Keyboard.K = "K".charCodeAt(0);
  16736. Phaser.Keyboard.L = "L".charCodeAt(0);
  16737. Phaser.Keyboard.M = "M".charCodeAt(0);
  16738. Phaser.Keyboard.N = "N".charCodeAt(0);
  16739. Phaser.Keyboard.O = "O".charCodeAt(0);
  16740. Phaser.Keyboard.P = "P".charCodeAt(0);
  16741. Phaser.Keyboard.Q = "Q".charCodeAt(0);
  16742. Phaser.Keyboard.R = "R".charCodeAt(0);
  16743. Phaser.Keyboard.S = "S".charCodeAt(0);
  16744. Phaser.Keyboard.T = "T".charCodeAt(0);
  16745. Phaser.Keyboard.U = "U".charCodeAt(0);
  16746. Phaser.Keyboard.V = "V".charCodeAt(0);
  16747. Phaser.Keyboard.W = "W".charCodeAt(0);
  16748. Phaser.Keyboard.X = "X".charCodeAt(0);
  16749. Phaser.Keyboard.Y = "Y".charCodeAt(0);
  16750. Phaser.Keyboard.Z = "Z".charCodeAt(0);
  16751. Phaser.Keyboard.ZERO = "0".charCodeAt(0);
  16752. Phaser.Keyboard.ONE = "1".charCodeAt(0);
  16753. Phaser.Keyboard.TWO = "2".charCodeAt(0);
  16754. Phaser.Keyboard.THREE = "3".charCodeAt(0);
  16755. Phaser.Keyboard.FOUR = "4".charCodeAt(0);
  16756. Phaser.Keyboard.FIVE = "5".charCodeAt(0);
  16757. Phaser.Keyboard.SIX = "6".charCodeAt(0);
  16758. Phaser.Keyboard.SEVEN = "7".charCodeAt(0);
  16759. Phaser.Keyboard.EIGHT = "8".charCodeAt(0);
  16760. Phaser.Keyboard.NINE = "9".charCodeAt(0);
  16761. Phaser.Keyboard.NUMPAD_0 = 96;
  16762. Phaser.Keyboard.NUMPAD_1 = 97;
  16763. Phaser.Keyboard.NUMPAD_2 = 98;
  16764. Phaser.Keyboard.NUMPAD_3 = 99;
  16765. Phaser.Keyboard.NUMPAD_4 = 100;
  16766. Phaser.Keyboard.NUMPAD_5 = 101;
  16767. Phaser.Keyboard.NUMPAD_6 = 102;
  16768. Phaser.Keyboard.NUMPAD_7 = 103;
  16769. Phaser.Keyboard.NUMPAD_8 = 104;
  16770. Phaser.Keyboard.NUMPAD_9 = 105;
  16771. Phaser.Keyboard.NUMPAD_MULTIPLY = 106;
  16772. Phaser.Keyboard.NUMPAD_ADD = 107;
  16773. Phaser.Keyboard.NUMPAD_ENTER = 108;
  16774. Phaser.Keyboard.NUMPAD_SUBTRACT = 109;
  16775. Phaser.Keyboard.NUMPAD_DECIMAL = 110;
  16776. Phaser.Keyboard.NUMPAD_DIVIDE = 111;
  16777. Phaser.Keyboard.F1 = 112;
  16778. Phaser.Keyboard.F2 = 113;
  16779. Phaser.Keyboard.F3 = 114;
  16780. Phaser.Keyboard.F4 = 115;
  16781. Phaser.Keyboard.F5 = 116;
  16782. Phaser.Keyboard.F6 = 117;
  16783. Phaser.Keyboard.F7 = 118;
  16784. Phaser.Keyboard.F8 = 119;
  16785. Phaser.Keyboard.F9 = 120;
  16786. Phaser.Keyboard.F10 = 121;
  16787. Phaser.Keyboard.F11 = 122;
  16788. Phaser.Keyboard.F12 = 123;
  16789. Phaser.Keyboard.F13 = 124;
  16790. Phaser.Keyboard.F14 = 125;
  16791. Phaser.Keyboard.F15 = 126;
  16792. Phaser.Keyboard.COLON = 186;
  16793. Phaser.Keyboard.EQUALS = 187;
  16794. Phaser.Keyboard.UNDERSCORE = 189;
  16795. Phaser.Keyboard.QUESTION_MARK = 191;
  16796. Phaser.Keyboard.TILDE = 192;
  16797. Phaser.Keyboard.OPEN_BRACKET = 219;
  16798. Phaser.Keyboard.BACKWARD_SLASH = 220;
  16799. Phaser.Keyboard.CLOSED_BRACKET = 221;
  16800. Phaser.Keyboard.QUOTES = 222;
  16801. Phaser.Keyboard.BACKSPACE = 8;
  16802. Phaser.Keyboard.TAB = 9;
  16803. Phaser.Keyboard.CLEAR = 12;
  16804. Phaser.Keyboard.ENTER = 13;
  16805. Phaser.Keyboard.SHIFT = 16;
  16806. Phaser.Keyboard.CONTROL = 17;
  16807. Phaser.Keyboard.ALT = 18;
  16808. Phaser.Keyboard.CAPS_LOCK = 20;
  16809. Phaser.Keyboard.ESC = 27;
  16810. Phaser.Keyboard.SPACEBAR = 32;
  16811. Phaser.Keyboard.PAGE_UP = 33;
  16812. Phaser.Keyboard.PAGE_DOWN = 34;
  16813. Phaser.Keyboard.END = 35;
  16814. Phaser.Keyboard.HOME = 36;
  16815. Phaser.Keyboard.LEFT = 37;
  16816. Phaser.Keyboard.UP = 38;
  16817. Phaser.Keyboard.RIGHT = 39;
  16818. Phaser.Keyboard.DOWN = 40;
  16819. Phaser.Keyboard.INSERT = 45;
  16820. Phaser.Keyboard.DELETE = 46;
  16821. Phaser.Keyboard.HELP = 47;
  16822. Phaser.Keyboard.NUM_LOCK = 144;
  16823. /**
  16824. * @author Richard Davey <rich@photonstorm.com>
  16825. * @copyright 2014 Photon Storm Ltd.
  16826. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  16827. */
  16828. /**
  16829. * Phaser.Mouse is responsible for handling all aspects of mouse interaction with the browser. It captures and processes mouse events.
  16830. *
  16831. * @class Phaser.Mouse
  16832. * @constructor
  16833. * @param {Phaser.Game} game - A reference to the currently running game.
  16834. */
  16835. Phaser.Mouse = function (game) {
  16836. /**
  16837. * @property {Phaser.Game} game - A reference to the currently running game.
  16838. */
  16839. this.game = game;
  16840. /**
  16841. * @property {Object} callbackContext - The context under which callbacks are called.
  16842. */
  16843. this.callbackContext = this.game;
  16844. /**
  16845. * @property {function} mouseDownCallback - A callback that can be fired when the mouse is pressed down.
  16846. */
  16847. this.mouseDownCallback = null;
  16848. /**
  16849. * @property {function} mouseMoveCallback - A callback that can be fired when the mouse is moved while pressed down.
  16850. */
  16851. this.mouseMoveCallback = null;
  16852. /**
  16853. * @property {function} mouseUpCallback - A callback that can be fired when the mouse is released from a pressed down state.
  16854. */
  16855. this.mouseUpCallback = null;
  16856. /**
  16857. * @property {boolean} capture - If true the DOM mouse events will have event.preventDefault applied to them, if false they will propogate fully.
  16858. */
  16859. this.capture = false;
  16860. /**
  16861. * @property {number} button- The type of click, either: Phaser.Mouse.NO_BUTTON, Phaser.Mouse.LEFT_BUTTON, Phaser.Mouse.MIDDLE_BUTTON or Phaser.Mouse.RIGHT_BUTTON.
  16862. * @default
  16863. */
  16864. this.button = -1;
  16865. /**
  16866. * @property {boolean} disabled - You can disable all Input by setting disabled = true. While set all new input related events will be ignored.
  16867. * @default
  16868. */
  16869. this.disabled = false;
  16870. /**
  16871. * @property {boolean} locked - If the mouse has been Pointer Locked successfully this will be set to true.
  16872. * @default
  16873. */
  16874. this.locked = false;
  16875. /**
  16876. * @property {Phaser.Signal} pointerLock - This event is dispatched when the browser enters or leaves pointer lock state.
  16877. * @default
  16878. */
  16879. this.pointerLock = new Phaser.Signal();
  16880. /**
  16881. * @property {MouseEvent} event - The browser mouse DOM event. Will be set to null if no mouse event has ever been received.
  16882. * @default
  16883. */
  16884. this.event = null;
  16885. /**
  16886. * @property {function} _onMouseDown - Internal event handler reference.
  16887. * @private
  16888. */
  16889. this._onMouseDown = null;
  16890. /**
  16891. * @property {function} _onMouseMove - Internal event handler reference.
  16892. * @private
  16893. */
  16894. this._onMouseMove = null;
  16895. /**
  16896. * @property {function} _onMouseUp - Internal event handler reference.
  16897. * @private
  16898. */
  16899. this._onMouseUp = null;
  16900. };
  16901. /**
  16902. * @constant
  16903. * @type {number}
  16904. */
  16905. Phaser.Mouse.NO_BUTTON = -1;
  16906. /**
  16907. * @constant
  16908. * @type {number}
  16909. */
  16910. Phaser.Mouse.LEFT_BUTTON = 0;
  16911. /**
  16912. * @constant
  16913. * @type {number}
  16914. */
  16915. Phaser.Mouse.MIDDLE_BUTTON = 1;
  16916. /**
  16917. * @constant
  16918. * @type {number}
  16919. */
  16920. Phaser.Mouse.RIGHT_BUTTON = 2;
  16921. Phaser.Mouse.prototype = {
  16922. /**
  16923. * Starts the event listeners running.
  16924. * @method Phaser.Mouse#start
  16925. */
  16926. start: function () {
  16927. if (this.game.device.android && this.game.device.chrome === false)
  16928. {
  16929. // Android stock browser fires mouse events even if you preventDefault on the touchStart, so ...
  16930. return;
  16931. }
  16932. if (this._onMouseDown !== null)
  16933. {
  16934. // Avoid setting multiple listeners
  16935. return;
  16936. }
  16937. var _this = this;
  16938. this._onMouseDown = function (event) {
  16939. return _this.onMouseDown(event);
  16940. };
  16941. this._onMouseMove = function (event) {
  16942. return _this.onMouseMove(event);
  16943. };
  16944. this._onMouseUp = function (event) {
  16945. return _this.onMouseUp(event);
  16946. };
  16947. this.game.canvas.addEventListener('mousedown', this._onMouseDown, true);
  16948. this.game.canvas.addEventListener('mousemove', this._onMouseMove, true);
  16949. this.game.canvas.addEventListener('mouseup', this._onMouseUp, true);
  16950. },
  16951. /**
  16952. * The internal method that handles the mouse down event from the browser.
  16953. * @method Phaser.Mouse#onMouseDown
  16954. * @param {MouseEvent} event - The native event from the browser. This gets stored in Mouse.event.
  16955. */
  16956. onMouseDown: function (event) {
  16957. this.event = event;
  16958. if (this.capture)
  16959. {
  16960. event.preventDefault();
  16961. }
  16962. this.button = event.button;
  16963. if (this.mouseDownCallback)
  16964. {
  16965. this.mouseDownCallback.call(this.callbackContext, event);
  16966. }
  16967. if (this.game.input.disabled || this.disabled)
  16968. {
  16969. return;
  16970. }
  16971. event['identifier'] = 0;
  16972. this.game.input.mousePointer.start(event);
  16973. },
  16974. /**
  16975. * The internal method that handles the mouse move event from the browser.
  16976. * @method Phaser.Mouse#onMouseMove
  16977. * @param {MouseEvent} event - The native event from the browser. This gets stored in Mouse.event.
  16978. */
  16979. onMouseMove: function (event) {
  16980. this.event = event;
  16981. if (this.capture)
  16982. {
  16983. event.preventDefault();
  16984. }
  16985. if (this.mouseMoveCallback)
  16986. {
  16987. this.mouseMoveCallback.call(this.callbackContext, event);
  16988. }
  16989. if (this.game.input.disabled || this.disabled)
  16990. {
  16991. return;
  16992. }
  16993. event['identifier'] = 0;
  16994. this.game.input.mousePointer.move(event);
  16995. },
  16996. /**
  16997. * The internal method that handles the mouse up event from the browser.
  16998. * @method Phaser.Mouse#onMouseUp
  16999. * @param {MouseEvent} event - The native event from the browser. This gets stored in Mouse.event.
  17000. */
  17001. onMouseUp: function (event) {
  17002. this.event = event;
  17003. if (this.capture)
  17004. {
  17005. event.preventDefault();
  17006. }
  17007. this.button = Phaser.Mouse.NO_BUTTON;
  17008. if (this.mouseUpCallback)
  17009. {
  17010. this.mouseUpCallback.call(this.callbackContext, event);
  17011. }
  17012. if (this.game.input.disabled || this.disabled)
  17013. {
  17014. return;
  17015. }
  17016. event['identifier'] = 0;
  17017. this.game.input.mousePointer.stop(event);
  17018. },
  17019. /**
  17020. * If the browser supports it you can request that the pointer be locked to the browser window.
  17021. * This is classically known as 'FPS controls', where the pointer can't leave the browser until the user presses an exit key.
  17022. * If the browser successfully enters a locked state the event Phaser.Mouse.pointerLock will be dispatched and the first parameter will be 'true'.
  17023. * @method Phaser.Mouse#requestPointerLock
  17024. */
  17025. requestPointerLock: function () {
  17026. if (this.game.device.pointerLock)
  17027. {
  17028. var element = this.game.canvas;
  17029. element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
  17030. element.requestPointerLock();
  17031. var _this = this;
  17032. this._pointerLockChange = function (event) {
  17033. return _this.pointerLockChange(event);
  17034. };
  17035. document.addEventListener('pointerlockchange', this._pointerLockChange, true);
  17036. document.addEventListener('mozpointerlockchange', this._pointerLockChange, true);
  17037. document.addEventListener('webkitpointerlockchange', this._pointerLockChange, true);
  17038. }
  17039. },
  17040. /**
  17041. * Internal pointerLockChange handler.
  17042. * @method Phaser.Mouse#pointerLockChange
  17043. * @param {pointerlockchange} event - The native event from the browser. This gets stored in Mouse.event.
  17044. */
  17045. pointerLockChange: function (event) {
  17046. var element = this.game.canvas;
  17047. if (document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element)
  17048. {
  17049. // Pointer was successfully locked
  17050. this.locked = true;
  17051. this.pointerLock.dispatch(true, event);
  17052. }
  17053. else
  17054. {
  17055. // Pointer was unlocked
  17056. this.locked = false;
  17057. this.pointerLock.dispatch(false, event);
  17058. }
  17059. },
  17060. /**
  17061. * Internal release pointer lock handler.
  17062. * @method Phaser.Mouse#releasePointerLock
  17063. */
  17064. releasePointerLock: function () {
  17065. document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock;
  17066. document.exitPointerLock();
  17067. document.removeEventListener('pointerlockchange', this._pointerLockChange, true);
  17068. document.removeEventListener('mozpointerlockchange', this._pointerLockChange, true);
  17069. document.removeEventListener('webkitpointerlockchange', this._pointerLockChange, true);
  17070. },
  17071. /**
  17072. * Stop the event listeners.
  17073. * @method Phaser.Mouse#stop
  17074. */
  17075. stop: function () {
  17076. this.game.canvas.removeEventListener('mousedown', this._onMouseDown, true);
  17077. this.game.canvas.removeEventListener('mousemove', this._onMouseMove, true);
  17078. this.game.canvas.removeEventListener('mouseup', this._onMouseUp, true);
  17079. }
  17080. };
  17081. Phaser.Mouse.prototype.constructor = Phaser.Mouse;
  17082. /**
  17083. * @author Richard Davey <rich@photonstorm.com>
  17084. * @copyright 2014 Photon Storm Ltd.
  17085. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  17086. */
  17087. /**
  17088. * Phaser - MSPointer constructor.
  17089. *
  17090. * @class Phaser.MSPointer
  17091. * @classdesc The MSPointer class handles touch interactions with the game and the resulting Pointer objects.
  17092. * It will work only in Internet Explorer 10 and Windows Store or Windows Phone 8 apps using JavaScript.
  17093. * http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx
  17094. * @constructor
  17095. * @param {Phaser.Game} game - A reference to the currently running game.
  17096. */
  17097. Phaser.MSPointer = function (game) {
  17098. /**
  17099. * @property {Phaser.Game} game - A reference to the currently running game.
  17100. */
  17101. this.game = game;
  17102. /**
  17103. * @property {Object} callbackContext - The context under which callbacks are called (defaults to game).
  17104. */
  17105. this.callbackContext = this.game;
  17106. /**
  17107. * You can disable all Input by setting disabled = true. While set all new input related events will be ignored.
  17108. * @property {boolean} disabled
  17109. */
  17110. this.disabled = false;
  17111. /**
  17112. * @property {function} _onMSPointerDown - Internal function to handle MSPointer events.
  17113. * @private
  17114. */
  17115. this._onMSPointerDown = null;
  17116. /**
  17117. * @property {function} _onMSPointerMove - Internal function to handle MSPointer events.
  17118. * @private
  17119. */
  17120. this._onMSPointerMove = null;
  17121. /**
  17122. * @property {function} _onMSPointerUp - Internal function to handle MSPointer events.
  17123. * @private
  17124. */
  17125. this._onMSPointerUp = null;
  17126. };
  17127. Phaser.MSPointer.prototype = {
  17128. /**
  17129. * Starts the event listeners running.
  17130. * @method Phaser.MSPointer#start
  17131. */
  17132. start: function () {
  17133. if (this._onMSPointerDown !== null)
  17134. {
  17135. // Avoid setting multiple listeners
  17136. return;
  17137. }
  17138. var _this = this;
  17139. if (this.game.device.mspointer === true)
  17140. {
  17141. this._onMSPointerDown = function (event) {
  17142. return _this.onPointerDown(event);
  17143. };
  17144. this._onMSPointerMove = function (event) {
  17145. return _this.onPointerMove(event);
  17146. };
  17147. this._onMSPointerUp = function (event) {
  17148. return _this.onPointerUp(event);
  17149. };
  17150. this.game.renderer.view.addEventListener('MSPointerDown', this._onMSPointerDown, false);
  17151. this.game.renderer.view.addEventListener('MSPointerMove', this._onMSPointerMove, false);
  17152. this.game.renderer.view.addEventListener('MSPointerUp', this._onMSPointerUp, false);
  17153. // IE11+ uses non-prefix events
  17154. this.game.renderer.view.addEventListener('pointerDown', this._onMSPointerDown, false);
  17155. this.game.renderer.view.addEventListener('pointerMove', this._onMSPointerMove, false);
  17156. this.game.renderer.view.addEventListener('pointerUp', this._onMSPointerUp, false);
  17157. this.game.renderer.view.style['-ms-content-zooming'] = 'none';
  17158. this.game.renderer.view.style['-ms-touch-action'] = 'none';
  17159. }
  17160. },
  17161. /**
  17162. * The function that handles the PointerDown event.
  17163. * @method Phaser.MSPointer#onPointerDown
  17164. * @param {PointerEvent} event
  17165. */
  17166. onPointerDown: function (event) {
  17167. if (this.game.input.disabled || this.disabled)
  17168. {
  17169. return;
  17170. }
  17171. event.preventDefault();
  17172. event.identifier = event.pointerId;
  17173. this.game.input.startPointer(event);
  17174. },
  17175. /**
  17176. * The function that handles the PointerMove event.
  17177. * @method Phaser.MSPointer#onPointerMove
  17178. * @param {PointerEvent } event
  17179. */
  17180. onPointerMove: function (event) {
  17181. if (this.game.input.disabled || this.disabled)
  17182. {
  17183. return;
  17184. }
  17185. event.preventDefault();
  17186. event.identifier = event.pointerId;
  17187. this.game.input.updatePointer(event);
  17188. },
  17189. /**
  17190. * The function that handles the PointerUp event.
  17191. * @method Phaser.MSPointer#onPointerUp
  17192. * @param {PointerEvent} event
  17193. */
  17194. onPointerUp: function (event) {
  17195. if (this.game.input.disabled || this.disabled)
  17196. {
  17197. return;
  17198. }
  17199. event.preventDefault();
  17200. event.identifier = event.pointerId;
  17201. this.game.input.stopPointer(event);
  17202. },
  17203. /**
  17204. * Stop the event listeners.
  17205. * @method Phaser.MSPointer#stop
  17206. */
  17207. stop: function () {
  17208. this.game.canvas.removeEventListener('MSPointerDown', this._onMSPointerDown);
  17209. this.game.canvas.removeEventListener('MSPointerMove', this._onMSPointerMove);
  17210. this.game.canvas.removeEventListener('MSPointerUp', this._onMSPointerUp);
  17211. this.game.canvas.removeEventListener('pointerDown', this._onMSPointerDown);
  17212. this.game.canvas.removeEventListener('pointerMove', this._onMSPointerMove);
  17213. this.game.canvas.removeEventListener('pointerUp', this._onMSPointerUp);
  17214. }
  17215. };
  17216. Phaser.MSPointer.prototype.constructor = Phaser.MSPointer;
  17217. /**
  17218. * @author Richard Davey <rich@photonstorm.com>
  17219. * @copyright 2014 Photon Storm Ltd.
  17220. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  17221. */
  17222. /**
  17223. * Phaser - Pointer constructor.
  17224. *
  17225. * @class Phaser.Pointer
  17226. * @classdesc A Pointer object is used by the Mouse, Touch and MSPoint managers and represents a single finger on the touch screen.
  17227. * @constructor
  17228. * @param {Phaser.Game} game - A reference to the currently running game.
  17229. * @param {number} id - The ID of the Pointer object within the game. Each game can have up to 10 active pointers.
  17230. */
  17231. Phaser.Pointer = function (game, id) {
  17232. /**
  17233. * @property {Phaser.Game} game - A reference to the currently running game.
  17234. */
  17235. this.game = game;
  17236. /**
  17237. * @property {number} id - The ID of the Pointer object within the game. Each game can have up to 10 active pointers.
  17238. */
  17239. this.id = id;
  17240. /**
  17241. * @property {boolean} _holdSent - Local private variable to store the status of dispatching a hold event.
  17242. * @private
  17243. * @default
  17244. */
  17245. this._holdSent = false;
  17246. /**
  17247. * @property {array} _history - Local private variable storing the short-term history of pointer movements.
  17248. * @private
  17249. */
  17250. this._history = [];
  17251. /**
  17252. * @property {number} _lastDrop - Local private variable storing the time at which the next history drop should occur.
  17253. * @private
  17254. * @default
  17255. */
  17256. this._nextDrop = 0;
  17257. /**
  17258. * @property {boolean} _stateReset - Monitor events outside of a state reset loop.
  17259. * @private
  17260. * @default
  17261. */
  17262. this._stateReset = false;
  17263. /**
  17264. * @property {boolean} withinGame - true if the Pointer is within the game area, otherwise false.
  17265. */
  17266. this.withinGame = false;
  17267. /**
  17268. * @property {number} clientX - The horizontal coordinate of point relative to the viewport in pixels, excluding any scroll offset.
  17269. * @default
  17270. */
  17271. this.clientX = -1;
  17272. /**
  17273. * @property {number} clientY - The vertical coordinate of point relative to the viewport in pixels, excluding any scroll offset.
  17274. * @default
  17275. */
  17276. this.clientY = -1;
  17277. /**
  17278. * @property {number} pageX - The horizontal coordinate of point relative to the viewport in pixels, including any scroll offset.
  17279. * @default
  17280. */
  17281. this.pageX = -1;
  17282. /**
  17283. * @property {number} pageY - The vertical coordinate of point relative to the viewport in pixels, including any scroll offset.
  17284. * @default
  17285. */
  17286. this.pageY = -1;
  17287. /**
  17288. * @property {number} screenX - The horizontal coordinate of point relative to the screen in pixels.
  17289. * @default
  17290. */
  17291. this.screenX = -1;
  17292. /**
  17293. * @property {number} screenY - The vertical coordinate of point relative to the screen in pixels.
  17294. * @default
  17295. */
  17296. this.screenY = -1;
  17297. /**
  17298. * @property {number} x - The horizontal coordinate of point relative to the game element. This value is automatically scaled based on game size.
  17299. * @default
  17300. */
  17301. this.x = -1;
  17302. /**
  17303. * @property {number} y - The vertical coordinate of point relative to the game element. This value is automatically scaled based on game size.
  17304. * @default
  17305. */
  17306. this.y = -1;
  17307. /**
  17308. * @property {boolean} isMouse - If the Pointer is a mouse this is true, otherwise false.
  17309. * @default
  17310. */
  17311. this.isMouse = false;
  17312. /**
  17313. * @property {boolean} isDown - If the Pointer is touching the touchscreen, or the mouse button is held down, isDown is set to true.
  17314. * @default
  17315. */
  17316. this.isDown = false;
  17317. /**
  17318. * @property {boolean} isUp - If the Pointer is not touching the touchscreen, or the mouse button is up, isUp is set to true.
  17319. * @default
  17320. */
  17321. this.isUp = true;
  17322. /**
  17323. * @property {number} timeDown - A timestamp representing when the Pointer first touched the touchscreen.
  17324. * @default
  17325. */
  17326. this.timeDown = 0;
  17327. /**
  17328. * @property {number} timeUp - A timestamp representing when the Pointer left the touchscreen.
  17329. * @default
  17330. */
  17331. this.timeUp = 0;
  17332. /**
  17333. * @property {number} previousTapTime - A timestamp representing when the Pointer was last tapped or clicked.
  17334. * @default
  17335. */
  17336. this.previousTapTime = 0;
  17337. /**
  17338. * @property {number} totalTouches - The total number of times this Pointer has been touched to the touchscreen.
  17339. * @default
  17340. */
  17341. this.totalTouches = 0;
  17342. /**
  17343. * @property {number} msSinceLastClick - The number of miliseconds since the last click.
  17344. * @default
  17345. */
  17346. this.msSinceLastClick = Number.MAX_VALUE;
  17347. /**
  17348. * @property {any} targetObject - The Game Object this Pointer is currently over / touching / dragging.
  17349. * @default
  17350. */
  17351. this.targetObject = null;
  17352. /**
  17353. * @property {boolean} active - An active pointer is one that is currently pressed down on the display. A Mouse is always active.
  17354. * @default
  17355. */
  17356. this.active = false;
  17357. /**
  17358. * @property {Phaser.Point} position - A Phaser.Point object containing the current x/y values of the pointer on the display.
  17359. */
  17360. this.position = new Phaser.Point();
  17361. /**
  17362. * @property {Phaser.Point} positionDown - A Phaser.Point object containing the x/y values of the pointer when it was last in a down state on the display.
  17363. */
  17364. this.positionDown = new Phaser.Point();
  17365. /**
  17366. * @property {Phaser.Point} positionUp - A Phaser.Point object containing the x/y values of the pointer when it was last released.
  17367. */
  17368. this.positionUp = new Phaser.Point();
  17369. /**
  17370. * A Phaser.Circle that is centered on the x/y coordinates of this pointer, useful for hit detection.
  17371. * The Circle size is 44px (Apples recommended "finger tip" size).
  17372. * @property {Phaser.Circle} circle
  17373. */
  17374. this.circle = new Phaser.Circle(0, 0, 44);
  17375. if (id === 0)
  17376. {
  17377. this.isMouse = true;
  17378. }
  17379. };
  17380. Phaser.Pointer.prototype = {
  17381. /**
  17382. * Called when the Pointer is pressed onto the touchscreen.
  17383. * @method Phaser.Pointer#start
  17384. * @param {Any} event
  17385. */
  17386. start: function (event) {
  17387. this.identifier = event.identifier;
  17388. this.target = event.target;
  17389. if (typeof event.button !== 'undefined')
  17390. {
  17391. this.button = event.button;
  17392. }
  17393. this._history = [];
  17394. this.active = true;
  17395. this.withinGame = true;
  17396. this.isDown = true;
  17397. this.isUp = false;
  17398. // Work out how long it has been since the last click
  17399. this.msSinceLastClick = this.game.time.now - this.timeDown;
  17400. this.timeDown = this.game.time.now;
  17401. this._holdSent = false;
  17402. // This sets the x/y and other local values
  17403. this.move(event, true);
  17404. // x and y are the old values here?
  17405. this.positionDown.setTo(this.x, this.y);
  17406. if (this.game.input.multiInputOverride === Phaser.Input.MOUSE_OVERRIDES_TOUCH || this.game.input.multiInputOverride === Phaser.Input.MOUSE_TOUCH_COMBINE || (this.game.input.multiInputOverride === Phaser.Input.TOUCH_OVERRIDES_MOUSE && this.game.input.currentPointers === 0))
  17407. {
  17408. this.game.input.x = this.x;
  17409. this.game.input.y = this.y;
  17410. this.game.input.position.setTo(this.x, this.y);
  17411. this.game.input.onDown.dispatch(this, event);
  17412. this.game.input.resetSpeed(this.x, this.y);
  17413. }
  17414. this._stateReset = false;
  17415. this.totalTouches++;
  17416. if (!this.isMouse)
  17417. {
  17418. this.game.input.currentPointers++;
  17419. }
  17420. if (this.targetObject !== null)
  17421. {
  17422. this.targetObject._touchedHandler(this);
  17423. }
  17424. return this;
  17425. },
  17426. /**
  17427. * Called by the Input Manager.
  17428. * @method Phaser.Pointer#update
  17429. */
  17430. update: function () {
  17431. if (this.active)
  17432. {
  17433. if (this._holdSent === false && this.duration >= this.game.input.holdRate)
  17434. {
  17435. if (this.game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this.game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this.game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this.game.input.currentPointers === 0))
  17436. {
  17437. this.game.input.onHold.dispatch(this);
  17438. }
  17439. this._holdSent = true;
  17440. }
  17441. // Update the droppings history
  17442. if (this.game.input.recordPointerHistory && this.game.time.now >= this._nextDrop)
  17443. {
  17444. this._nextDrop = this.game.time.now + this.game.input.recordRate;
  17445. this._history.push({
  17446. x: this.position.x,
  17447. y: this.position.y
  17448. });
  17449. if (this._history.length > this.game.input.recordLimit)
  17450. {
  17451. this._history.shift();
  17452. }
  17453. }
  17454. }
  17455. },
  17456. /**
  17457. * Called when the Pointer is moved.
  17458. * @method Phaser.Pointer#move
  17459. * @param {MouseEvent|PointerEvent|TouchEvent} event - The event passed up from the input handler.
  17460. * @param {boolean} [fromClick=false] - Was this called from the click event?
  17461. */
  17462. move: function (event, fromClick) {
  17463. if (this.game.input.pollLocked)
  17464. {
  17465. return;
  17466. }
  17467. if (typeof fromClick === 'undefined') { fromClick = false; }
  17468. if (typeof event.button !== 'undefined')
  17469. {
  17470. this.button = event.button;
  17471. }
  17472. this.clientX = event.clientX;
  17473. this.clientY = event.clientY;
  17474. this.pageX = event.pageX;
  17475. this.pageY = event.pageY;
  17476. this.screenX = event.screenX;
  17477. this.screenY = event.screenY;
  17478. this.x = (this.pageX - this.game.stage.offset.x) * this.game.input.scale.x;
  17479. this.y = (this.pageY - this.game.stage.offset.y) * this.game.input.scale.y;
  17480. this.position.setTo(this.x, this.y);
  17481. this.circle.x = this.x;
  17482. this.circle.y = this.y;
  17483. if (this.game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this.game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this.game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this.game.input.currentPointers === 0))
  17484. {
  17485. this.game.input.activePointer = this;
  17486. this.game.input.x = this.x;
  17487. this.game.input.y = this.y;
  17488. this.game.input.position.setTo(this.game.input.x, this.game.input.y);
  17489. this.game.input.circle.x = this.game.input.x;
  17490. this.game.input.circle.y = this.game.input.y;
  17491. }
  17492. // If the game is paused we don't process any target objects or callbacks
  17493. if (this.game.paused)
  17494. {
  17495. return this;
  17496. }
  17497. if (this.game.input.moveCallback)
  17498. {
  17499. this.game.input.moveCallback.call(this.game.input.moveCallbackContext, this, this.x, this.y);
  17500. }
  17501. // Easy out if we're dragging something and it still exists
  17502. if (this.targetObject !== null && this.targetObject.isDragged === true)
  17503. {
  17504. if (this.targetObject.update(this) === false)
  17505. {
  17506. this.targetObject = null;
  17507. }
  17508. return this;
  17509. }
  17510. // Work out which object is on the top
  17511. this._highestRenderOrderID = Number.MAX_SAFE_INTEGER;
  17512. this._highestRenderObject = null;
  17513. this._highestInputPriorityID = -1;
  17514. // Just run through the linked list
  17515. if (this.game.input.interactiveItems.total > 0)
  17516. {
  17517. var currentNode = this.game.input.interactiveItems.next;
  17518. do
  17519. {
  17520. // If the object is using pixelPerfect checks, or has a higher InputManager.PriorityID OR if the priority ID is the same as the current highest AND it has a higher renderOrderID, then set it to the top
  17521. if (currentNode.validForInput(this._highestInputPriorityID, this._highestRenderOrderID))
  17522. {
  17523. if ((!fromClick && currentNode.checkPointerOver(this)) || (fromClick && currentNode.checkPointerDown(this)))
  17524. {
  17525. this._highestRenderOrderID = currentNode.sprite._cache[3]; // renderOrderID
  17526. this._highestInputPriorityID = currentNode.priorityID;
  17527. this._highestRenderObject = currentNode;
  17528. }
  17529. }
  17530. currentNode = currentNode.next;
  17531. }
  17532. while (currentNode != null);
  17533. }
  17534. if (this._highestRenderObject === null)
  17535. {
  17536. // The pointer isn't currently over anything, check if we've got a lingering previous target
  17537. if (this.targetObject)
  17538. {
  17539. // console.log("The pointer isn't currently over anything, check if we've got a lingering previous target");
  17540. this.targetObject._pointerOutHandler(this);
  17541. this.targetObject = null;
  17542. }
  17543. }
  17544. else
  17545. {
  17546. if (this.targetObject === null)
  17547. {
  17548. // And now set the new one
  17549. // console.log('And now set the new one');
  17550. this.targetObject = this._highestRenderObject;
  17551. this._highestRenderObject._pointerOverHandler(this);
  17552. }
  17553. else
  17554. {
  17555. // We've got a target from the last update
  17556. // console.log("We've got a target from the last update");
  17557. if (this.targetObject === this._highestRenderObject)
  17558. {
  17559. // Same target as before, so update it
  17560. // console.log("Same target as before, so update it");
  17561. if (this._highestRenderObject.update(this) === false)
  17562. {
  17563. this.targetObject = null;
  17564. }
  17565. }
  17566. else
  17567. {
  17568. // The target has changed, so tell the old one we've left it
  17569. // console.log("The target has changed, so tell the old one we've left it");
  17570. this.targetObject._pointerOutHandler(this);
  17571. // And now set the new one
  17572. this.targetObject = this._highestRenderObject;
  17573. this.targetObject._pointerOverHandler(this);
  17574. }
  17575. }
  17576. }
  17577. return this;
  17578. },
  17579. /**
  17580. * Called when the Pointer leaves the target area.
  17581. * @method Phaser.Pointer#leave
  17582. * @param {MouseEvent|PointerEvent|TouchEvent} event - The event passed up from the input handler.
  17583. */
  17584. leave: function (event) {
  17585. this.withinGame = false;
  17586. this.move(event, false);
  17587. },
  17588. /**
  17589. * Called when the Pointer leaves the touchscreen.
  17590. * @method Phaser.Pointer#stop
  17591. * @param {MouseEvent|PointerEvent|TouchEvent} event - The event passed up from the input handler.
  17592. */
  17593. stop: function (event) {
  17594. if (this._stateReset)
  17595. {
  17596. event.preventDefault();
  17597. return;
  17598. }
  17599. this.timeUp = this.game.time.now;
  17600. if (this.game.input.multiInputOverride == Phaser.Input.MOUSE_OVERRIDES_TOUCH || this.game.input.multiInputOverride == Phaser.Input.MOUSE_TOUCH_COMBINE || (this.game.input.multiInputOverride == Phaser.Input.TOUCH_OVERRIDES_MOUSE && this.game.input.currentPointers === 0))
  17601. {
  17602. this.game.input.onUp.dispatch(this, event);
  17603. // Was it a tap?
  17604. if (this.duration >= 0 && this.duration <= this.game.input.tapRate)
  17605. {
  17606. // Was it a double-tap?
  17607. if (this.timeUp - this.previousTapTime < this.game.input.doubleTapRate)
  17608. {
  17609. // Yes, let's dispatch the signal then with the 2nd parameter set to true
  17610. this.game.input.onTap.dispatch(this, true);
  17611. }
  17612. else
  17613. {
  17614. // Wasn't a double-tap, so dispatch a single tap signal
  17615. this.game.input.onTap.dispatch(this, false);
  17616. }
  17617. this.previousTapTime = this.timeUp;
  17618. }
  17619. }
  17620. // Mouse is always active
  17621. if (this.id > 0)
  17622. {
  17623. this.active = false;
  17624. }
  17625. this.withinGame = false;
  17626. this.isDown = false;
  17627. this.isUp = true;
  17628. this.positionUp.setTo(this.x, this.y);
  17629. if (this.isMouse === false)
  17630. {
  17631. this.game.input.currentPointers--;
  17632. }
  17633. if (this.game.input.interactiveItems.total > 0)
  17634. {
  17635. var currentNode = this.game.input.interactiveItems.next;
  17636. do
  17637. {
  17638. if (currentNode)
  17639. {
  17640. currentNode._releasedHandler(this);
  17641. }
  17642. currentNode = currentNode.next;
  17643. }
  17644. while (currentNode != null);
  17645. }
  17646. if (this.targetObject)
  17647. {
  17648. this.targetObject._releasedHandler(this);
  17649. }
  17650. this.targetObject = null;
  17651. return this;
  17652. },
  17653. /**
  17654. * The Pointer is considered justPressed if the time it was pressed onto the touchscreen or clicked is less than justPressedRate.
  17655. * Note that calling justPressed doesn't reset the pressed status of the Pointer, it will return `true` for as long as the duration is valid.
  17656. * If you wish to check if the Pointer was pressed down just once then see the Sprite.events.onInputDown event.
  17657. * @method Phaser.Pointer#justPressed
  17658. * @param {number} [duration] - The time to check against. If none given it will use InputManager.justPressedRate.
  17659. * @return {boolean} true if the Pointer was pressed down within the duration given.
  17660. */
  17661. justPressed: function (duration) {
  17662. duration = duration || this.game.input.justPressedRate;
  17663. return (this.isDown === true && (this.timeDown + duration) > this.game.time.now);
  17664. },
  17665. /**
  17666. * The Pointer is considered justReleased if the time it left the touchscreen is less than justReleasedRate.
  17667. * Note that calling justReleased doesn't reset the pressed status of the Pointer, it will return `true` for as long as the duration is valid.
  17668. * If you wish to check if the Pointer was released just once then see the Sprite.events.onInputUp event.
  17669. * @method Phaser.Pointer#justReleased
  17670. * @param {number} [duration] - The time to check against. If none given it will use InputManager.justReleasedRate.
  17671. * @return {boolean} true if the Pointer was released within the duration given.
  17672. */
  17673. justReleased: function (duration) {
  17674. duration = duration || this.game.input.justReleasedRate;
  17675. return (this.isUp === true && (this.timeUp + duration) > this.game.time.now);
  17676. },
  17677. /**
  17678. * Resets the Pointer properties. Called by InputManager.reset when you perform a State change.
  17679. * @method Phaser.Pointer#reset
  17680. */
  17681. reset: function () {
  17682. if (this.isMouse === false)
  17683. {
  17684. this.active = false;
  17685. }
  17686. this.identifier = null;
  17687. this.isDown = false;
  17688. this.isUp = true;
  17689. this.totalTouches = 0;
  17690. this._holdSent = false;
  17691. this._history.length = 0;
  17692. this._stateReset = true;
  17693. if (this.targetObject)
  17694. {
  17695. this.targetObject._releasedHandler(this);
  17696. }
  17697. this.targetObject = null;
  17698. }
  17699. };
  17700. Phaser.Pointer.prototype.constructor = Phaser.Pointer;
  17701. /**
  17702. * How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1.
  17703. * @name Phaser.Pointer#duration
  17704. * @property {number} duration - How long the Pointer has been depressed on the touchscreen. If not currently down it returns -1.
  17705. * @readonly
  17706. */
  17707. Object.defineProperty(Phaser.Pointer.prototype, "duration", {
  17708. get: function () {
  17709. if (this.isUp)
  17710. {
  17711. return -1;
  17712. }
  17713. return this.game.time.now - this.timeDown;
  17714. }
  17715. });
  17716. /**
  17717. * Gets the X value of this Pointer in world coordinates based on the world camera.
  17718. * @name Phaser.Pointer#worldX
  17719. * @property {number} duration - The X value of this Pointer in world coordinates based on the world camera.
  17720. * @readonly
  17721. */
  17722. Object.defineProperty(Phaser.Pointer.prototype, "worldX", {
  17723. get: function () {
  17724. return this.game.world.camera.x + this.x;
  17725. }
  17726. });
  17727. /**
  17728. * Gets the Y value of this Pointer in world coordinates based on the world camera.
  17729. * @name Phaser.Pointer#worldY
  17730. * @property {number} duration - The Y value of this Pointer in world coordinates based on the world camera.
  17731. * @readonly
  17732. */
  17733. Object.defineProperty(Phaser.Pointer.prototype, "worldY", {
  17734. get: function () {
  17735. return this.game.world.camera.y + this.y;
  17736. }
  17737. });
  17738. /**
  17739. * @author Richard Davey <rich@photonstorm.com>
  17740. * @copyright 2014 Photon Storm Ltd.
  17741. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  17742. */
  17743. /**
  17744. * Phaser.Touch handles touch events with your game. Note: Android 2.x only supports 1 touch event at once, no multi-touch.
  17745. *
  17746. * @class Phaser.Touch
  17747. * @classdesc The Touch class handles touch interactions with the game and the resulting Pointer objects.
  17748. * @constructor
  17749. * @param {Phaser.Game} game - A reference to the currently running game.
  17750. */
  17751. Phaser.Touch = function (game) {
  17752. /**
  17753. * @property {Phaser.Game} game - A reference to the currently running game.
  17754. */
  17755. this.game = game;
  17756. /**
  17757. * @property {boolean} disabled - You can disable all Touch events by setting disabled = true. While set all new touch events will be ignored.
  17758. * @return {boolean}
  17759. */
  17760. this.disabled = false;
  17761. /**
  17762. * @property {Object} callbackContext - The context under which callbacks are called.
  17763. */
  17764. this.callbackContext = this.game;
  17765. /**
  17766. * @property {function} touchStartCallback - A callback that can be fired on a touchStart event.
  17767. */
  17768. this.touchStartCallback = null;
  17769. /**
  17770. * @property {function} touchMoveCallback - A callback that can be fired on a touchMove event.
  17771. */
  17772. this.touchMoveCallback = null;
  17773. /**
  17774. * @property {function} touchEndCallback - A callback that can be fired on a touchEnd event.
  17775. */
  17776. this.touchEndCallback = null;
  17777. /**
  17778. * @property {function} touchEnterCallback - A callback that can be fired on a touchEnter event.
  17779. */
  17780. this.touchEnterCallback = null;
  17781. /**
  17782. * @property {function} touchLeaveCallback - A callback that can be fired on a touchLeave event.
  17783. */
  17784. this.touchLeaveCallback = null;
  17785. /**
  17786. * @property {function} touchCancelCallback - A callback that can be fired on a touchCancel event.
  17787. */
  17788. this.touchCancelCallback = null;
  17789. /**
  17790. * @property {boolean} preventDefault - If true the TouchEvent will have prevent.default called on it.
  17791. * @default
  17792. */
  17793. this.preventDefault = true;
  17794. /**
  17795. * @property {TouchEvent} event - The browser touch DOM event. Will be set to null if no touch event has ever been received.
  17796. * @default
  17797. */
  17798. this.event = null;
  17799. /**
  17800. * @property {function} _onTouchStart - Internal event handler reference.
  17801. * @private
  17802. */
  17803. this._onTouchStart = null;
  17804. /**
  17805. * @property {function} _onTouchMove - Internal event handler reference.
  17806. * @private
  17807. */
  17808. this._onTouchMove = null;
  17809. /**
  17810. * @property {function} _onTouchEnd - Internal event handler reference.
  17811. * @private
  17812. */
  17813. this._onTouchEnd = null;
  17814. /**
  17815. * @property {function} _onTouchEnter - Internal event handler reference.
  17816. * @private
  17817. */
  17818. this._onTouchEnter = null;
  17819. /**
  17820. * @property {function} _onTouchLeave - Internal event handler reference.
  17821. * @private
  17822. */
  17823. this._onTouchLeave = null;
  17824. /**
  17825. * @property {function} _onTouchCancel - Internal event handler reference.
  17826. * @private
  17827. */
  17828. this._onTouchCancel = null;
  17829. /**
  17830. * @property {function} _onTouchMove - Internal event handler reference.
  17831. * @private
  17832. */
  17833. this._onTouchMove = null;
  17834. };
  17835. Phaser.Touch.prototype = {
  17836. /**
  17837. * Starts the event listeners running.
  17838. * @method Phaser.Touch#start
  17839. */
  17840. start: function () {
  17841. if (this._onTouchStart !== null)
  17842. {
  17843. // Avoid setting multiple listeners
  17844. return;
  17845. }
  17846. var _this = this;
  17847. if (this.game.device.touch)
  17848. {
  17849. this._onTouchStart = function (event) {
  17850. return _this.onTouchStart(event);
  17851. };
  17852. this._onTouchMove = function (event) {
  17853. return _this.onTouchMove(event);
  17854. };
  17855. this._onTouchEnd = function (event) {
  17856. return _this.onTouchEnd(event);
  17857. };
  17858. this._onTouchEnter = function (event) {
  17859. return _this.onTouchEnter(event);
  17860. };
  17861. this._onTouchLeave = function (event) {
  17862. return _this.onTouchLeave(event);
  17863. };
  17864. this._onTouchCancel = function (event) {
  17865. return _this.onTouchCancel(event);
  17866. };
  17867. this.game.canvas.addEventListener('touchstart', this._onTouchStart, false);
  17868. this.game.canvas.addEventListener('touchmove', this._onTouchMove, false);
  17869. this.game.canvas.addEventListener('touchend', this._onTouchEnd, false);
  17870. this.game.canvas.addEventListener('touchenter', this._onTouchEnter, false);
  17871. this.game.canvas.addEventListener('touchleave', this._onTouchLeave, false);
  17872. this.game.canvas.addEventListener('touchcancel', this._onTouchCancel, false);
  17873. }
  17874. },
  17875. /**
  17876. * Consumes all touchmove events on the document (only enable this if you know you need it!).
  17877. * @method Phaser.Touch#consumeTouchMove
  17878. */
  17879. consumeDocumentTouches: function () {
  17880. this._documentTouchMove = function (event) {
  17881. event.preventDefault();
  17882. };
  17883. document.addEventListener('touchmove', this._documentTouchMove, false);
  17884. },
  17885. /**
  17886. * The internal method that handles the touchstart event from the browser.
  17887. * @method Phaser.Touch#onTouchStart
  17888. * @param {TouchEvent} event - The native event from the browser. This gets stored in Touch.event.
  17889. */
  17890. onTouchStart: function (event) {
  17891. this.event = event;
  17892. if (this.touchStartCallback)
  17893. {
  17894. this.touchStartCallback.call(this.callbackContext, event);
  17895. }
  17896. if (this.game.input.disabled || this.disabled)
  17897. {
  17898. return;
  17899. }
  17900. if (this.preventDefault)
  17901. {
  17902. event.preventDefault();
  17903. }
  17904. // event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element)
  17905. // event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element
  17906. // event.changedTouches = the touches that CHANGED in this event, not the total number of them
  17907. for (var i = 0; i < event.changedTouches.length; i++)
  17908. {
  17909. this.game.input.startPointer(event.changedTouches[i]);
  17910. }
  17911. },
  17912. /**
  17913. * Touch cancel - touches that were disrupted (perhaps by moving into a plugin or browser chrome).
  17914. * Occurs for example on iOS when you put down 4 fingers and the app selector UI appears.
  17915. * @method Phaser.Touch#onTouchCancel
  17916. * @param {TouchEvent} event - The native event from the browser. This gets stored in Touch.event.
  17917. */
  17918. onTouchCancel: function (event) {
  17919. this.event = event;
  17920. if (this.touchCancelCallback)
  17921. {
  17922. this.touchCancelCallback.call(this.callbackContext, event);
  17923. }
  17924. if (this.game.input.disabled || this.disabled)
  17925. {
  17926. return;
  17927. }
  17928. if (this.preventDefault)
  17929. {
  17930. event.preventDefault();
  17931. }
  17932. // Touch cancel - touches that were disrupted (perhaps by moving into a plugin or browser chrome)
  17933. // http://www.w3.org/TR/touch-events/#dfn-touchcancel
  17934. for (var i = 0; i < event.changedTouches.length; i++)
  17935. {
  17936. this.game.input.stopPointer(event.changedTouches[i]);
  17937. }
  17938. },
  17939. /**
  17940. * For touch enter and leave its a list of the touch points that have entered or left the target.
  17941. * Doesn't appear to be supported by most browsers on a canvas element yet.
  17942. * @method Phaser.Touch#onTouchEnter
  17943. * @param {TouchEvent} event - The native event from the browser. This gets stored in Touch.event.
  17944. */
  17945. onTouchEnter: function (event) {
  17946. this.event = event;
  17947. if (this.touchEnterCallback)
  17948. {
  17949. this.touchEnterCallback.call(this.callbackContext, event);
  17950. }
  17951. if (this.game.input.disabled || this.disabled)
  17952. {
  17953. return;
  17954. }
  17955. if (this.preventDefault)
  17956. {
  17957. event.preventDefault();
  17958. }
  17959. },
  17960. /**
  17961. * For touch enter and leave its a list of the touch points that have entered or left the target.
  17962. * Doesn't appear to be supported by most browsers on a canvas element yet.
  17963. * @method Phaser.Touch#onTouchLeave
  17964. * @param {TouchEvent} event - The native event from the browser. This gets stored in Touch.event.
  17965. */
  17966. onTouchLeave: function (event) {
  17967. this.event = event;
  17968. if (this.touchLeaveCallback)
  17969. {
  17970. this.touchLeaveCallback.call(this.callbackContext, event);
  17971. }
  17972. if (this.preventDefault)
  17973. {
  17974. event.preventDefault();
  17975. }
  17976. },
  17977. /**
  17978. * The handler for the touchmove events.
  17979. * @method Phaser.Touch#onTouchMove
  17980. * @param {TouchEvent} event - The native event from the browser. This gets stored in Touch.event.
  17981. */
  17982. onTouchMove: function (event) {
  17983. this.event = event;
  17984. if (this.touchMoveCallback)
  17985. {
  17986. this.touchMoveCallback.call(this.callbackContext, event);
  17987. }
  17988. if (this.preventDefault)
  17989. {
  17990. event.preventDefault();
  17991. }
  17992. for (var i = 0; i < event.changedTouches.length; i++)
  17993. {
  17994. this.game.input.updatePointer(event.changedTouches[i]);
  17995. }
  17996. },
  17997. /**
  17998. * The handler for the touchend events.
  17999. * @method Phaser.Touch#onTouchEnd
  18000. * @param {TouchEvent} event - The native event from the browser. This gets stored in Touch.event.
  18001. */
  18002. onTouchEnd: function (event) {
  18003. this.event = event;
  18004. if (this.touchEndCallback)
  18005. {
  18006. this.touchEndCallback.call(this.callbackContext, event);
  18007. }
  18008. if (this.preventDefault)
  18009. {
  18010. event.preventDefault();
  18011. }
  18012. // For touch end its a list of the touch points that have been removed from the surface
  18013. // https://developer.mozilla.org/en-US/docs/DOM/TouchList
  18014. // event.changedTouches = the touches that CHANGED in this event, not the total number of them
  18015. for (var i = 0; i < event.changedTouches.length; i++)
  18016. {
  18017. this.game.input.stopPointer(event.changedTouches[i]);
  18018. }
  18019. },
  18020. /**
  18021. * Stop the event listeners.
  18022. * @method Phaser.Touch#stop
  18023. */
  18024. stop: function () {
  18025. if (this.game.device.touch)
  18026. {
  18027. this.game.canvas.removeEventListener('touchstart', this._onTouchStart);
  18028. this.game.canvas.removeEventListener('touchmove', this._onTouchMove);
  18029. this.game.canvas.removeEventListener('touchend', this._onTouchEnd);
  18030. this.game.canvas.removeEventListener('touchenter', this._onTouchEnter);
  18031. this.game.canvas.removeEventListener('touchleave', this._onTouchLeave);
  18032. this.game.canvas.removeEventListener('touchcancel', this._onTouchCancel);
  18033. }
  18034. }
  18035. };
  18036. Phaser.Touch.prototype.constructor = Phaser.Touch;
  18037. /**
  18038. * @author @karlmacklin <tacklemcclean@gmail.com>
  18039. * @copyright 2014 Photon Storm Ltd.
  18040. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  18041. */
  18042. /**
  18043. * The Gamepad class handles looking after gamepad input for your game.
  18044. * Remember to call gamepad.start(); expecting input!
  18045. *
  18046. * HTML5 GAMEPAD API SUPPORT IS AT AN EXPERIMENTAL STAGE!
  18047. * At moment of writing this (end of 2013) only Chrome supports parts of it out of the box. Firefox supports it
  18048. * via prefs flags (about:config, search gamepad). The browsers map the same controllers differently.
  18049. * This class has constans for Windows 7 Chrome mapping of
  18050. * XBOX 360 controller.
  18051. *
  18052. * @class Phaser.Gamepad
  18053. * @constructor
  18054. * @param {Phaser.Game} game - A reference to the currently running game.
  18055. */
  18056. Phaser.Gamepad = function (game) {
  18057. /**
  18058. * @property {Phaser.Game} game - Local reference to game.
  18059. */
  18060. this.game = game;
  18061. /**
  18062. * @property {Array<Phaser.SinglePad>} _gamepads - The four Phaser Gamepads.
  18063. * @private
  18064. */
  18065. this._gamepads = [
  18066. new Phaser.SinglePad(game, this),
  18067. new Phaser.SinglePad(game, this),
  18068. new Phaser.SinglePad(game, this),
  18069. new Phaser.SinglePad(game, this)
  18070. ];
  18071. /**
  18072. * @property {Object} _gamepadIndexMap - Maps the browsers gamepad indices to our Phaser Gamepads
  18073. * @private
  18074. */
  18075. this._gamepadIndexMap = {};
  18076. /**
  18077. * @property {Array} _rawPads - The raw state of the gamepads from the browser
  18078. * @private
  18079. */
  18080. this._rawPads = [];
  18081. /**
  18082. * @property {boolean} _active - Private flag for whether or not the API is polled
  18083. * @private
  18084. * @default
  18085. */
  18086. this._active = false;
  18087. /**
  18088. * You can disable all Gamepad Input by setting disabled to true. While true all new input related events will be ignored.
  18089. * @property {boolean} disabled - The disabled state of the Gamepad.
  18090. * @default
  18091. */
  18092. this.disabled = false;
  18093. /**
  18094. * Whether or not gamepads are supported in the current browser. Note that as of Dec. 2013 this check is actually not accurate at all due to poor implementation.
  18095. * @property {boolean} _gamepadSupportAvailable - Are gamepads supported in this browser or not?
  18096. * @private
  18097. */
  18098. this._gamepadSupportAvailable = !!navigator.webkitGetGamepads || !!navigator.webkitGamepads || (navigator.userAgent.indexOf('Firefox/') != -1) || !!navigator.getGamepads;
  18099. /**
  18100. * Used to check for differences between earlier polls and current state of gamepads.
  18101. * @property {Array} _prevRawGamepadTypes
  18102. * @private
  18103. * @default
  18104. */
  18105. this._prevRawGamepadTypes = [];
  18106. /**
  18107. * Used to check for differences between earlier polls and current state of gamepads.
  18108. * @property {Array} _prevTimestamps
  18109. * @private
  18110. * @default
  18111. */
  18112. this._prevTimestamps = [];
  18113. /**
  18114. * @property {Object} callbackContext - The context under which the callbacks are run.
  18115. */
  18116. this.callbackContext = this;
  18117. /**
  18118. * @property {function} onConnectCallback - This callback is invoked every time any gamepad is connected
  18119. */
  18120. this.onConnectCallback = null;
  18121. /**
  18122. * @property {function} onDisconnectCallback - This callback is invoked every time any gamepad is disconnected
  18123. */
  18124. this.onDisconnectCallback = null;
  18125. /**
  18126. * @property {function} onDownCallback - This callback is invoked every time any gamepad button is pressed down.
  18127. */
  18128. this.onDownCallback = null;
  18129. /**
  18130. * @property {function} onUpCallback - This callback is invoked every time any gamepad button is released.
  18131. */
  18132. this.onUpCallback = null;
  18133. /**
  18134. * @property {function} onAxisCallback - This callback is invoked every time any gamepad axis is changed.
  18135. */
  18136. this.onAxisCallback = null;
  18137. /**
  18138. * @property {function} onFloatCallback - This callback is invoked every time any gamepad button is changed to a value where value > 0 and value < 1.
  18139. */
  18140. this.onFloatCallback = null;
  18141. /**
  18142. * @property {function} _ongamepadconnected - Private callback for Firefox gamepad connection handling
  18143. * @private
  18144. */
  18145. this._ongamepadconnected = null;
  18146. /**
  18147. * @property {function} _gamepaddisconnected - Private callback for Firefox gamepad connection handling
  18148. * @private
  18149. */
  18150. this._gamepaddisconnected = null;
  18151. };
  18152. Phaser.Gamepad.prototype = {
  18153. /**
  18154. * Add callbacks to the main Gamepad handler to handle connect/disconnect/button down/button up/axis change/float value buttons
  18155. * @method Phaser.Gamepad#addCallbacks
  18156. * @param {Object} context - The context under which the callbacks are run.
  18157. * @param {Object} callbacks - Object that takes six different callback methods:
  18158. * onConnectCallback, onDisconnectCallback, onDownCallback, onUpCallback, onAxisCallback, onFloatCallback
  18159. */
  18160. addCallbacks: function (context, callbacks) {
  18161. if (typeof callbacks !== 'undefined')
  18162. {
  18163. this.onConnectCallback = (typeof callbacks.onConnect === 'function') ? callbacks.onConnect : this.onConnectCallback;
  18164. this.onDisconnectCallback = (typeof callbacks.onDisconnect === 'function') ? callbacks.onDisconnect : this.onDisconnectCallback;
  18165. this.onDownCallback = (typeof callbacks.onDown === 'function') ? callbacks.onDown : this.onDownCallback;
  18166. this.onUpCallback = (typeof callbacks.onUp === 'function') ? callbacks.onUp : this.onUpCallback;
  18167. this.onAxisCallback = (typeof callbacks.onAxis === 'function') ? callbacks.onAxis : this.onAxisCallback;
  18168. this.onFloatCallback = (typeof callbacks.onFloat === 'function') ? callbacks.onFloat : this.onFloatCallback;
  18169. }
  18170. },
  18171. /**
  18172. * Starts the Gamepad event handling.
  18173. * This MUST be called manually before Phaser will start polling the Gamepad API.
  18174. *
  18175. * @method Phaser.Gamepad#start
  18176. */
  18177. start: function () {
  18178. if (this._active)
  18179. {
  18180. // Avoid setting multiple listeners
  18181. return;
  18182. }
  18183. this._active = true;
  18184. var _this = this;
  18185. this._ongamepadconnected = function(event) {
  18186. var newPad = event.gamepad;
  18187. _this._rawPads.push(newPad);
  18188. _this._gamepads[newPad.index].connect(newPad);
  18189. };
  18190. window.addEventListener('gamepadconnected', this._ongamepadconnected, false);
  18191. this._ongamepaddisconnected = function(event) {
  18192. var removedPad = event.gamepad;
  18193. for (var i in _this._rawPads)
  18194. {
  18195. if (_this._rawPads[i].index === removedPad.index)
  18196. {
  18197. _this._rawPads.splice(i,1);
  18198. }
  18199. }
  18200. _this._gamepads[removedPad.index].disconnect();
  18201. };
  18202. window.addEventListener('gamepaddisconnected', this._ongamepaddisconnected, false);
  18203. },
  18204. /**
  18205. * Main gamepad update loop. Should not be called manually.
  18206. * @method Phaser.Gamepad#update
  18207. * @private
  18208. */
  18209. update: function () {
  18210. this._pollGamepads();
  18211. for (var i = 0; i < this._gamepads.length; i++)
  18212. {
  18213. if (this._gamepads[i]._connected)
  18214. {
  18215. this._gamepads[i].pollStatus();
  18216. }
  18217. }
  18218. },
  18219. /**
  18220. * Updating connected gamepads (for Google Chrome).
  18221. * Should not be called manually.
  18222. * @method Phaser.Gamepad#_pollGamepads
  18223. * @private
  18224. */
  18225. _pollGamepads: function () {
  18226. var rawGamepads = navigator.getGamepads || (navigator.webkitGetGamepads && navigator.webkitGetGamepads()) || navigator.webkitGamepads;
  18227. if (rawGamepads)
  18228. {
  18229. this._rawPads = [];
  18230. var gamepadsChanged = false;
  18231. for (var i = 0; i < rawGamepads.length; i++)
  18232. {
  18233. if (typeof rawGamepads[i] !== this._prevRawGamepadTypes[i])
  18234. {
  18235. gamepadsChanged = true;
  18236. this._prevRawGamepadTypes[i] = typeof rawGamepads[i];
  18237. }
  18238. if (rawGamepads[i])
  18239. {
  18240. this._rawPads.push(rawGamepads[i]);
  18241. }
  18242. // Support max 4 pads at the moment
  18243. if (i === 3)
  18244. {
  18245. break;
  18246. }
  18247. }
  18248. if (gamepadsChanged)
  18249. {
  18250. var validConnections = { rawIndices: {}, padIndices: {} };
  18251. var singlePad;
  18252. for (var j = 0; j < this._gamepads.length; j++)
  18253. {
  18254. singlePad = this._gamepads[j];
  18255. if (singlePad.connected)
  18256. {
  18257. for (var k = 0; k < this._rawPads.length; k++)
  18258. {
  18259. if (this._rawPads[k].index === singlePad.index)
  18260. {
  18261. validConnections.rawIndices[singlePad.index] = true;
  18262. validConnections.padIndices[j] = true;
  18263. }
  18264. }
  18265. }
  18266. }
  18267. for (var l = 0; l < this._gamepads.length; l++)
  18268. {
  18269. singlePad = this._gamepads[l];
  18270. if (validConnections.padIndices[l])
  18271. {
  18272. continue;
  18273. }
  18274. if (this._rawPads.length < 1)
  18275. {
  18276. singlePad.disconnect();
  18277. }
  18278. for (var m = 0; m < this._rawPads.length; m++)
  18279. {
  18280. if (validConnections.padIndices[l])
  18281. {
  18282. break;
  18283. }
  18284. var rawPad = this._rawPads[m];
  18285. if (rawPad)
  18286. {
  18287. if (validConnections.rawIndices[rawPad.index])
  18288. {
  18289. singlePad.disconnect();
  18290. continue;
  18291. }
  18292. else
  18293. {
  18294. singlePad.connect(rawPad);
  18295. validConnections.rawIndices[rawPad.index] = true;
  18296. validConnections.padIndices[l] = true;
  18297. }
  18298. }
  18299. else
  18300. {
  18301. singlePad.disconnect();
  18302. }
  18303. }
  18304. }
  18305. }
  18306. }
  18307. },
  18308. /**
  18309. * Sets the deadZone variable for all four gamepads
  18310. * @method Phaser.Gamepad#setDeadZones
  18311. */
  18312. setDeadZones: function (value) {
  18313. for (var i = 0; i < this._gamepads.length; i++)
  18314. {
  18315. this._gamepads[i].deadZone = value;
  18316. }
  18317. },
  18318. /**
  18319. * Stops the Gamepad event handling.
  18320. *
  18321. * @method Phaser.Gamepad#stop
  18322. */
  18323. stop: function () {
  18324. this._active = false;
  18325. window.removeEventListener('gamepadconnected', this._ongamepadconnected);
  18326. window.removeEventListener('gamepaddisconnected', this._ongamepaddisconnected);
  18327. },
  18328. /**
  18329. * Reset all buttons/axes of all gamepads
  18330. * @method Phaser.Gamepad#reset
  18331. */
  18332. reset: function () {
  18333. this.update();
  18334. for (var i = 0; i < this._gamepads.length; i++)
  18335. {
  18336. this._gamepads[i].reset();
  18337. }
  18338. },
  18339. /**
  18340. * Returns the "just pressed" state of a button from ANY gamepad connected. Just pressed is considered true if the button was pressed down within the duration given (default 250ms).
  18341. * @method Phaser.Gamepad#justPressed
  18342. * @param {number} buttonCode - The buttonCode of the button to check for.
  18343. * @param {number} [duration=250] - The duration below which the button is considered as being just pressed.
  18344. * @return {boolean} True if the button is just pressed otherwise false.
  18345. */
  18346. justPressed: function (buttonCode, duration) {
  18347. for (var i = 0; i < this._gamepads.length; i++)
  18348. {
  18349. if (this._gamepads[i].justPressed(buttonCode, duration) === true)
  18350. {
  18351. return true;
  18352. }
  18353. }
  18354. return false;
  18355. },
  18356. /**
  18357. * Returns the "just released" state of a button from ANY gamepad connected. Just released is considered as being true if the button was released within the duration given (default 250ms).
  18358. * @method Phaser.Gamepad#justPressed
  18359. * @param {number} buttonCode - The buttonCode of the button to check for.
  18360. * @param {number} [duration=250] - The duration below which the button is considered as being just released.
  18361. * @return {boolean} True if the button is just released otherwise false.
  18362. */
  18363. justReleased: function (buttonCode, duration) {
  18364. for (var i = 0; i < this._gamepads.length; i++)
  18365. {
  18366. if (this._gamepads[i].justReleased(buttonCode, duration) === true)
  18367. {
  18368. return true;
  18369. }
  18370. }
  18371. return false;
  18372. },
  18373. /**
  18374. * Returns true if the button is currently pressed down, on ANY gamepad.
  18375. * @method Phaser.Gamepad#isDown
  18376. * @param {number} buttonCode - The buttonCode of the button to check for.
  18377. * @return {boolean} True if a button is currently down.
  18378. */
  18379. isDown: function (buttonCode) {
  18380. for (var i = 0; i < this._gamepads.length; i++)
  18381. {
  18382. if (this._gamepads[i].isDown(buttonCode) === true)
  18383. {
  18384. return true;
  18385. }
  18386. }
  18387. return false;
  18388. }
  18389. };
  18390. Phaser.Gamepad.prototype.constructor = Phaser.Gamepad;
  18391. /**
  18392. * If the gamepad input is active or not - if not active it should not be updated from Input.js
  18393. * @name Phaser.Gamepad#active
  18394. * @property {boolean} active - If the gamepad input is active or not.
  18395. * @readonly
  18396. */
  18397. Object.defineProperty(Phaser.Gamepad.prototype, "active", {
  18398. get: function () {
  18399. return this._active;
  18400. }
  18401. });
  18402. /**
  18403. * Whether or not gamepads are supported in current browser.
  18404. * @name Phaser.Gamepad#supported
  18405. * @property {boolean} supported - Whether or not gamepads are supported in current browser.
  18406. * @readonly
  18407. */
  18408. Object.defineProperty(Phaser.Gamepad.prototype, "supported", {
  18409. get: function () {
  18410. return this._gamepadSupportAvailable;
  18411. }
  18412. });
  18413. /**
  18414. * How many live gamepads are currently connected.
  18415. * @name Phaser.Gamepad#padsConnected
  18416. * @property {boolean} padsConnected - How many live gamepads are currently connected.
  18417. * @readonly
  18418. */
  18419. Object.defineProperty(Phaser.Gamepad.prototype, "padsConnected", {
  18420. get: function () {
  18421. return this._rawPads.length;
  18422. }
  18423. });
  18424. /**
  18425. * Gamepad #1
  18426. * @name Phaser.Gamepad#pad1
  18427. * @property {boolean} pad1 - Gamepad #1;
  18428. * @readonly
  18429. */
  18430. Object.defineProperty(Phaser.Gamepad.prototype, "pad1", {
  18431. get: function () {
  18432. return this._gamepads[0];
  18433. }
  18434. });
  18435. /**
  18436. * Gamepad #2
  18437. * @name Phaser.Gamepad#pad2
  18438. * @property {boolean} pad2 - Gamepad #2
  18439. * @readonly
  18440. */
  18441. Object.defineProperty(Phaser.Gamepad.prototype, "pad2", {
  18442. get: function () {
  18443. return this._gamepads[1];
  18444. }
  18445. });
  18446. /**
  18447. * Gamepad #3
  18448. * @name Phaser.Gamepad#pad3
  18449. * @property {boolean} pad3 - Gamepad #3
  18450. * @readonly
  18451. */
  18452. Object.defineProperty(Phaser.Gamepad.prototype, "pad3", {
  18453. get: function () {
  18454. return this._gamepads[2];
  18455. }
  18456. });
  18457. /**
  18458. * Gamepad #4
  18459. * @name Phaser.Gamepad#pad4
  18460. * @property {boolean} pad4 - Gamepad #4
  18461. * @readonly
  18462. */
  18463. Object.defineProperty(Phaser.Gamepad.prototype, "pad4", {
  18464. get: function () {
  18465. return this._gamepads[3];
  18466. }
  18467. });
  18468. Phaser.Gamepad.BUTTON_0 = 0;
  18469. Phaser.Gamepad.BUTTON_1 = 1;
  18470. Phaser.Gamepad.BUTTON_2 = 2;
  18471. Phaser.Gamepad.BUTTON_3 = 3;
  18472. Phaser.Gamepad.BUTTON_4 = 4;
  18473. Phaser.Gamepad.BUTTON_5 = 5;
  18474. Phaser.Gamepad.BUTTON_6 = 6;
  18475. Phaser.Gamepad.BUTTON_7 = 7;
  18476. Phaser.Gamepad.BUTTON_8 = 8;
  18477. Phaser.Gamepad.BUTTON_9 = 9;
  18478. Phaser.Gamepad.BUTTON_10 = 10;
  18479. Phaser.Gamepad.BUTTON_11 = 11;
  18480. Phaser.Gamepad.BUTTON_12 = 12;
  18481. Phaser.Gamepad.BUTTON_13 = 13;
  18482. Phaser.Gamepad.BUTTON_14 = 14;
  18483. Phaser.Gamepad.BUTTON_15 = 15;
  18484. Phaser.Gamepad.AXIS_0 = 0;
  18485. Phaser.Gamepad.AXIS_1 = 1;
  18486. Phaser.Gamepad.AXIS_2 = 2;
  18487. Phaser.Gamepad.AXIS_3 = 3;
  18488. Phaser.Gamepad.AXIS_4 = 4;
  18489. Phaser.Gamepad.AXIS_5 = 5;
  18490. Phaser.Gamepad.AXIS_6 = 6;
  18491. Phaser.Gamepad.AXIS_7 = 7;
  18492. Phaser.Gamepad.AXIS_8 = 8;
  18493. Phaser.Gamepad.AXIS_9 = 9;
  18494. // Below mapping applies to XBOX 360 Wired and Wireless controller on Google Chrome (tested on Windows 7).
  18495. // - Firefox uses different map! Separate amount of buttons and axes. DPAD = axis and not a button.
  18496. // In other words - discrepancies when using gamepads.
  18497. Phaser.Gamepad.XBOX360_A = 0;
  18498. Phaser.Gamepad.XBOX360_B = 1;
  18499. Phaser.Gamepad.XBOX360_X = 2;
  18500. Phaser.Gamepad.XBOX360_Y = 3;
  18501. Phaser.Gamepad.XBOX360_LEFT_BUMPER = 4;
  18502. Phaser.Gamepad.XBOX360_RIGHT_BUMPER = 5;
  18503. Phaser.Gamepad.XBOX360_LEFT_TRIGGER = 6;
  18504. Phaser.Gamepad.XBOX360_RIGHT_TRIGGER = 7;
  18505. Phaser.Gamepad.XBOX360_BACK = 8;
  18506. Phaser.Gamepad.XBOX360_START = 9;
  18507. Phaser.Gamepad.XBOX360_STICK_LEFT_BUTTON = 10;
  18508. Phaser.Gamepad.XBOX360_STICK_RIGHT_BUTTON = 11;
  18509. Phaser.Gamepad.XBOX360_DPAD_LEFT = 14;
  18510. Phaser.Gamepad.XBOX360_DPAD_RIGHT = 15;
  18511. Phaser.Gamepad.XBOX360_DPAD_UP = 12;
  18512. Phaser.Gamepad.XBOX360_DPAD_DOWN = 13;
  18513. Phaser.Gamepad.XBOX360_STICK_LEFT_X = 0;
  18514. Phaser.Gamepad.XBOX360_STICK_LEFT_Y = 1;
  18515. Phaser.Gamepad.XBOX360_STICK_RIGHT_X = 2;
  18516. Phaser.Gamepad.XBOX360_STICK_RIGHT_Y = 3;
  18517. /**
  18518. * @author @karlmacklin <tacklemcclean@gmail.com>
  18519. * @copyright 2014 Photon Storm Ltd.
  18520. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  18521. */
  18522. /**
  18523. * @class Phaser.SinglePad
  18524. * @classdesc A single Phaser Gamepad
  18525. * @constructor
  18526. * @param {Phaser.Game} game - Current game instance.
  18527. * @param {Object} padParent - The parent Phaser.Gamepad object (all gamepads reside under this)
  18528. */
  18529. Phaser.SinglePad = function (game, padParent) {
  18530. /**
  18531. * @property {Phaser.Game} game - Local reference to game.
  18532. */
  18533. this.game = game;
  18534. /**
  18535. * @property {Phaser.Gamepad} padParent - Main Phaser Gamepad object
  18536. */
  18537. this._padParent = padParent;
  18538. /**
  18539. * @property {number} index - The gamepad index as per browsers data
  18540. * @default
  18541. */
  18542. this._index = null;
  18543. /**
  18544. * @property {Object} _rawPad - The 'raw' gamepad data.
  18545. * @private
  18546. */
  18547. this._rawPad = null;
  18548. /**
  18549. * @property {boolean} _connected - Is this pad connected or not.
  18550. * @private
  18551. */
  18552. this._connected = false;
  18553. /**
  18554. * @property {number} _prevTimestamp - Used to check for differences between earlier polls and current state of gamepads.
  18555. * @private
  18556. */
  18557. this._prevTimestamp = null;
  18558. /**
  18559. * @property {Array} _rawButtons - The 'raw' button state.
  18560. * @private
  18561. */
  18562. this._rawButtons = [];
  18563. /**
  18564. * @property {Array} _buttons - Current Phaser state of the buttons.
  18565. * @private
  18566. */
  18567. this._buttons = [];
  18568. /**
  18569. * @property {Array} _axes - Current axes state.
  18570. * @private
  18571. */
  18572. this._axes = [];
  18573. /**
  18574. * @property {Array} _hotkeys - Hotkey buttons.
  18575. * @private
  18576. */
  18577. this._hotkeys = [];
  18578. /**
  18579. * @property {Object} callbackContext - The context under which the callbacks are run.
  18580. */
  18581. this.callbackContext = this;
  18582. /**
  18583. * @property {function} onConnectCallback - This callback is invoked every time this gamepad is connected
  18584. */
  18585. this.onConnectCallback = null;
  18586. /**
  18587. * @property {function} onDisconnectCallback - This callback is invoked every time this gamepad is disconnected
  18588. */
  18589. this.onDisconnectCallback = null;
  18590. /**
  18591. * @property {function} onDownCallback - This callback is invoked every time a button is pressed down.
  18592. */
  18593. this.onDownCallback = null;
  18594. /**
  18595. * @property {function} onUpCallback - This callback is invoked every time a gamepad button is released.
  18596. */
  18597. this.onUpCallback = null;
  18598. /**
  18599. * @property {function} onAxisCallback - This callback is invoked every time an axis is changed.
  18600. */
  18601. this.onAxisCallback = null;
  18602. /**
  18603. * @property {function} onFloatCallback - This callback is invoked every time a button is changed to a value where value > 0 and value < 1.
  18604. */
  18605. this.onFloatCallback = null;
  18606. /**
  18607. * @property {number} deadZone - Dead zone for axis feedback - within this value you won't trigger updates.
  18608. */
  18609. this.deadZone = 0.26;
  18610. };
  18611. Phaser.SinglePad.prototype = {
  18612. /**
  18613. * Add callbacks to the this Gamepad to handle connect/disconnect/button down/button up/axis change/float value buttons
  18614. * @method Phaser.SinglePad#addCallbacks
  18615. * @param {Object} context - The context under which the callbacks are run.
  18616. * @param {Object} callbacks - Object that takes six different callbak methods:
  18617. * onConnectCallback, onDisconnectCallback, onDownCallback, onUpCallback, onAxisCallback, onFloatCallback
  18618. */
  18619. addCallbacks: function (context, callbacks) {
  18620. if (typeof callbacks !== 'undefined')
  18621. {
  18622. this.onConnectCallback = (typeof callbacks.onConnect === 'function') ? callbacks.onConnect : this.onConnectCallback;
  18623. this.onDisconnectCallback = (typeof callbacks.onDisconnect === 'function') ? callbacks.onDisconnect : this.onDisconnectCallback;
  18624. this.onDownCallback = (typeof callbacks.onDown === 'function') ? callbacks.onDown : this.onDownCallback;
  18625. this.onUpCallback = (typeof callbacks.onUp === 'function') ? callbacks.onUp : this.onUpCallback;
  18626. this.onAxisCallback = (typeof callbacks.onAxis === 'function') ? callbacks.onAxis : this.onAxisCallback;
  18627. this.onFloatCallback = (typeof callbacks.onFloat === 'function') ? callbacks.onFloat : this.onFloatCallback;
  18628. }
  18629. },
  18630. /**
  18631. * If you need more fine-grained control over a Key you can create a new Phaser.Key object via this method.
  18632. * The Key object can then be polled, have events attached to it, etc.
  18633. *
  18634. * @method Phaser.SinglePad#addButton
  18635. * @param {number} buttonCode - The buttonCode of the button, i.e. Phaser.Gamepad.BUTTON_0 or Phaser.Gamepad.BUTTON_1
  18636. * @return {Phaser.GamepadButton} The GamepadButton object which you can store locally and reference directly.
  18637. */
  18638. addButton: function (buttonCode) {
  18639. this._hotkeys[buttonCode] = new Phaser.GamepadButton(this.game, buttonCode);
  18640. return this._hotkeys[buttonCode];
  18641. },
  18642. /**
  18643. * Main update function, should be called by Phaser.Gamepad
  18644. * @method Phaser.SinglePad#pollStatus
  18645. */
  18646. pollStatus: function () {
  18647. if (this._rawPad.timestamp && (this._rawPad.timestamp == this._prevTimestamp))
  18648. {
  18649. return;
  18650. }
  18651. for (var i = 0; i < this._rawPad.buttons.length; i += 1)
  18652. {
  18653. var buttonValue = this._rawPad.buttons[i];
  18654. if (this._rawButtons[i] !== buttonValue)
  18655. {
  18656. if (buttonValue === 1)
  18657. {
  18658. this.processButtonDown(i, buttonValue);
  18659. }
  18660. else if (buttonValue === 0)
  18661. {
  18662. this.processButtonUp(i, buttonValue);
  18663. }
  18664. else
  18665. {
  18666. this.processButtonFloat(i, buttonValue);
  18667. }
  18668. this._rawButtons[i] = buttonValue;
  18669. }
  18670. }
  18671. var axes = this._rawPad.axes;
  18672. for (var j = 0; j < axes.length; j += 1)
  18673. {
  18674. var axis = axes[j];
  18675. if (axis > 0 && axis > this.deadZone || axis < 0 && axis < -this.deadZone)
  18676. {
  18677. this.processAxisChange({axis: j, value: axis});
  18678. }
  18679. else
  18680. {
  18681. this.processAxisChange({axis: j, value: 0});
  18682. }
  18683. }
  18684. this._prevTimestamp = this._rawPad.timestamp;
  18685. },
  18686. /**
  18687. * Gamepad connect function, should be called by Phaser.Gamepad
  18688. * @method Phaser.SinglePad#connect
  18689. * @param {Object} rawPad - The raw gamepad object
  18690. */
  18691. connect: function (rawPad) {
  18692. var triggerCallback = !this._connected;
  18693. this._index = rawPad.index;
  18694. this._connected = true;
  18695. this._rawPad = rawPad;
  18696. this._rawButtons = rawPad.buttons;
  18697. this._axes = rawPad.axes;
  18698. if (triggerCallback && this._padParent.onConnectCallback)
  18699. {
  18700. this._padParent.onConnectCallback.call(this._padParent.callbackContext, this._index);
  18701. }
  18702. if (triggerCallback && this.onConnectCallback)
  18703. {
  18704. this.onConnectCallback.call(this.callbackContext);
  18705. }
  18706. },
  18707. /**
  18708. * Gamepad disconnect function, should be called by Phaser.Gamepad
  18709. * @method Phaser.SinglePad#disconnect
  18710. */
  18711. disconnect: function () {
  18712. var triggerCallback = this._connected;
  18713. this._connected = false;
  18714. this._rawPad = undefined;
  18715. this._rawButtons = [];
  18716. this._buttons = [];
  18717. var disconnectingIndex = this._index;
  18718. this._index = null;
  18719. if (triggerCallback && this._padParent.onDisconnectCallback)
  18720. {
  18721. this._padParent.onDisconnectCallback.call(this._padParent.callbackContext, disconnectingIndex);
  18722. }
  18723. if (triggerCallback && this.onDisconnectCallback)
  18724. {
  18725. this.onDisconnectCallback.call(this.callbackContext);
  18726. }
  18727. },
  18728. /**
  18729. * Handles changes in axis
  18730. * @method Phaser.SinglePad#processAxisChange
  18731. * @param {Object} axisState - State of the relevant axis
  18732. */
  18733. processAxisChange: function (axisState) {
  18734. if (this.game.input.disabled || this.game.input.gamepad.disabled)
  18735. {
  18736. return;
  18737. }
  18738. if (this._axes[axisState.axis] === axisState.value)
  18739. {
  18740. return;
  18741. }
  18742. this._axes[axisState.axis] = axisState.value;
  18743. if (this._padParent.onAxisCallback)
  18744. {
  18745. this._padParent.onAxisCallback.call(this._padParent.callbackContext, axisState, this._index);
  18746. }
  18747. if (this.onAxisCallback)
  18748. {
  18749. this.onAxisCallback.call(this.callbackContext, axisState);
  18750. }
  18751. },
  18752. /**
  18753. * Handles button down press
  18754. * @method Phaser.SinglePad#processButtonDown
  18755. * @param {number} buttonCode - Which buttonCode of this button
  18756. * @param {Object} value - Button value
  18757. */
  18758. processButtonDown: function (buttonCode, value) {
  18759. if (this.game.input.disabled || this.game.input.gamepad.disabled)
  18760. {
  18761. return;
  18762. }
  18763. if (this._padParent.onDownCallback)
  18764. {
  18765. this._padParent.onDownCallback.call(this._padParent.callbackContext, buttonCode, value, this._index);
  18766. }
  18767. if (this.onDownCallback)
  18768. {
  18769. this.onDownCallback.call(this.callbackContext, buttonCode, value);
  18770. }
  18771. if (this._buttons[buttonCode] && this._buttons[buttonCode].isDown)
  18772. {
  18773. // Key already down and still down, so update
  18774. this._buttons[buttonCode].duration = this.game.time.now - this._buttons[buttonCode].timeDown;
  18775. }
  18776. else
  18777. {
  18778. if (!this._buttons[buttonCode])
  18779. {
  18780. // Not used this button before, so register it
  18781. this._buttons[buttonCode] = {
  18782. isDown: true,
  18783. timeDown: this.game.time.now,
  18784. timeUp: 0,
  18785. duration: 0,
  18786. value: value
  18787. };
  18788. }
  18789. else
  18790. {
  18791. // Button used before but freshly down
  18792. this._buttons[buttonCode].isDown = true;
  18793. this._buttons[buttonCode].timeDown = this.game.time.now;
  18794. this._buttons[buttonCode].duration = 0;
  18795. this._buttons[buttonCode].value = value;
  18796. }
  18797. }
  18798. if (this._hotkeys[buttonCode])
  18799. {
  18800. this._hotkeys[buttonCode].processButtonDown(value);
  18801. }
  18802. },
  18803. /**
  18804. * Handles button release
  18805. * @method Phaser.SinglePad#processButtonUp
  18806. * @param {number} buttonCode - Which buttonCode of this button
  18807. * @param {Object} value - Button value
  18808. */
  18809. processButtonUp: function (buttonCode, value) {
  18810. if (this.game.input.disabled || this.game.input.gamepad.disabled)
  18811. {
  18812. return;
  18813. }
  18814. if (this._padParent.onUpCallback)
  18815. {
  18816. this._padParent.onUpCallback.call(this._padParent.callbackContext, buttonCode, value, this._index);
  18817. }
  18818. if (this.onUpCallback)
  18819. {
  18820. this.onUpCallback.call(this.callbackContext, buttonCode, value);
  18821. }
  18822. if (this._hotkeys[buttonCode])
  18823. {
  18824. this._hotkeys[buttonCode].processButtonUp(value);
  18825. }
  18826. if (this._buttons[buttonCode])
  18827. {
  18828. this._buttons[buttonCode].isDown = false;
  18829. this._buttons[buttonCode].timeUp = this.game.time.now;
  18830. this._buttons[buttonCode].value = value;
  18831. }
  18832. else
  18833. {
  18834. // Not used this button before, so register it
  18835. this._buttons[buttonCode] = {
  18836. isDown: false,
  18837. timeDown: this.game.time.now,
  18838. timeUp: this.game.time.now,
  18839. duration: 0,
  18840. value: value
  18841. };
  18842. }
  18843. },
  18844. /**
  18845. * Handles buttons with floating values (like analog buttons that acts almost like an axis but still registers like a button)
  18846. * @method Phaser.SinglePad#processButtonFloat
  18847. * @param {number} buttonCode - Which buttonCode of this button
  18848. * @param {Object} value - Button value (will range somewhere between 0 and 1, but not specifically 0 or 1.
  18849. */
  18850. processButtonFloat: function (buttonCode, value) {
  18851. if (this.game.input.disabled || this.game.input.gamepad.disabled)
  18852. {
  18853. return;
  18854. }
  18855. if (this._padParent.onFloatCallback)
  18856. {
  18857. this._padParent.onFloatCallback.call(this._padParent.callbackContext, buttonCode, value, this._index);
  18858. }
  18859. if (this.onFloatCallback)
  18860. {
  18861. this.onFloatCallback.call(this.callbackContext, buttonCode, value);
  18862. }
  18863. if (!this._buttons[buttonCode])
  18864. {
  18865. // Not used this button before, so register it
  18866. this._buttons[buttonCode] = { value: value };
  18867. }
  18868. else
  18869. {
  18870. // Button used before but freshly down
  18871. this._buttons[buttonCode].value = value;
  18872. }
  18873. if (this._hotkeys[buttonCode])
  18874. {
  18875. this._hotkeys[buttonCode].processButtonFloat(value);
  18876. }
  18877. },
  18878. /**
  18879. * Returns value of requested axis
  18880. * @method Phaser.SinglePad#axis
  18881. * @param {number} axisCode - The index of the axis to check
  18882. * @return {number} Axis value if available otherwise false
  18883. */
  18884. axis: function (axisCode) {
  18885. if (this._axes[axisCode])
  18886. {
  18887. return this._axes[axisCode];
  18888. }
  18889. return false;
  18890. },
  18891. /**
  18892. * Returns true if the button is currently pressed down.
  18893. * @method Phaser.SinglePad#isDown
  18894. * @param {number} buttonCode - The buttonCode of the key to check.
  18895. * @return {boolean} True if the key is currently down.
  18896. */
  18897. isDown: function (buttonCode) {
  18898. if (this._buttons[buttonCode])
  18899. {
  18900. return this._buttons[buttonCode].isDown;
  18901. }
  18902. return false;
  18903. },
  18904. /**
  18905. * Returns the "just released" state of a button from this gamepad. Just released is considered as being true if the button was released within the duration given (default 250ms).
  18906. * @method Phaser.SinglePad#justReleased
  18907. * @param {number} buttonCode - The buttonCode of the button to check for.
  18908. * @param {number} [duration=250] - The duration below which the button is considered as being just released.
  18909. * @return {boolean} True if the button is just released otherwise false.
  18910. */
  18911. justReleased: function (buttonCode, duration) {
  18912. if (typeof duration === "undefined") { duration = 250; }
  18913. return (this._buttons[buttonCode] && this._buttons[buttonCode].isDown === false && (this.game.time.now - this._buttons[buttonCode].timeUp < duration));
  18914. },
  18915. /**
  18916. * Returns the "just pressed" state of a button from this gamepad. Just pressed is considered true if the button was pressed down within the duration given (default 250ms).
  18917. * @method Phaser.SinglePad#justPressed
  18918. * @param {number} buttonCode - The buttonCode of the button to check for.
  18919. * @param {number} [duration=250] - The duration below which the button is considered as being just pressed.
  18920. * @return {boolean} True if the button is just pressed otherwise false.
  18921. */
  18922. justPressed: function (buttonCode, duration) {
  18923. if (typeof duration === "undefined") { duration = 250; }
  18924. return (this._buttons[buttonCode] && this._buttons[buttonCode].isDown && this._buttons[buttonCode].duration < duration);
  18925. },
  18926. /**
  18927. * Returns the value of a gamepad button. Intended mainly for cases when you have floating button values, for example
  18928. * analog trigger buttons on the XBOX 360 controller
  18929. * @method Phaser.SinglePad#buttonValue
  18930. * @param {number} buttonCode - The buttonCode of the button to check.
  18931. * @return {boolean} Button value if available otherwise false.
  18932. */
  18933. buttonValue: function (buttonCode) {
  18934. if (this._buttons[buttonCode])
  18935. {
  18936. return this._buttons[buttonCode].value;
  18937. }
  18938. return false;
  18939. },
  18940. /**
  18941. * Reset all buttons/axes of this gamepad
  18942. * @method Phaser.SinglePad#reset
  18943. */
  18944. reset: function () {
  18945. for (var i = 0; i < this._buttons.length; i++)
  18946. {
  18947. this._buttons[i] = 0;
  18948. }
  18949. for (var j = 0; j < this._axes.length; j++)
  18950. {
  18951. this._axes[j] = 0;
  18952. }
  18953. }
  18954. };
  18955. Phaser.SinglePad.prototype.constructor = Phaser.SinglePad;
  18956. /**
  18957. * Whether or not this particular gamepad is connected or not.
  18958. * @name Phaser.SinglePad#connected
  18959. * @property {boolean} connected - Whether or not this particular gamepad is connected or not.
  18960. * @readonly
  18961. */
  18962. Object.defineProperty(Phaser.SinglePad.prototype, "connected", {
  18963. get: function () {
  18964. return this._connected;
  18965. }
  18966. });
  18967. /**
  18968. * Gamepad index as per browser data
  18969. * @name Phaser.SinglePad#index
  18970. * @property {number} index - The gamepad index, used to identify specific gamepads in the browser
  18971. * @readonly
  18972. */
  18973. Object.defineProperty(Phaser.SinglePad.prototype, "index", {
  18974. get: function () {
  18975. return this._index;
  18976. }
  18977. });
  18978. /**
  18979. * @author @karlmacklin <tacklemcclean@gmail.com>
  18980. * @copyright 2014 Photon Storm Ltd.
  18981. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  18982. */
  18983. /**
  18984. * @class Phaser.GamepadButton
  18985. * @classdesc If you need more fine-grained control over the handling of specific buttons you can create and use Phaser.GamepadButton objects.
  18986. * @constructor
  18987. * @param {Phaser.Game} game - Current game instance.
  18988. * @param {number} buttoncode - The button code this GamepadButton is responsible for.
  18989. */
  18990. Phaser.GamepadButton = function (game, buttoncode) {
  18991. /**
  18992. * @property {Phaser.Game} game - A reference to the currently running game.
  18993. */
  18994. this.game = game;
  18995. /**
  18996. * @property {boolean} isDown - The "down" state of the button.
  18997. * @default
  18998. */
  18999. this.isDown = false;
  19000. /**
  19001. * @property {boolean} isUp - The "up" state of the button.
  19002. * @default
  19003. */
  19004. this.isUp = true;
  19005. /**
  19006. * @property {number} timeDown - The timestamp when the button was last pressed down.
  19007. * @default
  19008. */
  19009. this.timeDown = 0;
  19010. /**
  19011. * If the button is down this value holds the duration of that button press and is constantly updated.
  19012. * If the button is up it holds the duration of the previous down session.
  19013. * @property {number} duration - The number of milliseconds this button has been held down for.
  19014. * @default
  19015. */
  19016. this.duration = 0;
  19017. /**
  19018. * @property {number} timeUp - The timestamp when the button was last released.
  19019. * @default
  19020. */
  19021. this.timeUp = 0;
  19022. /**
  19023. * @property {number} repeats - If a button is held down this holds down the number of times the button has 'repeated'.
  19024. * @default
  19025. */
  19026. this.repeats = 0;
  19027. /**
  19028. * @property {number} value - Button value. Mainly useful for checking analog buttons (like shoulder triggers)
  19029. * @default
  19030. */
  19031. this.value = 0;
  19032. /**
  19033. * @property {number} buttonCode - The buttoncode of this button.
  19034. */
  19035. this.buttonCode = buttoncode;
  19036. /**
  19037. * @property {Phaser.Signal} onDown - This Signal is dispatched every time this GamepadButton is pressed down. It is only dispatched once (until the button is released again).
  19038. */
  19039. this.onDown = new Phaser.Signal();
  19040. /**
  19041. * @property {Phaser.Signal} onUp - This Signal is dispatched every time this GamepadButton is pressed down. It is only dispatched once (until the button is released again).
  19042. */
  19043. this.onUp = new Phaser.Signal();
  19044. /**
  19045. * @property {Phaser.Signal} onFloat - This Signal is dispatched every time this GamepadButton changes floating value (between (but not exactly) 0 and 1)
  19046. */
  19047. this.onFloat = new Phaser.Signal();
  19048. };
  19049. Phaser.GamepadButton.prototype = {
  19050. /**
  19051. * Called automatically by Phaser.SinglePad.
  19052. * @method Phaser.GamepadButton#processButtonDown
  19053. * @param {Object} value - Button value
  19054. * @protected
  19055. */
  19056. processButtonDown: function (value) {
  19057. if (this.isDown)
  19058. {
  19059. this.duration = this.game.time.now - this.timeDown;
  19060. this.repeats++;
  19061. }
  19062. else
  19063. {
  19064. this.isDown = true;
  19065. this.isUp = false;
  19066. this.timeDown = this.game.time.now;
  19067. this.duration = 0;
  19068. this.repeats = 0;
  19069. this.value = value;
  19070. this.onDown.dispatch(this, value);
  19071. }
  19072. },
  19073. /**
  19074. * Called automatically by Phaser.SinglePad.
  19075. * @method Phaser.GamepadButton#processButtonUp
  19076. * @param {Object} value - Button value
  19077. * @protected
  19078. */
  19079. processButtonUp: function (value) {
  19080. this.isDown = false;
  19081. this.isUp = true;
  19082. this.timeUp = this.game.time.now;
  19083. this.value = value;
  19084. this.onUp.dispatch(this, value);
  19085. },
  19086. /**
  19087. * Called automatically by Phaser.Gamepad.
  19088. * @method Phaser.GamepadButton#processButtonFloat
  19089. * @param {Object} value - Button value
  19090. * @protected
  19091. */
  19092. processButtonFloat: function (value) {
  19093. this.value = value;
  19094. this.onFloat.dispatch(this, value);
  19095. },
  19096. /**
  19097. * Returns the "just pressed" state of this button. Just pressed is considered true if the button was pressed down within the duration given (default 250ms).
  19098. * @method Phaser.GamepadButton#justPressed
  19099. * @param {number} [duration=250] - The duration below which the button is considered as being just pressed.
  19100. * @return {boolean} True if the button is just pressed otherwise false.
  19101. */
  19102. justPressed: function (duration) {
  19103. if (typeof duration === "undefined") { duration = 250; }
  19104. return (this.isDown && this.duration < duration);
  19105. },
  19106. /**
  19107. * Returns the "just released" state of this button. Just released is considered as being true if the button was released within the duration given (default 250ms).
  19108. * @method Phaser.GamepadButton#justPressed
  19109. * @param {number} [duration=250] - The duration below which the button is considered as being just released.
  19110. * @return {boolean} True if the button is just pressed otherwise false.
  19111. */
  19112. justReleased: function (duration) {
  19113. if (typeof duration === "undefined") { duration = 250; }
  19114. return (this.isDown === false && (this.game.time.now - this.timeUp < duration));
  19115. }
  19116. };
  19117. Phaser.GamepadButton.prototype.constructor = Phaser.GamepadButton;
  19118. /**
  19119. * @author Richard Davey <rich@photonstorm.com>
  19120. * @copyright 2014 Photon Storm Ltd.
  19121. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  19122. */
  19123. /**
  19124. * The Input Handler is bound to a specific Sprite and is responsible for managing all Input events on that Sprite.
  19125. * @class Phaser.InputHandler
  19126. * @constructor
  19127. * @param {Phaser.Sprite} sprite - The Sprite object to which this Input Handler belongs.
  19128. */
  19129. Phaser.InputHandler = function (sprite) {
  19130. /**
  19131. * @property {Phaser.Sprite} sprite - The Sprite object to which this Input Handler belongs.
  19132. */
  19133. this.sprite = sprite;
  19134. /**
  19135. * @property {Phaser.Game} game - A reference to the currently running game.
  19136. */
  19137. this.game = sprite.game;
  19138. /**
  19139. * @property {boolean} enabled - If enabled the Input Handler will process input requests and monitor pointer activity.
  19140. * @default
  19141. */
  19142. this.enabled = false;
  19143. /**
  19144. * @property {number} priorityID - The PriorityID controls which Sprite receives an Input event first if they should overlap.
  19145. * @default
  19146. */
  19147. this.priorityID = 0;
  19148. /**
  19149. * @property {boolean} useHandCursor - On a desktop browser you can set the 'hand' cursor to appear when moving over the Sprite.
  19150. * @default
  19151. */
  19152. this.useHandCursor = false;
  19153. /**
  19154. * @property {boolean} _setHandCursor - Did this Sprite trigger the hand cursor?
  19155. * @private
  19156. */
  19157. this._setHandCursor = false;
  19158. /**
  19159. * @property {boolean} isDragged - true if the Sprite is being currently dragged.
  19160. * @default
  19161. */
  19162. this.isDragged = false;
  19163. /**
  19164. * @property {boolean} allowHorizontalDrag - Controls if the Sprite is allowed to be dragged horizontally.
  19165. * @default
  19166. */
  19167. this.allowHorizontalDrag = true;
  19168. /**
  19169. * @property {boolean} allowVerticalDrag - Controls if the Sprite is allowed to be dragged vertically.
  19170. * @default
  19171. */
  19172. this.allowVerticalDrag = true;
  19173. /**
  19174. * @property {boolean} bringToTop - If true when this Sprite is clicked or dragged it will automatically be bought to the top of the Group it is within.
  19175. * @default
  19176. */
  19177. this.bringToTop = false;
  19178. /**
  19179. * @property {Phaser.Point} snapOffset - A Point object that contains by how far the Sprite snap is offset.
  19180. * @default
  19181. */
  19182. this.snapOffset = null;
  19183. /**
  19184. * @property {boolean} snapOnDrag - When the Sprite is dragged this controls if the center of the Sprite will snap to the pointer on drag or not.
  19185. * @default
  19186. */
  19187. this.snapOnDrag = false;
  19188. /**
  19189. * @property {boolean} snapOnRelease - When the Sprite is dragged this controls if the Sprite will be snapped on release.
  19190. * @default
  19191. */
  19192. this.snapOnRelease = false;
  19193. /**
  19194. * @property {number} snapX - When a Sprite has snapping enabled this holds the width of the snap grid.
  19195. * @default
  19196. */
  19197. this.snapX = 0;
  19198. /**
  19199. * @property {number} snapY - When a Sprite has snapping enabled this holds the height of the snap grid.
  19200. * @default
  19201. */
  19202. this.snapY = 0;
  19203. /**
  19204. * @property {number} snapOffsetX - This defines the top-left X coordinate of the snap grid.
  19205. * @default
  19206. */
  19207. this.snapOffsetX = 0;
  19208. /**
  19209. * @property {number} snapOffsetY - This defines the top-left Y coordinate of the snap grid..
  19210. * @default
  19211. */
  19212. this.snapOffsetY = 0;
  19213. /**
  19214. * Set to true to use pixel perfect hit detection when checking if the pointer is over this Sprite.
  19215. * The x/y coordinates of the pointer are tested against the image in combination with the InputHandler.pixelPerfectAlpha value.
  19216. * Warning: This is expensive, especially on mobile (where it's not even needed!) so only enable if required. Also see the less-expensive InputHandler.pixelPerfectClick.
  19217. * @property {number} pixelPerfectOver - Use a pixel perfect check when testing for pointer over.
  19218. * @default
  19219. */
  19220. this.pixelPerfectOver = false;
  19221. /**
  19222. * Set to true to use pixel perfect hit detection when checking if the pointer is over this Sprite when it's clicked or touched.
  19223. * The x/y coordinates of the pointer are tested against the image in combination with the InputHandler.pixelPerfectAlpha value.
  19224. * Warning: This is expensive so only enable if you really need it.
  19225. * @property {number} pixelPerfectClick - Use a pixel perfect check when testing for clicks or touches on the Sprite.
  19226. * @default
  19227. */
  19228. this.pixelPerfectClick = false;
  19229. /**
  19230. * @property {number} pixelPerfectAlpha - The alpha tolerance threshold. If the alpha value of the pixel matches or is above this value, it's considered a hit.
  19231. * @default
  19232. */
  19233. this.pixelPerfectAlpha = 255;
  19234. /**
  19235. * @property {boolean} draggable - Is this sprite allowed to be dragged by the mouse? true = yes, false = no
  19236. * @default
  19237. */
  19238. this.draggable = false;
  19239. /**
  19240. * @property {Phaser.Rectangle} boundsRect - A region of the game world within which the sprite is restricted during drag.
  19241. * @default
  19242. */
  19243. this.boundsRect = null;
  19244. /**
  19245. * @property {Phaser.Sprite} boundsSprite - A Sprite the bounds of which this sprite is restricted during drag.
  19246. * @default
  19247. */
  19248. this.boundsSprite = null;
  19249. /**
  19250. * If this object is set to consume the pointer event then it will stop all propogation from this object on.
  19251. * For example if you had a stack of 6 sprites with the same priority IDs and one consumed the event, none of the others would receive it.
  19252. * @property {boolean} consumePointerEvent
  19253. * @default
  19254. */
  19255. this.consumePointerEvent = false;
  19256. /**
  19257. * @property {boolean} _wasEnabled - Internal cache var.
  19258. * @private
  19259. */
  19260. this._wasEnabled = false;
  19261. /**
  19262. * @property {Phaser.Point} _tempPoint - Internal cache var.
  19263. * @private
  19264. */
  19265. this._tempPoint = new Phaser.Point();
  19266. /**
  19267. * @property {array} _pointerData - Internal cache var.
  19268. * @private
  19269. */
  19270. this._pointerData = [];
  19271. this._pointerData.push({
  19272. id: 0,
  19273. x: 0,
  19274. y: 0,
  19275. isDown: false,
  19276. isUp: false,
  19277. isOver: false,
  19278. isOut: false,
  19279. timeOver: 0,
  19280. timeOut: 0,
  19281. timeDown: 0,
  19282. timeUp: 0,
  19283. downDuration: 0,
  19284. isDragged: false
  19285. });
  19286. };
  19287. Phaser.InputHandler.prototype = {
  19288. /**
  19289. * Starts the Input Handler running. This is called automatically when you enable input on a Sprite, or can be called directly if you need to set a specific priority.
  19290. * @method Phaser.InputHandler#start
  19291. * @param {number} priority - Higher priority sprites take click priority over low-priority sprites when they are stacked on-top of each other.
  19292. * @param {boolean} useHandCursor - If true the Sprite will show the hand cursor on mouse-over (doesn't apply to mobile browsers)
  19293. * @return {Phaser.Sprite} The Sprite object to which the Input Handler is bound.
  19294. */
  19295. start: function (priority, useHandCursor) {
  19296. priority = priority || 0;
  19297. if (typeof useHandCursor == 'undefined') { useHandCursor = false; }
  19298. // Turning on
  19299. if (this.enabled === false)
  19300. {
  19301. // Register, etc
  19302. this.game.input.interactiveItems.add(this);
  19303. this.useHandCursor = useHandCursor;
  19304. this.priorityID = priority;
  19305. for (var i = 0; i < 10; i++)
  19306. {
  19307. this._pointerData[i] = {
  19308. id: i,
  19309. x: 0,
  19310. y: 0,
  19311. isDown: false,
  19312. isUp: false,
  19313. isOver: false,
  19314. isOut: false,
  19315. timeOver: 0,
  19316. timeOut: 0,
  19317. timeDown: 0,
  19318. timeUp: 0,
  19319. downDuration: 0,
  19320. isDragged: false
  19321. };
  19322. }
  19323. this.snapOffset = new Phaser.Point();
  19324. this.enabled = true;
  19325. this._wasEnabled = true;
  19326. // Create the signals the Input component will emit
  19327. if (this.sprite.events && this.sprite.events.onInputOver === null)
  19328. {
  19329. this.sprite.events.onInputOver = new Phaser.Signal();
  19330. this.sprite.events.onInputOut = new Phaser.Signal();
  19331. this.sprite.events.onInputDown = new Phaser.Signal();
  19332. this.sprite.events.onInputUp = new Phaser.Signal();
  19333. this.sprite.events.onDragStart = new Phaser.Signal();
  19334. this.sprite.events.onDragStop = new Phaser.Signal();
  19335. }
  19336. }
  19337. this.sprite.events.onAddedToGroup.add(this.addedToGroup, this);
  19338. this.sprite.events.onRemovedFromGroup.add(this.removedFromGroup, this);
  19339. return this.sprite;
  19340. },
  19341. /**
  19342. * Handles when the parent Sprite is added to a new Group.
  19343. *
  19344. * @method Phaser.InputHandler#addedToGroup
  19345. * @private
  19346. */
  19347. addedToGroup: function () {
  19348. if (this._wasEnabled && !this.enabled)
  19349. {
  19350. this.start();
  19351. }
  19352. },
  19353. /**
  19354. * Handles when the parent Sprite is removed from a Group.
  19355. *
  19356. * @method Phaser.InputHandler#removedFromGroup
  19357. * @private
  19358. */
  19359. removedFromGroup: function () {
  19360. if (this.enabled)
  19361. {
  19362. this._wasEnabled = true;
  19363. this.stop();
  19364. }
  19365. else
  19366. {
  19367. this._wasEnabled = false;
  19368. }
  19369. },
  19370. /**
  19371. * Resets the Input Handler and disables it.
  19372. * @method Phaser.InputHandler#reset
  19373. */
  19374. reset: function () {
  19375. this.enabled = false;
  19376. for (var i = 0; i < 10; i++)
  19377. {
  19378. this._pointerData[i] = {
  19379. id: i,
  19380. x: 0,
  19381. y: 0,
  19382. isDown: false,
  19383. isUp: false,
  19384. isOver: false,
  19385. isOut: false,
  19386. timeOver: 0,
  19387. timeOut: 0,
  19388. timeDown: 0,
  19389. timeUp: 0,
  19390. downDuration: 0,
  19391. isDragged: false
  19392. };
  19393. }
  19394. },
  19395. /**
  19396. * Stops the Input Handler from running.
  19397. * @method Phaser.InputHandler#stop
  19398. */
  19399. stop: function () {
  19400. // Turning off
  19401. if (this.enabled === false)
  19402. {
  19403. return;
  19404. }
  19405. else
  19406. {
  19407. // De-register, etc
  19408. this.enabled = false;
  19409. this.game.input.interactiveItems.remove(this);
  19410. }
  19411. },
  19412. /**
  19413. * Clean up memory.
  19414. * @method Phaser.InputHandler#destroy
  19415. */
  19416. destroy: function () {
  19417. if (this.enabled)
  19418. {
  19419. if (this._setHandCursor)
  19420. {
  19421. this.game.canvas.style.cursor = "default";
  19422. this._setHandCursor = false;
  19423. }
  19424. this.enabled = false;
  19425. this.game.input.interactiveItems.remove(this);
  19426. this._pointerData.length = 0;
  19427. this.boundsRect = null;
  19428. this.boundsSprite = null;
  19429. this.sprite = null;
  19430. }
  19431. },
  19432. /**
  19433. * Checks if the object this InputHandler is bound to is valid for consideration in the Pointer move event.
  19434. * This is called by Phaser.Pointer and shouldn't typically be called directly.
  19435. *
  19436. * @method Phaser.InputHandler#validForInput
  19437. * @protected
  19438. * @param {number} highestID - The highest ID currently processed by the Pointer.
  19439. * @param {number} highestRenderID - The highest Render Order ID currently processed by the Pointer.
  19440. * @return {boolean} True if the object this InputHandler is bound to should be considered as valid for input detection.
  19441. */
  19442. validForInput: function (highestID, highestRenderID) {
  19443. if (this.sprite.scale.x === 0 || this.sprite.scale.y === 0)
  19444. {
  19445. return false;
  19446. }
  19447. if (this.pixelPerfectClick || this.pixelPerfectOver)
  19448. {
  19449. return true;
  19450. }
  19451. if (this.priorityID > highestID || (this.priorityID === highestID && this.sprite._cache[3] < highestRenderID))
  19452. {
  19453. return true;
  19454. }
  19455. return false;
  19456. },
  19457. /**
  19458. * The x coordinate of the Input pointer, relative to the top-left of the parent Sprite.
  19459. * This value is only set when the pointer is over this Sprite.
  19460. * @method Phaser.InputHandler#pointerX
  19461. * @param {Phaser.Pointer} pointer
  19462. * @return {number} The x coordinate of the Input pointer.
  19463. */
  19464. pointerX: function (pointer) {
  19465. pointer = pointer || 0;
  19466. return this._pointerData[pointer].x;
  19467. },
  19468. /**
  19469. * The y coordinate of the Input pointer, relative to the top-left of the parent Sprite
  19470. * This value is only set when the pointer is over this Sprite.
  19471. * @method Phaser.InputHandler#pointerY
  19472. * @param {Phaser.Pointer} pointer
  19473. * @return {number} The y coordinate of the Input pointer.
  19474. */
  19475. pointerY: function (pointer) {
  19476. pointer = pointer || 0;
  19477. return this._pointerData[pointer].y;
  19478. },
  19479. /**
  19480. * If the Pointer is touching the touchscreen, or the mouse button is held down, isDown is set to true.
  19481. * @method Phaser.InputHandler#pointerDown
  19482. * @param {Phaser.Pointer} pointer
  19483. * @return {boolean}
  19484. */
  19485. pointerDown: function (pointer) {
  19486. pointer = pointer || 0;
  19487. return this._pointerData[pointer].isDown;
  19488. },
  19489. /**
  19490. * If the Pointer is not touching the touchscreen, or the mouse button is up, isUp is set to true
  19491. * @method Phaser.InputHandler#pointerUp
  19492. * @param {Phaser.Pointer} pointer
  19493. * @return {boolean}
  19494. */
  19495. pointerUp: function (pointer) {
  19496. pointer = pointer || 0;
  19497. return this._pointerData[pointer].isUp;
  19498. },
  19499. /**
  19500. * A timestamp representing when the Pointer first touched the touchscreen.
  19501. * @method Phaser.InputHandler#pointerTimeDown
  19502. * @param {Phaser.Pointer} pointer
  19503. * @return {number}
  19504. */
  19505. pointerTimeDown: function (pointer) {
  19506. pointer = pointer || 0;
  19507. return this._pointerData[pointer].timeDown;
  19508. },
  19509. /**
  19510. * A timestamp representing when the Pointer left the touchscreen.
  19511. * @method Phaser.InputHandler#pointerTimeUp
  19512. * @param {Phaser.Pointer} pointer
  19513. * @return {number}
  19514. */
  19515. pointerTimeUp: function (pointer) {
  19516. pointer = pointer || 0;
  19517. return this._pointerData[pointer].timeUp;
  19518. },
  19519. /**
  19520. * Is the Pointer over this Sprite?
  19521. * @method Phaser.InputHandler#pointerOver
  19522. * @param {number} [index] - The ID number of a Pointer to check. If you don't provide a number it will check all Pointers.
  19523. * @return {boolean} True if the given pointer (if a index was given, or any pointer if not) is over this object.
  19524. */
  19525. pointerOver: function (index) {
  19526. if (this.enabled)
  19527. {
  19528. if (typeof index === 'undefined')
  19529. {
  19530. for (var i = 0; i < 10; i++)
  19531. {
  19532. if (this._pointerData[i].isOver)
  19533. {
  19534. return true;
  19535. }
  19536. }
  19537. }
  19538. else
  19539. {
  19540. return this._pointerData[index].isOver;
  19541. }
  19542. }
  19543. return false;
  19544. },
  19545. /**
  19546. * Is the Pointer outside of this Sprite?
  19547. * @method Phaser.InputHandler#pointerOut
  19548. * @param {number} [index] - The ID number of a Pointer to check. If you don't provide a number it will check all Pointers.
  19549. * @return {boolean} True if the given pointer (if a index was given, or any pointer if not) is out of this object.
  19550. */
  19551. pointerOut: function (index) {
  19552. if (this.enabled)
  19553. {
  19554. if (typeof index === 'undefined')
  19555. {
  19556. for (var i = 0; i < 10; i++)
  19557. {
  19558. if (this._pointerData[i].isOut)
  19559. {
  19560. return true;
  19561. }
  19562. }
  19563. }
  19564. else
  19565. {
  19566. return this._pointerData[index].isOut;
  19567. }
  19568. }
  19569. return false;
  19570. },
  19571. /**
  19572. * A timestamp representing when the Pointer first touched the touchscreen.
  19573. * @method Phaser.InputHandler#pointerTimeOver
  19574. * @param {Phaser.Pointer} pointer
  19575. * @return {number}
  19576. */
  19577. pointerTimeOver: function (pointer) {
  19578. pointer = pointer || 0;
  19579. return this._pointerData[pointer].timeOver;
  19580. },
  19581. /**
  19582. * A timestamp representing when the Pointer left the touchscreen.
  19583. * @method Phaser.InputHandler#pointerTimeOut
  19584. * @param {Phaser.Pointer} pointer
  19585. * @return {number}
  19586. */
  19587. pointerTimeOut: function (pointer) {
  19588. pointer = pointer || 0;
  19589. return this._pointerData[pointer].timeOut;
  19590. },
  19591. /**
  19592. * Is this sprite being dragged by the mouse or not?
  19593. * @method Phaser.InputHandler#pointerDragged
  19594. * @param {Phaser.Pointer} pointer
  19595. * @return {boolean} True if the pointer is dragging an object, otherwise false.
  19596. */
  19597. pointerDragged: function (pointer) {
  19598. pointer = pointer || 0;
  19599. return this._pointerData[pointer].isDragged;
  19600. },
  19601. /**
  19602. * Checks if the given pointer is over this Sprite and can click it.
  19603. * @method Phaser.InputHandler#checkPointerDown
  19604. * @param {Phaser.Pointer} pointer
  19605. * @return {boolean} True if the pointer is down, otherwise false.
  19606. */
  19607. checkPointerDown: function (pointer) {
  19608. if (!this.enabled || !this.sprite || !this.sprite.parent || !this.sprite.visible || !this.sprite.parent.visible)
  19609. {
  19610. return false;
  19611. }
  19612. // Need to pass it a temp point, in case we need it again for the pixel check
  19613. if (this.game.input.hitTest(this.sprite, pointer, this._tempPoint))
  19614. {
  19615. if (this.pixelPerfectClick)
  19616. {
  19617. return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
  19618. }
  19619. else
  19620. {
  19621. return true;
  19622. }
  19623. }
  19624. return false;
  19625. },
  19626. /**
  19627. * Checks if the given pointer is over this Sprite.
  19628. * @method Phaser.InputHandler#checkPointerOver
  19629. * @param {Phaser.Pointer} pointer
  19630. * @return {boolean}
  19631. */
  19632. checkPointerOver: function (pointer) {
  19633. if (!this.enabled || !this.sprite || !this.sprite.parent || !this.sprite.visible || !this.sprite.parent.visible)
  19634. {
  19635. return false;
  19636. }
  19637. // Need to pass it a temp point, in case we need it again for the pixel check
  19638. if (this.game.input.hitTest(this.sprite, pointer, this._tempPoint))
  19639. {
  19640. if (this.pixelPerfectOver)
  19641. {
  19642. return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
  19643. }
  19644. else
  19645. {
  19646. return true;
  19647. }
  19648. }
  19649. return false;
  19650. },
  19651. /**
  19652. * Runs a pixel perfect check against the given x/y coordinates of the Sprite this InputHandler is bound to.
  19653. * It compares the alpha value of the pixel and if >= InputHandler.pixelPerfectAlpha it returns true.
  19654. * @method Phaser.InputHandler#checkPixel
  19655. * @param {number} x - The x coordinate to check.
  19656. * @param {number} y - The y coordinate to check.
  19657. * @param {Phaser.Pointer} [pointer] - The pointer to get the x/y coordinate from if not passed as the first two parameters.
  19658. * @return {boolean} true if there is the alpha of the pixel is >= InputHandler.pixelPerfectAlpha
  19659. */
  19660. checkPixel: function (x, y, pointer) {
  19661. // Grab a pixel from our image into the hitCanvas and then test it
  19662. if (this.sprite.texture.baseTexture.source)
  19663. {
  19664. this.game.input.hitContext.clearRect(0, 0, 1, 1);
  19665. if (x === null && y === null)
  19666. {
  19667. // Use the pointer parameter
  19668. this.game.input.getLocalPosition(this.sprite, pointer, this._tempPoint);
  19669. var x = this._tempPoint.x;
  19670. var y = this._tempPoint.y;
  19671. }
  19672. if (this.sprite.anchor.x !== 0)
  19673. {
  19674. x -= -this.sprite.texture.frame.width * this.sprite.anchor.x;
  19675. }
  19676. if (this.sprite.anchor.y !== 0)
  19677. {
  19678. y -= -this.sprite.texture.frame.height * this.sprite.anchor.y;
  19679. }
  19680. x += this.sprite.texture.frame.x;
  19681. y += this.sprite.texture.frame.y;
  19682. this.game.input.hitContext.drawImage(this.sprite.texture.baseTexture.source, x, y, 1, 1, 0, 0, 1, 1);
  19683. var rgb = this.game.input.hitContext.getImageData(0, 0, 1, 1);
  19684. if (rgb.data[3] >= this.pixelPerfectAlpha)
  19685. {
  19686. return true;
  19687. }
  19688. }
  19689. return false;
  19690. },
  19691. /**
  19692. * Update.
  19693. * @method Phaser.InputHandler#update
  19694. * @protected
  19695. * @param {Phaser.Pointer} pointer
  19696. */
  19697. update: function (pointer) {
  19698. if (this.sprite === null || this.sprite.parent === undefined)
  19699. {
  19700. // Abort. We've been destroyed.
  19701. return;
  19702. }
  19703. if (!this.enabled || !this.sprite.visible || !this.sprite.parent.visible)
  19704. {
  19705. this._pointerOutHandler(pointer);
  19706. return false;
  19707. }
  19708. if (this.draggable && this._draggedPointerID == pointer.id)
  19709. {
  19710. return this.updateDrag(pointer);
  19711. }
  19712. else if (this._pointerData[pointer.id].isOver === true)
  19713. {
  19714. if (this.checkPointerOver(pointer))
  19715. {
  19716. this._pointerData[pointer.id].x = pointer.x - this.sprite.x;
  19717. this._pointerData[pointer.id].y = pointer.y - this.sprite.y;
  19718. return true;
  19719. }
  19720. else
  19721. {
  19722. this._pointerOutHandler(pointer);
  19723. return false;
  19724. }
  19725. }
  19726. },
  19727. /**
  19728. * Internal method handling the pointer over event.
  19729. * @method Phaser.InputHandler#_pointerOverHandler
  19730. * @private
  19731. * @param {Phaser.Pointer} pointer
  19732. */
  19733. _pointerOverHandler: function (pointer) {
  19734. if (this.sprite === null)
  19735. {
  19736. // Abort. We've been destroyed.
  19737. return;
  19738. }
  19739. if (this._pointerData[pointer.id].isOver === false)
  19740. {
  19741. this._pointerData[pointer.id].isOver = true;
  19742. this._pointerData[pointer.id].isOut = false;
  19743. this._pointerData[pointer.id].timeOver = this.game.time.now;
  19744. this._pointerData[pointer.id].x = pointer.x - this.sprite.x;
  19745. this._pointerData[pointer.id].y = pointer.y - this.sprite.y;
  19746. if (this.useHandCursor && this._pointerData[pointer.id].isDragged === false)
  19747. {
  19748. this.game.canvas.style.cursor = "pointer";
  19749. this._setHandCursor = false;
  19750. }
  19751. this.sprite.events.onInputOver.dispatch(this.sprite, pointer);
  19752. }
  19753. },
  19754. /**
  19755. * Internal method handling the pointer out event.
  19756. * @method Phaser.InputHandler#_pointerOutHandler
  19757. * @private
  19758. * @param {Phaser.Pointer} pointer
  19759. */
  19760. _pointerOutHandler: function (pointer) {
  19761. if (this.sprite === null)
  19762. {
  19763. // Abort. We've been destroyed.
  19764. return;
  19765. }
  19766. this._pointerData[pointer.id].isOver = false;
  19767. this._pointerData[pointer.id].isOut = true;
  19768. this._pointerData[pointer.id].timeOut = this.game.time.now;
  19769. if (this.useHandCursor && this._pointerData[pointer.id].isDragged === false)
  19770. {
  19771. this.game.canvas.style.cursor = "default";
  19772. this._setHandCursor = false;
  19773. }
  19774. if (this.sprite && this.sprite.events)
  19775. {
  19776. this.sprite.events.onInputOut.dispatch(this.sprite, pointer);
  19777. }
  19778. },
  19779. /**
  19780. * Internal method handling the touched event.
  19781. * @method Phaser.InputHandler#_touchedHandler
  19782. * @private
  19783. * @param {Phaser.Pointer} pointer
  19784. */
  19785. _touchedHandler: function (pointer) {
  19786. if (this.sprite === null)
  19787. {
  19788. // Abort. We've been destroyed.
  19789. return;
  19790. }
  19791. if (this._pointerData[pointer.id].isDown === false && this._pointerData[pointer.id].isOver === true)
  19792. {
  19793. if (this.pixelPerfectClick && !this.checkPixel(null, null, pointer))
  19794. {
  19795. return;
  19796. }
  19797. this._pointerData[pointer.id].isDown = true;
  19798. this._pointerData[pointer.id].isUp = false;
  19799. this._pointerData[pointer.id].timeDown = this.game.time.now;
  19800. this.sprite.events.onInputDown.dispatch(this.sprite, pointer);
  19801. // Start drag
  19802. if (this.draggable && this.isDragged === false)
  19803. {
  19804. this.startDrag(pointer);
  19805. }
  19806. if (this.bringToTop)
  19807. {
  19808. this.sprite.bringToTop();
  19809. }
  19810. }
  19811. // Consume the event?
  19812. return this.consumePointerEvent;
  19813. },
  19814. /**
  19815. * Internal method handling the pointer released event.
  19816. * @method Phaser.InputHandler#_releasedHandler
  19817. * @private
  19818. * @param {Phaser.Pointer} pointer
  19819. */
  19820. _releasedHandler: function (pointer) {
  19821. if (this.sprite === null)
  19822. {
  19823. // Abort. We've been destroyed.
  19824. return;
  19825. }
  19826. // If was previously touched by this Pointer, check if still is AND still over this item
  19827. if (this._pointerData[pointer.id].isDown && pointer.isUp)
  19828. {
  19829. this._pointerData[pointer.id].isDown = false;
  19830. this._pointerData[pointer.id].isUp = true;
  19831. this._pointerData[pointer.id].timeUp = this.game.time.now;
  19832. this._pointerData[pointer.id].downDuration = this._pointerData[pointer.id].timeUp - this._pointerData[pointer.id].timeDown;
  19833. // Only release the InputUp signal if the pointer is still over this sprite
  19834. if (this.checkPointerOver(pointer))
  19835. {
  19836. // Release the inputUp signal and provide optional parameter if pointer is still over the sprite or not
  19837. this.sprite.events.onInputUp.dispatch(this.sprite, pointer, true);
  19838. }
  19839. else
  19840. {
  19841. // Release the inputUp signal and provide optional parameter if pointer is still over the sprite or not
  19842. this.sprite.events.onInputUp.dispatch(this.sprite, pointer, false);
  19843. // Pointer outside the sprite? Reset the cursor
  19844. if (this.useHandCursor)
  19845. {
  19846. this.game.canvas.style.cursor = "default";
  19847. this._setHandCursor = false;
  19848. }
  19849. }
  19850. // Stop drag
  19851. if (this.draggable && this.isDragged && this._draggedPointerID == pointer.id)
  19852. {
  19853. this.stopDrag(pointer);
  19854. }
  19855. }
  19856. },
  19857. /**
  19858. * Updates the Pointer drag on this Sprite.
  19859. * @method Phaser.InputHandler#updateDrag
  19860. * @param {Phaser.Pointer} pointer
  19861. * @return {boolean}
  19862. */
  19863. updateDrag: function (pointer) {
  19864. if (pointer.isUp)
  19865. {
  19866. this.stopDrag(pointer);
  19867. return false;
  19868. }
  19869. if (this.sprite.fixedToCamera)
  19870. {
  19871. if (this.allowHorizontalDrag)
  19872. {
  19873. this.sprite.cameraOffset.x = pointer.x + this._dragPoint.x + this.dragOffset.x;
  19874. }
  19875. if (this.allowVerticalDrag)
  19876. {
  19877. this.sprite.cameraOffset.y = pointer.y + this._dragPoint.y + this.dragOffset.y;
  19878. }
  19879. if (this.boundsRect)
  19880. {
  19881. this.checkBoundsRect();
  19882. }
  19883. if (this.boundsSprite)
  19884. {
  19885. this.checkBoundsSprite();
  19886. }
  19887. if (this.snapOnDrag)
  19888. {
  19889. this.sprite.cameraOffset.x = Math.round((this.sprite.cameraOffset.x - (this.snapOffsetX % this.snapX)) / this.snapX) * this.snapX + (this.snapOffsetX % this.snapX);
  19890. this.sprite.cameraOffset.y = Math.round((this.sprite.cameraOffset.y - (this.snapOffsetY % this.snapY)) / this.snapY) * this.snapY + (this.snapOffsetY % this.snapY);
  19891. }
  19892. }
  19893. else
  19894. {
  19895. if (this.allowHorizontalDrag)
  19896. {
  19897. this.sprite.x = pointer.x + this._dragPoint.x + this.dragOffset.x;
  19898. }
  19899. if (this.allowVerticalDrag)
  19900. {
  19901. this.sprite.y = pointer.y + this._dragPoint.y + this.dragOffset.y;
  19902. }
  19903. if (this.boundsRect)
  19904. {
  19905. this.checkBoundsRect();
  19906. }
  19907. if (this.boundsSprite)
  19908. {
  19909. this.checkBoundsSprite();
  19910. }
  19911. if (this.snapOnDrag)
  19912. {
  19913. this.sprite.x = Math.round((this.sprite.x - (this.snapOffsetX % this.snapX)) / this.snapX) * this.snapX + (this.snapOffsetX % this.snapX);
  19914. this.sprite.y = Math.round((this.sprite.y - (this.snapOffsetY % this.snapY)) / this.snapY) * this.snapY + (this.snapOffsetY % this.snapY);
  19915. }
  19916. }
  19917. return true;
  19918. },
  19919. /**
  19920. * Returns true if the pointer has entered the Sprite within the specified delay time (defaults to 500ms, half a second)
  19921. * @method Phaser.InputHandler#justOver
  19922. * @param {Phaser.Pointer} pointer
  19923. * @param {number} delay - The time below which the pointer is considered as just over.
  19924. * @return {boolean}
  19925. */
  19926. justOver: function (pointer, delay) {
  19927. pointer = pointer || 0;
  19928. delay = delay || 500;
  19929. return (this._pointerData[pointer].isOver && this.overDuration(pointer) < delay);
  19930. },
  19931. /**
  19932. * Returns true if the pointer has left the Sprite within the specified delay time (defaults to 500ms, half a second)
  19933. * @method Phaser.InputHandler#justOut
  19934. * @param {Phaser.Pointer} pointer
  19935. * @param {number} delay - The time below which the pointer is considered as just out.
  19936. * @return {boolean}
  19937. */
  19938. justOut: function (pointer, delay) {
  19939. pointer = pointer || 0;
  19940. delay = delay || 500;
  19941. return (this._pointerData[pointer].isOut && (this.game.time.now - this._pointerData[pointer].timeOut < delay));
  19942. },
  19943. /**
  19944. * Returns true if the pointer has touched or clicked on the Sprite within the specified delay time (defaults to 500ms, half a second)
  19945. * @method Phaser.InputHandler#justPressed
  19946. * @param {Phaser.Pointer} pointer
  19947. * @param {number} delay - The time below which the pointer is considered as just over.
  19948. * @return {boolean}
  19949. */
  19950. justPressed: function (pointer, delay) {
  19951. pointer = pointer || 0;
  19952. delay = delay || 500;
  19953. return (this._pointerData[pointer].isDown && this.downDuration(pointer) < delay);
  19954. },
  19955. /**
  19956. * Returns true if the pointer was touching this Sprite, but has been released within the specified delay time (defaults to 500ms, half a second)
  19957. * @method Phaser.InputHandler#justReleased
  19958. * @param {Phaser.Pointer} pointer
  19959. * @param {number} delay - The time below which the pointer is considered as just out.
  19960. * @return {boolean}
  19961. */
  19962. justReleased: function (pointer, delay) {
  19963. pointer = pointer || 0;
  19964. delay = delay || 500;
  19965. return (this._pointerData[pointer].isUp && (this.game.time.now - this._pointerData[pointer].timeUp < delay));
  19966. },
  19967. /**
  19968. * If the pointer is currently over this Sprite this returns how long it has been there for in milliseconds.
  19969. * @method Phaser.InputHandler#overDuration
  19970. * @param {Phaser.Pointer} pointer
  19971. * @return {number} The number of milliseconds the pointer has been over the Sprite, or -1 if not over.
  19972. */
  19973. overDuration: function (pointer) {
  19974. pointer = pointer || 0;
  19975. if (this._pointerData[pointer].isOver)
  19976. {
  19977. return this.game.time.now - this._pointerData[pointer].timeOver;
  19978. }
  19979. return -1;
  19980. },
  19981. /**
  19982. * If the pointer is currently over this Sprite this returns how long it has been there for in milliseconds.
  19983. * @method Phaser.InputHandler#downDuration
  19984. * @param {Phaser.Pointer} pointer
  19985. * @return {number} The number of milliseconds the pointer has been pressed down on the Sprite, or -1 if not over.
  19986. */
  19987. downDuration: function (pointer) {
  19988. pointer = pointer || 0;
  19989. if (this._pointerData[pointer].isDown)
  19990. {
  19991. return this.game.time.now - this._pointerData[pointer].timeDown;
  19992. }
  19993. return -1;
  19994. },
  19995. /**
  19996. * Make this Sprite draggable by the mouse. You can also optionally set mouseStartDragCallback and mouseStopDragCallback
  19997. * @method Phaser.InputHandler#enableDrag
  19998. * @param {boolean} [lockCenter=false] - If false the Sprite will drag from where you click it minus the dragOffset. If true it will center itself to the tip of the mouse pointer.
  19999. * @param {boolean} [bringToTop=false] - If true the Sprite will be bought to the top of the rendering list in its current Group.
  20000. * @param {boolean} [pixelPerfect=false] - If true it will use a pixel perfect test to see if you clicked the Sprite. False uses the bounding box.
  20001. * @param {boolean} [alphaThreshold=255] - If using pixel perfect collision this specifies the alpha level from 0 to 255 above which a collision is processed.
  20002. * @param {Phaser.Rectangle} [boundsRect=null] - If you want to restrict the drag of this sprite to a specific Rectangle, pass the Phaser.Rectangle here, otherwise it's free to drag anywhere.
  20003. * @param {Phaser.Sprite} [boundsSprite=null] - If you want to restrict the drag of this sprite to within the bounding box of another sprite, pass it here.
  20004. */
  20005. enableDrag: function (lockCenter, bringToTop, pixelPerfect, alphaThreshold, boundsRect, boundsSprite) {
  20006. if (typeof lockCenter == 'undefined') { lockCenter = false; }
  20007. if (typeof bringToTop == 'undefined') { bringToTop = false; }
  20008. if (typeof pixelPerfect == 'undefined') { pixelPerfect = false; }
  20009. if (typeof alphaThreshold == 'undefined') { alphaThreshold = 255; }
  20010. if (typeof boundsRect == 'undefined') { boundsRect = null; }
  20011. if (typeof boundsSprite == 'undefined') { boundsSprite = null; }
  20012. this._dragPoint = new Phaser.Point();
  20013. this.draggable = true;
  20014. this.bringToTop = bringToTop;
  20015. this.dragOffset = new Phaser.Point();
  20016. this.dragFromCenter = lockCenter;
  20017. this.pixelPerfect = pixelPerfect;
  20018. this.pixelPerfectAlpha = alphaThreshold;
  20019. if (boundsRect)
  20020. {
  20021. this.boundsRect = boundsRect;
  20022. }
  20023. if (boundsSprite)
  20024. {
  20025. this.boundsSprite = boundsSprite;
  20026. }
  20027. },
  20028. /**
  20029. * Stops this sprite from being able to be dragged. If it is currently the target of an active drag it will be stopped immediately. Also disables any set callbacks.
  20030. * @method Phaser.InputHandler#disableDrag
  20031. */
  20032. disableDrag: function () {
  20033. if (this._pointerData)
  20034. {
  20035. for (var i = 0; i < 10; i++)
  20036. {
  20037. this._pointerData[i].isDragged = false;
  20038. }
  20039. }
  20040. this.draggable = false;
  20041. this.isDragged = false;
  20042. this._draggedPointerID = -1;
  20043. },
  20044. /**
  20045. * Called by Pointer when drag starts on this Sprite. Should not usually be called directly.
  20046. * @method Phaser.InputHandler#startDrag
  20047. * @param {Phaser.Pointer} pointer
  20048. */
  20049. startDrag: function (pointer) {
  20050. this.isDragged = true;
  20051. this._draggedPointerID = pointer.id;
  20052. this._pointerData[pointer.id].isDragged = true;
  20053. if (this.sprite.fixedToCamera)
  20054. {
  20055. if (this.dragFromCenter)
  20056. {
  20057. this.sprite.centerOn(pointer.x, pointer.y);
  20058. this._dragPoint.setTo(this.sprite.cameraOffset.x - pointer.x, this.sprite.cameraOffset.y - pointer.y);
  20059. }
  20060. else
  20061. {
  20062. this._dragPoint.setTo(this.sprite.cameraOffset.x - pointer.x, this.sprite.cameraOffset.y - pointer.y);
  20063. }
  20064. }
  20065. else
  20066. {
  20067. if (this.dragFromCenter)
  20068. {
  20069. var bounds = this.sprite.getBounds();
  20070. this.sprite.x = pointer.x + (this.sprite.x - bounds.centerX);
  20071. this.sprite.y = pointer.y + (this.sprite.y - bounds.centerY);
  20072. this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y);
  20073. }
  20074. else
  20075. {
  20076. this._dragPoint.setTo(this.sprite.x - pointer.x, this.sprite.y - pointer.y);
  20077. }
  20078. }
  20079. this.updateDrag(pointer);
  20080. if (this.bringToTop)
  20081. {
  20082. this.sprite.bringToTop();
  20083. }
  20084. this.sprite.events.onDragStart.dispatch(this.sprite, pointer);
  20085. },
  20086. /**
  20087. * Called by Pointer when drag is stopped on this Sprite. Should not usually be called directly.
  20088. * @method Phaser.InputHandler#stopDrag
  20089. * @param {Phaser.Pointer} pointer
  20090. */
  20091. stopDrag: function (pointer) {
  20092. this.isDragged = false;
  20093. this._draggedPointerID = -1;
  20094. this._pointerData[pointer.id].isDragged = false;
  20095. if (this.snapOnRelease)
  20096. {
  20097. if (this.sprite.fixedToCamera)
  20098. {
  20099. this.sprite.cameraOffset.x = Math.round((this.sprite.cameraOffset.x - (this.snapOffsetX % this.snapX)) / this.snapX) * this.snapX + (this.snapOffsetX % this.snapX);
  20100. this.sprite.cameraOffset.y = Math.round((this.sprite.cameraOffset.y - (this.snapOffsetY % this.snapY)) / this.snapY) * this.snapY + (this.snapOffsetY % this.snapY);
  20101. }
  20102. else
  20103. {
  20104. this.sprite.x = Math.round((this.sprite.x - (this.snapOffsetX % this.snapX)) / this.snapX) * this.snapX + (this.snapOffsetX % this.snapX);
  20105. this.sprite.y = Math.round((this.sprite.y - (this.snapOffsetY % this.snapY)) / this.snapY) * this.snapY + (this.snapOffsetY % this.snapY);
  20106. }
  20107. }
  20108. this.sprite.events.onDragStop.dispatch(this.sprite, pointer);
  20109. if (this.checkPointerOver(pointer) === false)
  20110. {
  20111. this._pointerOutHandler(pointer);
  20112. }
  20113. },
  20114. /**
  20115. * Restricts this sprite to drag movement only on the given axis. Note: If both are set to false the sprite will never move!
  20116. * @method Phaser.InputHandler#setDragLock
  20117. * @param {boolean} [allowHorizontal=true] - To enable the sprite to be dragged horizontally set to true, otherwise false.
  20118. * @param {boolean} [allowVertical=true] - To enable the sprite to be dragged vertically set to true, otherwise false.
  20119. */
  20120. setDragLock: function (allowHorizontal, allowVertical) {
  20121. if (typeof allowHorizontal == 'undefined') { allowHorizontal = true; }
  20122. if (typeof allowVertical == 'undefined') { allowVertical = true; }
  20123. this.allowHorizontalDrag = allowHorizontal;
  20124. this.allowVerticalDrag = allowVertical;
  20125. },
  20126. /**
  20127. * Make this Sprite snap to the given grid either during drag or when it's released.
  20128. * For example 16x16 as the snapX and snapY would make the sprite snap to every 16 pixels.
  20129. * @method Phaser.InputHandler#enableSnap
  20130. * @param {number} snapX - The width of the grid cell to snap to.
  20131. * @param {number} snapY - The height of the grid cell to snap to.
  20132. * @param {boolean} [onDrag=true] - If true the sprite will snap to the grid while being dragged.
  20133. * @param {boolean} [onRelease=false] - If true the sprite will snap to the grid when released.
  20134. * @param {number} [snapOffsetX=0] - Used to offset the top-left starting point of the snap grid.
  20135. * @param {number} [snapOffsetX=0] - Used to offset the top-left starting point of the snap grid.
  20136. */
  20137. enableSnap: function (snapX, snapY, onDrag, onRelease, snapOffsetX, snapOffsetY) {
  20138. if (typeof onDrag == 'undefined') { onDrag = true; }
  20139. if (typeof onRelease == 'undefined') { onRelease = false; }
  20140. if (typeof snapOffsetX == 'undefined') { snapOffsetX = 0; }
  20141. if (typeof snapOffsetY == 'undefined') { snapOffsetY = 0; }
  20142. this.snapX = snapX;
  20143. this.snapY = snapY;
  20144. this.snapOffsetX = snapOffsetX;
  20145. this.snapOffsetY = snapOffsetY;
  20146. this.snapOnDrag = onDrag;
  20147. this.snapOnRelease = onRelease;
  20148. },
  20149. /**
  20150. * Stops the sprite from snapping to a grid during drag or release.
  20151. * @method Phaser.InputHandler#disableSnap
  20152. */
  20153. disableSnap: function () {
  20154. this.snapOnDrag = false;
  20155. this.snapOnRelease = false;
  20156. },
  20157. /**
  20158. * Bounds Rect check for the sprite drag
  20159. * @method Phaser.InputHandler#checkBoundsRect
  20160. */
  20161. checkBoundsRect: function () {
  20162. if (this.sprite.fixedToCamera)
  20163. {
  20164. if (this.sprite.cameraOffset.x < this.boundsRect.left)
  20165. {
  20166. this.sprite.cameraOffset.x = this.boundsRect.cameraOffset.x;
  20167. }
  20168. else if ((this.sprite.cameraOffset.x + this.sprite.width) > this.boundsRect.right)
  20169. {
  20170. this.sprite.cameraOffset.x = this.boundsRect.right - this.sprite.width;
  20171. }
  20172. if (this.sprite.cameraOffset.y < this.boundsRect.top)
  20173. {
  20174. this.sprite.cameraOffset.y = this.boundsRect.top;
  20175. }
  20176. else if ((this.sprite.cameraOffset.y + this.sprite.height) > this.boundsRect.bottom)
  20177. {
  20178. this.sprite.cameraOffset.y = this.boundsRect.bottom - this.sprite.height;
  20179. }
  20180. }
  20181. else
  20182. {
  20183. if (this.sprite.x < this.boundsRect.left)
  20184. {
  20185. this.sprite.x = this.boundsRect.x;
  20186. }
  20187. else if ((this.sprite.x + this.sprite.width) > this.boundsRect.right)
  20188. {
  20189. this.sprite.x = this.boundsRect.right - this.sprite.width;
  20190. }
  20191. if (this.sprite.y < this.boundsRect.top)
  20192. {
  20193. this.sprite.y = this.boundsRect.top;
  20194. }
  20195. else if ((this.sprite.y + this.sprite.height) > this.boundsRect.bottom)
  20196. {
  20197. this.sprite.y = this.boundsRect.bottom - this.sprite.height;
  20198. }
  20199. }
  20200. },
  20201. /**
  20202. * Parent Sprite Bounds check for the sprite drag.
  20203. * @method Phaser.InputHandler#checkBoundsSprite
  20204. */
  20205. checkBoundsSprite: function () {
  20206. if (this.sprite.fixedToCamera && this.boundsSprite.fixedToCamera)
  20207. {
  20208. if (this.sprite.cameraOffset.x < this.boundsSprite.camerOffset.x)
  20209. {
  20210. this.sprite.cameraOffset.x = this.boundsSprite.camerOffset.x;
  20211. }
  20212. else if ((this.sprite.cameraOffset.x + this.sprite.width) > (this.boundsSprite.camerOffset.x + this.boundsSprite.width))
  20213. {
  20214. this.sprite.cameraOffset.x = (this.boundsSprite.camerOffset.x + this.boundsSprite.width) - this.sprite.width;
  20215. }
  20216. if (this.sprite.cameraOffset.y < this.boundsSprite.camerOffset.y)
  20217. {
  20218. this.sprite.cameraOffset.y = this.boundsSprite.camerOffset.y;
  20219. }
  20220. else if ((this.sprite.cameraOffset.y + this.sprite.height) > (this.boundsSprite.camerOffset.y + this.boundsSprite.height))
  20221. {
  20222. this.sprite.cameraOffset.y = (this.boundsSprite.camerOffset.y + this.boundsSprite.height) - this.sprite.height;
  20223. }
  20224. }
  20225. else
  20226. {
  20227. if (this.sprite.x < this.boundsSprite.x)
  20228. {
  20229. this.sprite.x = this.boundsSprite.x;
  20230. }
  20231. else if ((this.sprite.x + this.sprite.width) > (this.boundsSprite.x + this.boundsSprite.width))
  20232. {
  20233. this.sprite.x = (this.boundsSprite.x + this.boundsSprite.width) - this.sprite.width;
  20234. }
  20235. if (this.sprite.y < this.boundsSprite.y)
  20236. {
  20237. this.sprite.y = this.boundsSprite.y;
  20238. }
  20239. else if ((this.sprite.y + this.sprite.height) > (this.boundsSprite.y + this.boundsSprite.height))
  20240. {
  20241. this.sprite.y = (this.boundsSprite.y + this.boundsSprite.height) - this.sprite.height;
  20242. }
  20243. }
  20244. }
  20245. };
  20246. Phaser.InputHandler.prototype.constructor = Phaser.InputHandler;
  20247. /**
  20248. * @author Richard Davey <rich@photonstorm.com>
  20249. * @copyright 2014 Photon Storm Ltd.
  20250. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  20251. */
  20252. /**
  20253. * @class Phaser.Events
  20254. *
  20255. * @classdesc The Events component is a collection of events fired by the parent game object.
  20256. *
  20257. * For example to tell when a Sprite has been added to a new group:
  20258. *
  20259. * `sprite.events.onAddedToGroup.add(yourFunction, this);`
  20260. *
  20261. * Where `yourFunction` is the function you want called when this event occurs.
  20262. *
  20263. * Note that the Input related events only exist if the Sprite has had `inputEnabled` set to `true`.
  20264. *
  20265. * @constructor
  20266. *
  20267. * @param {Phaser.Sprite} sprite - A reference to Description.
  20268. */
  20269. Phaser.Events = function (sprite) {
  20270. this.parent = sprite;
  20271. this.onAddedToGroup = new Phaser.Signal();
  20272. this.onRemovedFromGroup = new Phaser.Signal();
  20273. this.onKilled = new Phaser.Signal();
  20274. this.onRevived = new Phaser.Signal();
  20275. this.onOutOfBounds = new Phaser.Signal();
  20276. this.onEnterBounds = new Phaser.Signal();
  20277. this.onInputOver = null;
  20278. this.onInputOut = null;
  20279. this.onInputDown = null;
  20280. this.onInputUp = null;
  20281. this.onDragStart = null;
  20282. this.onDragStop = null;
  20283. this.onAnimationStart = null;
  20284. this.onAnimationComplete = null;
  20285. this.onAnimationLoop = null;
  20286. };
  20287. Phaser.Events.prototype = {
  20288. destroy: function () {
  20289. this.parent = null;
  20290. this.onAddedToGroup.dispose();
  20291. this.onRemovedFromGroup.dispose();
  20292. this.onKilled.dispose();
  20293. this.onRevived.dispose();
  20294. this.onOutOfBounds.dispose();
  20295. if (this.onInputOver)
  20296. {
  20297. this.onInputOver.dispose();
  20298. this.onInputOut.dispose();
  20299. this.onInputDown.dispose();
  20300. this.onInputUp.dispose();
  20301. this.onDragStart.dispose();
  20302. this.onDragStop.dispose();
  20303. }
  20304. if (this.onAnimationStart)
  20305. {
  20306. this.onAnimationStart.dispose();
  20307. this.onAnimationComplete.dispose();
  20308. this.onAnimationLoop.dispose();
  20309. }
  20310. }
  20311. };
  20312. Phaser.Events.prototype.constructor = Phaser.Events;
  20313. /**
  20314. * @author Richard Davey <rich@photonstorm.com>
  20315. * @copyright 2014 Photon Storm Ltd.
  20316. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  20317. */
  20318. /**
  20319. * The Game Object Factory is a quick way to create all of the different sorts of core objects that Phaser uses.
  20320. *
  20321. * @class Phaser.GameObjectFactory
  20322. * @constructor
  20323. * @param {Phaser.Game} game - A reference to the currently running game.
  20324. */
  20325. Phaser.GameObjectFactory = function (game) {
  20326. /**
  20327. * @property {Phaser.Game} game - A reference to the currently running Game.
  20328. */
  20329. this.game = game;
  20330. /**
  20331. * @property {Phaser.World} world - A reference to the game world.
  20332. */
  20333. this.world = this.game.world;
  20334. };
  20335. Phaser.GameObjectFactory.prototype = {
  20336. /**
  20337. * Adds an existing object to the game world.
  20338. * @method Phaser.GameObjectFactory#existing
  20339. * @param {*} object - An instance of Phaser.Sprite, Phaser.Button or any other display object..
  20340. * @return {*} The child that was added to the Group.
  20341. */
  20342. existing: function (object) {
  20343. return this.world.add(object);
  20344. },
  20345. /**
  20346. * Create a new `Image` object. An Image is a light-weight object you can use to display anything that doesn't need physics or animation.
  20347. * It can still rotate, scale, crop and receive input events. This makes it perfect for logos, backgrounds, simple buttons and other non-Sprite graphics.
  20348. *
  20349. * @method Phaser.GameObjectFactory#image
  20350. * @param {number} x - X position of the image.
  20351. * @param {number} y - Y position of the image.
  20352. * @param {string|Phaser.RenderTexture|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  20353. * @param {string|number} [frame] - If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name.
  20354. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20355. * @returns {Phaser.Sprite} the newly created sprite object.
  20356. */
  20357. image: function (x, y, key, frame, group) {
  20358. if (typeof group === 'undefined') { group = this.world; }
  20359. return group.add(new Phaser.Image(this.game, x, y, key, frame));
  20360. },
  20361. /**
  20362. * Create a new Sprite with specific position and sprite sheet key.
  20363. *
  20364. * @method Phaser.GameObjectFactory#sprite
  20365. * @param {number} x - X position of the new sprite.
  20366. * @param {number} y - Y position of the new sprite.
  20367. * @param {string|Phaser.RenderTexture|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  20368. * @param {string|number} [frame] - If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name.
  20369. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20370. * @returns {Phaser.Sprite} the newly created sprite object.
  20371. */
  20372. sprite: function (x, y, key, frame, group) {
  20373. if (typeof group === 'undefined') { group = this.world; }
  20374. return group.create(x, y, key, frame);
  20375. },
  20376. /**
  20377. * Create a tween object for a specific object. The object can be any JavaScript object or Phaser object such as Sprite.
  20378. *
  20379. * @method Phaser.GameObjectFactory#tween
  20380. * @param {object} obj - Object the tween will be run on.
  20381. * @return {Phaser.Tween} The newly created Phaser.Tween object.
  20382. */
  20383. tween: function (obj) {
  20384. return this.game.tweens.create(obj);
  20385. },
  20386. /**
  20387. * A Group is a container for display objects that allows for fast pooling, recycling and collision checks.
  20388. *
  20389. * @method Phaser.GameObjectFactory#group
  20390. * @param {any} [parent] - The parent Group or DisplayObjectContainer that will hold this group, if any. If set to null the Group won't be added to the display list. If undefined it will be added to World by default.
  20391. * @param {string} [name='group'] - A name for this Group. Not used internally but useful for debugging.
  20392. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  20393. * @param {boolean} [enableBody=false] - If true all Sprites created with `Group.create` or `Group.createMulitple` will have a physics body created on them. Change the body type with physicsBodyType.
  20394. * @param {number} [physicsBodyType=0] - If enableBody is true this is the type of physics body that is created on new Sprites. Phaser.Physics.ARCADE, Phaser.Physics.P2, Phaser.Physics.NINJA, etc.
  20395. * @return {Phaser.Group} The newly created group.
  20396. */
  20397. group: function (parent, name, addToStage, enableBody, physicsBodyType) {
  20398. return new Phaser.Group(this.game, parent, name, addToStage, enableBody, physicsBodyType);
  20399. },
  20400. /**
  20401. * A Group is a container for display objects that allows for fast pooling, recycling and collision checks.
  20402. * A Physics Group is the same as an ordinary Group except that is has enableBody turned on by default, so any Sprites it creates
  20403. * are automatically given a physics body.
  20404. *
  20405. * @method Phaser.GameObjectFactory#group
  20406. * @param {number} [physicsBodyType=Phaser.Physics.ARCADE] - If enableBody is true this is the type of physics body that is created on new Sprites. Phaser.Physics.ARCADE, Phaser.Physics.P2, Phaser.Physics.NINJA, etc.
  20407. * @param {any} [parent] - The parent Group or DisplayObjectContainer that will hold this group, if any. If set to null the Group won't be added to the display list. If undefined it will be added to World by default.
  20408. * @param {string} [name='group'] - A name for this Group. Not used internally but useful for debugging.
  20409. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  20410. * @return {Phaser.Group} The newly created group.
  20411. */
  20412. physicsGroup: function (physicsBodyType, parent, name, addToStage) {
  20413. return new Phaser.Group(this.game, parent, name, addToStage, true, physicsBodyType);
  20414. },
  20415. /**
  20416. * A Group is a container for display objects that allows for fast pooling, recycling and collision checks.
  20417. *
  20418. * @method Phaser.GameObjectFactory#spriteBatch
  20419. * @param {any} parent - The parent Group or DisplayObjectContainer that will hold this group, if any.
  20420. * @param {string} [name='group'] - A name for this Group. Not used internally but useful for debugging.
  20421. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  20422. * @return {Phaser.Group} The newly created group.
  20423. */
  20424. spriteBatch: function (parent, name, addToStage) {
  20425. if (typeof name === 'undefined') { name = 'group'; }
  20426. if (typeof addToStage === 'undefined') { addToStage = false; }
  20427. return new Phaser.SpriteBatch(this.game, parent, name, addToStage);
  20428. },
  20429. /**
  20430. * Creates a new Sound object.
  20431. *
  20432. * @method Phaser.GameObjectFactory#audio
  20433. * @param {string} key - The Game.cache key of the sound that this object will use.
  20434. * @param {number} [volume=1] - The volume at which the sound will be played.
  20435. * @param {boolean} [loop=false] - Whether or not the sound will loop.
  20436. * @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio.
  20437. * @return {Phaser.Sound} The newly created text object.
  20438. */
  20439. audio: function (key, volume, loop, connect) {
  20440. return this.game.sound.add(key, volume, loop, connect);
  20441. },
  20442. /**
  20443. * Creates a new Sound object.
  20444. *
  20445. * @method Phaser.GameObjectFactory#sound
  20446. * @param {string} key - The Game.cache key of the sound that this object will use.
  20447. * @param {number} [volume=1] - The volume at which the sound will be played.
  20448. * @param {boolean} [loop=false] - Whether or not the sound will loop.
  20449. * @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio.
  20450. * @return {Phaser.Sound} The newly created text object.
  20451. */
  20452. sound: function (key, volume, loop, connect) {
  20453. return this.game.sound.add(key, volume, loop, connect);
  20454. },
  20455. /**
  20456. * Creates a new TileSprite object.
  20457. *
  20458. * @method Phaser.GameObjectFactory#tileSprite
  20459. * @param {number} x - The x coordinate (in world space) to position the TileSprite at.
  20460. * @param {number} y - The y coordinate (in world space) to position the TileSprite at.
  20461. * @param {number} width - The width of the TileSprite.
  20462. * @param {number} height - The height of the TileSprite.
  20463. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the TileSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  20464. * @param {string|number} frame - If this TileSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  20465. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20466. * @return {Phaser.TileSprite} The newly created tileSprite object.
  20467. */
  20468. tileSprite: function (x, y, width, height, key, frame, group) {
  20469. if (typeof group === 'undefined') { group = this.world; }
  20470. return group.add(new Phaser.TileSprite(this.game, x, y, width, height, key, frame));
  20471. },
  20472. /**
  20473. * Creates a new Text object.
  20474. *
  20475. * @method Phaser.GameObjectFactory#text
  20476. * @param {number} x - X position of the new text object.
  20477. * @param {number} y - Y position of the new text object.
  20478. * @param {string} text - The actual text that will be written.
  20479. * @param {object} style - The style object containing style attributes like font, font size , etc.
  20480. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20481. * @return {Phaser.Text} The newly created text object.
  20482. */
  20483. text: function (x, y, text, style, group) {
  20484. if (typeof group === 'undefined') { group = this.world; }
  20485. return group.add(new Phaser.Text(this.game, x, y, text, style));
  20486. },
  20487. /**
  20488. * Creates a new Button object.
  20489. *
  20490. * @method Phaser.GameObjectFactory#button
  20491. * @param {number} [x] X position of the new button object.
  20492. * @param {number} [y] Y position of the new button object.
  20493. * @param {string} [key] The image key as defined in the Game.Cache to use as the texture for this button.
  20494. * @param {function} [callback] The function to call when this button is pressed
  20495. * @param {object} [callbackContext] The context in which the callback will be called (usually 'this')
  20496. * @param {string|number} [overFrame] This is the frame or frameName that will be set when this button is in an over state. Give either a number to use a frame ID or a string for a frame name.
  20497. * @param {string|number} [outFrame] This is the frame or frameName that will be set when this button is in an out state. Give either a number to use a frame ID or a string for a frame name.
  20498. * @param {string|number} [downFrame] This is the frame or frameName that will be set when this button is in a down state. Give either a number to use a frame ID or a string for a frame name.
  20499. * @param {string|number} [upFrame] This is the frame or frameName that will be set when this button is in an up state. Give either a number to use a frame ID or a string for a frame name.
  20500. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20501. * @return {Phaser.Button} The newly created button object.
  20502. */
  20503. button: function (x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame, group) {
  20504. if (typeof group === 'undefined') { group = this.world; }
  20505. return group.add(new Phaser.Button(this.game, x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame));
  20506. },
  20507. /**
  20508. * Creates a new Graphics object.
  20509. *
  20510. * @method Phaser.GameObjectFactory#graphics
  20511. * @param {number} x - X position of the new graphics object.
  20512. * @param {number} y - Y position of the new graphics object.
  20513. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20514. * @return {Phaser.Graphics} The newly created graphics object.
  20515. */
  20516. graphics: function (x, y, group) {
  20517. if (typeof group === 'undefined') { group = this.world; }
  20518. return group.add(new Phaser.Graphics(this.game, x, y));
  20519. },
  20520. /**
  20521. * Emitter is a lightweight particle emitter. It can be used for one-time explosions or for
  20522. * continuous effects like rain and fire. All it really does is launch Particle objects out
  20523. * at set intervals, and fixes their positions and velocities accorindgly.
  20524. *
  20525. * @method Phaser.GameObjectFactory#emitter
  20526. * @param {number} [x=0] - The x coordinate within the Emitter that the particles are emitted from.
  20527. * @param {number} [y=0] - The y coordinate within the Emitter that the particles are emitted from.
  20528. * @param {number} [maxParticles=50] - The total number of particles in this emitter.
  20529. * @return {Phaser.Emitter} The newly created emitter object.
  20530. */
  20531. emitter: function (x, y, maxParticles) {
  20532. return this.game.particles.add(new Phaser.Particles.Arcade.Emitter(this.game, x, y, maxParticles));
  20533. },
  20534. /**
  20535. * Create a new RetroFont object to be used as a texture for an Image or Sprite and optionally add it to the Cache.
  20536. * A RetroFont uses a bitmap which contains fixed with characters for the font set. You use character spacing to define the set.
  20537. * If you need variable width character support then use a BitmapText object instead. The main difference between a RetroFont and a BitmapText
  20538. * is that a RetroFont creates a single texture that you can apply to a game object, where-as a BitmapText creates one Sprite object per letter of text.
  20539. * The texture can be asssigned or one or multiple images/sprites, but note that the text the RetroFont uses will be shared across them all,
  20540. * i.e. if you need each Image to have different text in it, then you need to create multiple RetroFont objects.
  20541. *
  20542. * @method Phaser.GameObjectFactory#retroFont
  20543. * @param {string} font - The key of the image in the Game.Cache that the RetroFont will use.
  20544. * @param {number} characterWidth - The width of each character in the font set.
  20545. * @param {number} characterHeight - The height of each character in the font set.
  20546. * @param {string} chars - The characters used in the font set, in display order. You can use the TEXT_SET consts for common font set arrangements.
  20547. * @param {number} charsPerRow - The number of characters per row in the font set.
  20548. * @param {number} [xSpacing=0] - If the characters in the font set have horizontal spacing between them set the required amount here.
  20549. * @param {number} [ySpacing=0] - If the characters in the font set have vertical spacing between them set the required amount here.
  20550. * @param {number} [xOffset=0] - If the font set doesn't start at the top left of the given image, specify the X coordinate offset here.
  20551. * @param {number} [yOffset=0] - If the font set doesn't start at the top left of the given image, specify the Y coordinate offset here.
  20552. * @return {Phaser.RetroFont} The newly created RetroFont texture which can be applied to an Image or Sprite.
  20553. */
  20554. retroFont: function (font, characterWidth, characterHeight, chars, charsPerRow, xSpacing, ySpacing, xOffset, yOffset) {
  20555. return new Phaser.RetroFont(this.game, font, characterWidth, characterHeight, chars, charsPerRow, xSpacing, ySpacing, xOffset, yOffset);
  20556. },
  20557. /**
  20558. * Create a new BitmapText object.
  20559. *
  20560. * @method Phaser.GameObjectFactory#bitmapText
  20561. * @param {number} x - X position of the new bitmapText object.
  20562. * @param {number} y - Y position of the new bitmapText object.
  20563. * @param {string} font - The key of the BitmapText font as stored in Game.Cache.
  20564. * @param {string} [text] - The actual text that will be rendered. Can be set later via BitmapText.text.
  20565. * @param {number} [size] - The size the font will be rendered in, in pixels.
  20566. * @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
  20567. * @return {Phaser.BitmapText} The newly created bitmapText object.
  20568. */
  20569. bitmapText: function (x, y, font, text, size, group) {
  20570. if (typeof group === 'undefined') { group = this.world; }
  20571. return group.add(new Phaser.BitmapText(this.game, x, y, font, text, size));
  20572. },
  20573. /**
  20574. * Creates a new Phaser.Tilemap object. The map can either be populated with data from a Tiled JSON file or from a CSV file.
  20575. * To do this pass the Cache key as the first parameter. When using Tiled data you need only provide the key.
  20576. * When using CSV data you must provide the key and the tileWidth and tileHeight parameters.
  20577. * If creating a blank tilemap to be populated later, you can either specify no parameters at all and then use `Tilemap.create` or pass the map and tile dimensions here.
  20578. * Note that all Tilemaps use a base tile size to calculate dimensions from, but that a TilemapLayer may have its own unique tile size that overrides it.
  20579. *
  20580. * @method Phaser.GameObjectFactory#tilemap
  20581. * @param {string} [key] - The key of the tilemap data as stored in the Cache. If you're creating a blank map either leave this parameter out or pass `null`.
  20582. * @param {number} [tileWidth=32] - The pixel width of a single map tile. If using CSV data you must specify this. Not required if using Tiled map data.
  20583. * @param {number} [tileHeight=32] - The pixel height of a single map tile. If using CSV data you must specify this. Not required if using Tiled map data.
  20584. * @param {number} [width=10] - The width of the map in tiles. If this map is created from Tiled or CSV data you don't need to specify this.
  20585. * @param {number} [height=10] - The height of the map in tiles. If this map is created from Tiled or CSV data you don't need to specify this.
  20586. * @return {Phaser.Tilemap} The newly created tilemap object.
  20587. */
  20588. tilemap: function (key, tileWidth, tileHeight, width, height) {
  20589. return new Phaser.Tilemap(this.game, key, tileWidth, tileHeight, width, height);
  20590. },
  20591. /**
  20592. * A dynamic initially blank canvas to which images can be drawn.
  20593. *
  20594. * @method Phaser.GameObjectFactory#renderTexture
  20595. * @param {number} [width=100] - the width of the RenderTexture.
  20596. * @param {number} [height=100] - the height of the RenderTexture.
  20597. * @param {string} [key=''] - Asset key for the RenderTexture when stored in the Cache (see addToCache parameter).
  20598. * @param {boolean} [addToCache=false] - Should this RenderTexture be added to the Game.Cache? If so you can retrieve it with Cache.getTexture(key)
  20599. * @return {Phaser.RenderTexture} The newly created RenderTexture object.
  20600. */
  20601. renderTexture: function (width, height, key, addToCache) {
  20602. if (typeof key === 'undefined' || key === '') { key = this.game.rnd.uuid(); }
  20603. if (typeof addToCache === 'undefined') { addToCache = false; }
  20604. var texture = new Phaser.RenderTexture(this.game, width, height, key);
  20605. if (addToCache)
  20606. {
  20607. this.game.cache.addRenderTexture(key, texture);
  20608. }
  20609. return texture;
  20610. },
  20611. /**
  20612. * A BitmapData object which can be manipulated and drawn to like a traditional Canvas object and used to texture Sprites.
  20613. *
  20614. * @method Phaser.GameObjectFactory#bitmapData
  20615. * @param {number} [width=100] - The width of the BitmapData in pixels.
  20616. * @param {number} [height=100] - The height of the BitmapData in pixels.
  20617. * @param {string} [key=''] - Asset key for the BitmapData when stored in the Cache (see addToCache parameter).
  20618. * @param {boolean} [addToCache=false] - Should this BitmapData be added to the Game.Cache? If so you can retrieve it with Cache.getBitmapData(key)
  20619. * @return {Phaser.BitmapData} The newly created BitmapData object.
  20620. */
  20621. bitmapData: function (width, height, key, addToCache) {
  20622. if (typeof addToCache === 'undefined') { addToCache = false; }
  20623. if (typeof key === 'undefined' || key === '') { key = this.game.rnd.uuid(); }
  20624. var texture = new Phaser.BitmapData(this.game, key, width, height);
  20625. if (addToCache)
  20626. {
  20627. this.game.cache.addBitmapData(key, texture);
  20628. }
  20629. return texture;
  20630. },
  20631. /**
  20632. * A WebGL shader/filter that can be applied to Sprites.
  20633. *
  20634. * @method Phaser.GameObjectFactory#filter
  20635. * @param {string} filter - The name of the filter you wish to create, for example HueRotate or SineWave.
  20636. * @param {any} - Whatever parameters are needed to be passed to the filter init function.
  20637. * @return {Phaser.Filter} The newly created Phaser.Filter object.
  20638. */
  20639. filter: function (filter) {
  20640. var args = Array.prototype.splice.call(arguments, 1);
  20641. var filter = new Phaser.Filter[filter](this.game);
  20642. filter.init.apply(filter, args);
  20643. return filter;
  20644. }
  20645. };
  20646. Phaser.GameObjectFactory.prototype.constructor = Phaser.GameObjectFactory;
  20647. /**
  20648. * @author Richard Davey <rich@photonstorm.com>
  20649. * @copyright 2014 Photon Storm Ltd.
  20650. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  20651. */
  20652. /**
  20653. * The Game Object Creator is a quick way to create all of the different sorts of core objects that Phaser uses, but not add them to the game world.
  20654. * Use the GameObjectFactory to create and add the objects into the world.
  20655. *
  20656. * @class Phaser.GameObjectCreator
  20657. * @constructor
  20658. * @param {Phaser.Game} game - A reference to the currently running game.
  20659. */
  20660. Phaser.GameObjectCreator = function (game) {
  20661. /**
  20662. * @property {Phaser.Game} game - A reference to the currently running Game.
  20663. */
  20664. this.game = game;
  20665. /**
  20666. * @property {Phaser.World} world - A reference to the game world.
  20667. */
  20668. this.world = this.game.world;
  20669. };
  20670. Phaser.GameObjectCreator.prototype = {
  20671. /**
  20672. * Create a new `Image` object. An Image is a light-weight object you can use to display anything that doesn't need physics or animation.
  20673. * It can still rotate, scale, crop and receive input events. This makes it perfect for logos, backgrounds, simple buttons and other non-Sprite graphics.
  20674. *
  20675. * @method Phaser.GameObjectCreator#image
  20676. * @param {number} x - X position of the image.
  20677. * @param {number} y - Y position of the image.
  20678. * @param {string|Phaser.RenderTexture|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  20679. * @param {string|number} [frame] - If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name.
  20680. * @returns {Phaser.Sprite} the newly created sprite object.
  20681. */
  20682. image: function (x, y, key, frame) {
  20683. return new Phaser.Image(this.game, x, y, key, frame);
  20684. },
  20685. /**
  20686. * Create a new Sprite with specific position and sprite sheet key.
  20687. *
  20688. * @method Phaser.GameObjectCreator#sprite
  20689. * @param {number} x - X position of the new sprite.
  20690. * @param {number} y - Y position of the new sprite.
  20691. * @param {string|Phaser.RenderTexture|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  20692. * @param {string|number} [frame] - If the sprite uses an image from a texture atlas or sprite sheet you can pass the frame here. Either a number for a frame ID or a string for a frame name.
  20693. * @returns {Phaser.Sprite} the newly created sprite object.
  20694. */
  20695. sprite: function (x, y, key, frame) {
  20696. return new Phaser.Sprite(this.game, x, y, key, frame);
  20697. },
  20698. /**
  20699. * Create a tween object for a specific object. The object can be any JavaScript object or Phaser object such as Sprite.
  20700. *
  20701. * @method Phaser.GameObjectCreator#tween
  20702. * @param {object} obj - Object the tween will be run on.
  20703. * @return {Phaser.Tween} The Tween object.
  20704. */
  20705. tween: function (obj) {
  20706. return new Phaser.Tween(obj, this.game);
  20707. },
  20708. /**
  20709. * A Group is a container for display objects that allows for fast pooling, recycling and collision checks.
  20710. *
  20711. * @method Phaser.GameObjectCreator#group
  20712. * @param {string} [name='group'] - A name for this Group. Not used internally but useful for debugging.
  20713. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  20714. * @param {boolean} [enableBody=false] - If true all Sprites created with `Group.create` or `Group.createMulitple` will have a physics body created on them. Change the body type with physicsBodyType.
  20715. * @param {number} [physicsBodyType=0] - If enableBody is true this is the type of physics body that is created on new Sprites. Phaser.Physics.ARCADE, Phaser.Physics.P2, Phaser.Physics.NINJA, etc.
  20716. * @return {Phaser.Group} The newly created group.
  20717. */
  20718. group: function (parent, name, addToStage, enableBody, physicsBodyType) {
  20719. return new Phaser.Group(this.game, null, name, addToStage, enableBody, physicsBodyType);
  20720. },
  20721. /**
  20722. * A Group is a container for display objects that allows for fast pooling, recycling and collision checks.
  20723. *
  20724. * @method Phaser.GameObjectCreator#spriteBatch
  20725. * @param {any} parent - The parent Group or DisplayObjectContainer that will hold this group, if any.
  20726. * @param {string} [name='group'] - A name for this Group. Not used internally but useful for debugging.
  20727. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  20728. * @return {Phaser.Group} The newly created group.
  20729. */
  20730. spriteBatch: function (parent, name, addToStage) {
  20731. if (typeof name === 'undefined') { name = 'group'; }
  20732. if (typeof addToStage === 'undefined') { addToStage = false; }
  20733. return new Phaser.SpriteBatch(this.game, parent, name, addToStage);
  20734. },
  20735. /**
  20736. * Creates a new Sound object.
  20737. *
  20738. * @method Phaser.GameObjectCreator#audio
  20739. * @param {string} key - The Game.cache key of the sound that this object will use.
  20740. * @param {number} [volume=1] - The volume at which the sound will be played.
  20741. * @param {boolean} [loop=false] - Whether or not the sound will loop.
  20742. * @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio.
  20743. * @return {Phaser.Sound} The newly created text object.
  20744. */
  20745. audio: function (key, volume, loop, connect) {
  20746. return this.game.sound.add(key, volume, loop, connect);
  20747. },
  20748. /**
  20749. * Creates a new Sound object.
  20750. *
  20751. * @method Phaser.GameObjectCreator#sound
  20752. * @param {string} key - The Game.cache key of the sound that this object will use.
  20753. * @param {number} [volume=1] - The volume at which the sound will be played.
  20754. * @param {boolean} [loop=false] - Whether or not the sound will loop.
  20755. * @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio.
  20756. * @return {Phaser.Sound} The newly created text object.
  20757. */
  20758. sound: function (key, volume, loop, connect) {
  20759. return this.game.sound.add(key, volume, loop, connect);
  20760. },
  20761. /**
  20762. * Creates a new TileSprite object.
  20763. *
  20764. * @method Phaser.GameObjectCreator#tileSprite
  20765. * @param {number} x - The x coordinate (in world space) to position the TileSprite at.
  20766. * @param {number} y - The y coordinate (in world space) to position the TileSprite at.
  20767. * @param {number} width - The width of the TileSprite.
  20768. * @param {number} height - The height of the TileSprite.
  20769. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the TileSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  20770. * @param {string|number} frame - If this TileSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  20771. * @return {Phaser.TileSprite} The newly created tileSprite object.
  20772. */
  20773. tileSprite: function (x, y, width, height, key, frame) {
  20774. return new Phaser.TileSprite(this.game, x, y, width, height, key, frame);
  20775. },
  20776. /**
  20777. * Creates a new Text object.
  20778. *
  20779. * @method Phaser.GameObjectCreator#text
  20780. * @param {number} x - X position of the new text object.
  20781. * @param {number} y - Y position of the new text object.
  20782. * @param {string} text - The actual text that will be written.
  20783. * @param {object} style - The style object containing style attributes like font, font size , etc.
  20784. * @return {Phaser.Text} The newly created text object.
  20785. */
  20786. text: function (x, y, text, style) {
  20787. return new Phaser.Text(this.game, x, y, text, style);
  20788. },
  20789. /**
  20790. * Creates a new Button object.
  20791. *
  20792. * @method Phaser.GameObjectCreator#button
  20793. * @param {number} [x] X position of the new button object.
  20794. * @param {number} [y] Y position of the new button object.
  20795. * @param {string} [key] The image key as defined in the Game.Cache to use as the texture for this button.
  20796. * @param {function} [callback] The function to call when this button is pressed
  20797. * @param {object} [callbackContext] The context in which the callback will be called (usually 'this')
  20798. * @param {string|number} [overFrame] This is the frame or frameName that will be set when this button is in an over state. Give either a number to use a frame ID or a string for a frame name.
  20799. * @param {string|number} [outFrame] This is the frame or frameName that will be set when this button is in an out state. Give either a number to use a frame ID or a string for a frame name.
  20800. * @param {string|number} [downFrame] This is the frame or frameName that will be set when this button is in a down state. Give either a number to use a frame ID or a string for a frame name.
  20801. * @param {string|number} [upFrame] This is the frame or frameName that will be set when this button is in an up state. Give either a number to use a frame ID or a string for a frame name.
  20802. * @return {Phaser.Button} The newly created button object.
  20803. */
  20804. button: function (x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame) {
  20805. return new Phaser.Button(this.game, x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame);
  20806. },
  20807. /**
  20808. * Creates a new Graphics object.
  20809. *
  20810. * @method Phaser.GameObjectCreator#graphics
  20811. * @param {number} x - X position of the new graphics object.
  20812. * @param {number} y - Y position of the new graphics object.
  20813. * @return {Phaser.Graphics} The newly created graphics object.
  20814. */
  20815. graphics: function (x, y) {
  20816. return new Phaser.Graphics(this.game, x, y);
  20817. },
  20818. /**
  20819. * Emitter is a lightweight particle emitter. It can be used for one-time explosions or for
  20820. * continuous effects like rain and fire. All it really does is launch Particle objects out
  20821. * at set intervals, and fixes their positions and velocities accorindgly.
  20822. *
  20823. * @method Phaser.GameObjectCreator#emitter
  20824. * @param {number} [x=0] - The x coordinate within the Emitter that the particles are emitted from.
  20825. * @param {number} [y=0] - The y coordinate within the Emitter that the particles are emitted from.
  20826. * @param {number} [maxParticles=50] - The total number of particles in this emitter.
  20827. * @return {Phaser.Emitter} The newly created emitter object.
  20828. */
  20829. emitter: function (x, y, maxParticles) {
  20830. return new Phaser.Particles.Arcade.Emitter(this.game, x, y, maxParticles);
  20831. },
  20832. /**
  20833. * Create a new RetroFont object to be used as a texture for an Image or Sprite and optionally add it to the Cache.
  20834. * A RetroFont uses a bitmap which contains fixed with characters for the font set. You use character spacing to define the set.
  20835. * If you need variable width character support then use a BitmapText object instead. The main difference between a RetroFont and a BitmapText
  20836. * is that a RetroFont creates a single texture that you can apply to a game object, where-as a BitmapText creates one Sprite object per letter of text.
  20837. * The texture can be asssigned or one or multiple images/sprites, but note that the text the RetroFont uses will be shared across them all,
  20838. * i.e. if you need each Image to have different text in it, then you need to create multiple RetroFont objects.
  20839. *
  20840. * @method Phaser.GameObjectCreator#retroFont
  20841. * @param {string} font - The key of the image in the Game.Cache that the RetroFont will use.
  20842. * @param {number} characterWidth - The width of each character in the font set.
  20843. * @param {number} characterHeight - The height of each character in the font set.
  20844. * @param {string} chars - The characters used in the font set, in display order. You can use the TEXT_SET consts for common font set arrangements.
  20845. * @param {number} charsPerRow - The number of characters per row in the font set.
  20846. * @param {number} [xSpacing=0] - If the characters in the font set have horizontal spacing between them set the required amount here.
  20847. * @param {number} [ySpacing=0] - If the characters in the font set have vertical spacing between them set the required amount here.
  20848. * @param {number} [xOffset=0] - If the font set doesn't start at the top left of the given image, specify the X coordinate offset here.
  20849. * @param {number} [yOffset=0] - If the font set doesn't start at the top left of the given image, specify the Y coordinate offset here.
  20850. * @return {Phaser.RetroFont} The newly created RetroFont texture which can be applied to an Image or Sprite.
  20851. */
  20852. retroFont: function (font, characterWidth, characterHeight, chars, charsPerRow, xSpacing, ySpacing, xOffset, yOffset) {
  20853. return new Phaser.RetroFont(this.game, font, characterWidth, characterHeight, chars, charsPerRow, xSpacing, ySpacing, xOffset, yOffset);
  20854. },
  20855. /**
  20856. * Create a new BitmapText object.
  20857. *
  20858. * @method Phaser.GameObjectCreator#bitmapText
  20859. * @param {number} x - X position of the new bitmapText object.
  20860. * @param {number} y - Y position of the new bitmapText object.
  20861. * @param {string} font - The key of the BitmapText font as stored in Game.Cache.
  20862. * @param {string} [text] - The actual text that will be rendered. Can be set later via BitmapText.text.
  20863. * @param {number} [size] - The size the font will be rendered in, in pixels.
  20864. * @return {Phaser.BitmapText} The newly created bitmapText object.
  20865. */
  20866. bitmapText: function (x, y, font, text, size) {
  20867. return new Phaser.BitmapText(this.game, x, y, font, text, size);
  20868. },
  20869. /**
  20870. * Creates a new Phaser.Tilemap object. The map can either be populated with data from a Tiled JSON file or from a CSV file.
  20871. * To do this pass the Cache key as the first parameter. When using Tiled data you need only provide the key.
  20872. * When using CSV data you must provide the key and the tileWidth and tileHeight parameters.
  20873. * If creating a blank tilemap to be populated later, you can either specify no parameters at all and then use `Tilemap.create` or pass the map and tile dimensions here.
  20874. * Note that all Tilemaps use a base tile size to calculate dimensions from, but that a TilemapLayer may have its own unique tile size that overrides it.
  20875. *
  20876. * @method Phaser.GameObjectCreator#tilemap
  20877. * @param {string} [key] - The key of the tilemap data as stored in the Cache. If you're creating a blank map either leave this parameter out or pass `null`.
  20878. * @param {number} [tileWidth=32] - The pixel width of a single map tile. If using CSV data you must specify this. Not required if using Tiled map data.
  20879. * @param {number} [tileHeight=32] - The pixel height of a single map tile. If using CSV data you must specify this. Not required if using Tiled map data.
  20880. * @param {number} [width=10] - The width of the map in tiles. If this map is created from Tiled or CSV data you don't need to specify this.
  20881. * @param {number} [height=10] - The height of the map in tiles. If this map is created from Tiled or CSV data you don't need to specify this.
  20882. */
  20883. tilemap: function (key, tileWidth, tileHeight, width, height) {
  20884. return new Phaser.Tilemap(this.game, key, tileWidth, tileHeight, width, height);
  20885. },
  20886. /**
  20887. * A dynamic initially blank canvas to which images can be drawn.
  20888. *
  20889. * @method Phaser.GameObjectCreator#renderTexture
  20890. * @param {number} [width=100] - the width of the RenderTexture.
  20891. * @param {number} [height=100] - the height of the RenderTexture.
  20892. * @param {string} [key=''] - Asset key for the RenderTexture when stored in the Cache (see addToCache parameter).
  20893. * @param {boolean} [addToCache=false] - Should this RenderTexture be added to the Game.Cache? If so you can retrieve it with Cache.getTexture(key)
  20894. * @return {Phaser.RenderTexture} The newly created RenderTexture object.
  20895. */
  20896. renderTexture: function (width, height, key, addToCache) {
  20897. if (typeof key === 'undefined' || key === '') { key = this.game.rnd.uuid(); }
  20898. if (typeof addToCache === 'undefined') { addToCache = false; }
  20899. var texture = new Phaser.RenderTexture(this.game, width, height, key);
  20900. if (addToCache)
  20901. {
  20902. this.game.cache.addRenderTexture(key, texture);
  20903. }
  20904. return texture;
  20905. },
  20906. /**
  20907. * A BitmapData object which can be manipulated and drawn to like a traditional Canvas object and used to texture Sprites.
  20908. *
  20909. * @method Phaser.GameObjectCreator#bitmapData
  20910. * @param {number} [width=100] - The width of the BitmapData in pixels.
  20911. * @param {number} [height=100] - The height of the BitmapData in pixels.
  20912. * @param {string} [key=''] - Asset key for the BitmapData when stored in the Cache (see addToCache parameter).
  20913. * @param {boolean} [addToCache=false] - Should this BitmapData be added to the Game.Cache? If so you can retrieve it with Cache.getBitmapData(key)
  20914. * @return {Phaser.BitmapData} The newly created BitmapData object.
  20915. */
  20916. bitmapData: function (width, height, key, addToCache) {
  20917. if (typeof addToCache === 'undefined') { addToCache = false; }
  20918. if (typeof key === 'undefined' || key === '') { key = this.game.rnd.uuid(); }
  20919. var texture = new Phaser.BitmapData(this.game, key, width, height);
  20920. if (addToCache)
  20921. {
  20922. this.game.cache.addBitmapData(key, texture);
  20923. }
  20924. return texture;
  20925. },
  20926. /**
  20927. * A WebGL shader/filter that can be applied to Sprites.
  20928. *
  20929. * @method Phaser.GameObjectCreator#filter
  20930. * @param {string} filter - The name of the filter you wish to create, for example HueRotate or SineWave.
  20931. * @param {any} - Whatever parameters are needed to be passed to the filter init function.
  20932. * @return {Phaser.Filter} The newly created Phaser.Filter object.
  20933. */
  20934. filter: function (filter) {
  20935. var args = Array.prototype.splice.call(arguments, 1);
  20936. var filter = new Phaser.Filter[filter](this.game);
  20937. filter.init.apply(filter, args);
  20938. return filter;
  20939. }
  20940. };
  20941. Phaser.GameObjectCreator.prototype.constructor = Phaser.GameObjectCreator;
  20942. /**
  20943. * @author Richard Davey <rich@photonstorm.com>
  20944. * @copyright 2014 Photon Storm Ltd.
  20945. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  20946. */
  20947. /**
  20948. * Creates a new BitmapData object.
  20949. *
  20950. * @class Phaser.BitmapData
  20951. *
  20952. * @classdesc A BitmapData object contains a Canvas element to which you can draw anything you like via normal Canvas context operations.
  20953. * A single BitmapData can be used as the texture one or many Images/Sprites. So if you need to dynamically create a Sprite texture then they are a good choice.
  20954. *
  20955. * @constructor
  20956. * @param {Phaser.Game} game - A reference to the currently running game.
  20957. * @param {string} key - Internal Phaser reference key for the render texture.
  20958. * @param {number} [width=100] - The width of the BitmapData in pixels.
  20959. * @param {number} [height=100] - The height of the BitmapData in pixels.
  20960. */
  20961. Phaser.BitmapData = function (game, key, width, height) {
  20962. if (typeof width === 'undefined') { width = 100; }
  20963. if (typeof height === 'undefined') { height = 100; }
  20964. /**
  20965. * @property {Phaser.Game} game - A reference to the currently running game.
  20966. */
  20967. this.game = game;
  20968. /**
  20969. * @property {string} key - The key of the BitmapData in the Cache, if stored there.
  20970. */
  20971. this.key = key;
  20972. /**
  20973. * @property {number} width - The width of the BitmapData in pixels.
  20974. */
  20975. this.width = width;
  20976. /**
  20977. * @property {number} height - The height of the BitmapData in pixels.
  20978. */
  20979. this.height = height;
  20980. /**
  20981. * @property {HTMLCanvasElement} canvas - The canvas to which this BitmapData draws.
  20982. * @default
  20983. */
  20984. this.canvas = Phaser.Canvas.create(width, height, '', true);
  20985. /**
  20986. * @property {CanvasRenderingContext2D} context - The 2d context of the canvas.
  20987. * @default
  20988. */
  20989. this.context = this.canvas.getContext('2d');
  20990. /**
  20991. * @property {CanvasRenderingContext2D} ctx - A reference to BitmapData.context.
  20992. */
  20993. this.ctx = this.context;
  20994. /**
  20995. * @property {array} imageData - The canvas image data.
  20996. */
  20997. this.imageData = this.context.getImageData(0, 0, width, height);
  20998. /**
  20999. * @property {UInt8Clamped} pixels - A reference to the context imageData buffer.
  21000. */
  21001. if (this.imageData.data.buffer)
  21002. {
  21003. this.pixels = this.imageData.data.buffer;
  21004. }
  21005. else
  21006. {
  21007. this.pixels = this.imageData.data;
  21008. }
  21009. /**
  21010. * @property {PIXI.BaseTexture} baseTexture - The PIXI.BaseTexture.
  21011. * @default
  21012. */
  21013. this.baseTexture = new PIXI.BaseTexture(this.canvas);
  21014. /**
  21015. * @property {PIXI.Texture} texture - The PIXI.Texture.
  21016. * @default
  21017. */
  21018. this.texture = new PIXI.Texture(this.baseTexture);
  21019. /**
  21020. * @property {Phaser.Frame} textureFrame - The Frame this BitmapData uses for rendering.
  21021. * @default
  21022. */
  21023. this.textureFrame = new Phaser.Frame(0, 0, 0, width, height, 'bitmapData', game.rnd.uuid());
  21024. /**
  21025. * @property {number} type - The const type of this object.
  21026. * @default
  21027. */
  21028. this.type = Phaser.BITMAPDATA;
  21029. /**
  21030. * @property {boolean} dirty - If dirty this BitmapData will be re-rendered.
  21031. */
  21032. this.dirty = false;
  21033. };
  21034. Phaser.BitmapData.prototype = {
  21035. /**
  21036. * Updates the given objects so that they use this BitmapData as their texture. This will replace any texture they will currently have set.
  21037. *
  21038. * @method Phaser.BitmapData#add
  21039. * @param {Phaser.Sprite|Phaser.Sprite[]|Phaser.Image|Phaser.Image[]} object - Either a single Sprite/Image or an Array of Sprites/Images.
  21040. */
  21041. add: function (object) {
  21042. if (Array.isArray(object))
  21043. {
  21044. for (var i = 0; i < object.length; i++)
  21045. {
  21046. if (object[i]['loadTexture'])
  21047. {
  21048. object[i].loadTexture(this);
  21049. }
  21050. }
  21051. }
  21052. else
  21053. {
  21054. object.loadTexture(this);
  21055. }
  21056. },
  21057. /**
  21058. * Clears the BitmapData.
  21059. * @method Phaser.BitmapData#clear
  21060. */
  21061. clear: function () {
  21062. this.context.clearRect(0, 0, this.width, this.height);
  21063. this.dirty = true;
  21064. },
  21065. /**
  21066. * Resizes the BitmapData.
  21067. * @method Phaser.BitmapData#resize
  21068. */
  21069. resize: function (width, height) {
  21070. if (width !== this.width || height !== this.height)
  21071. {
  21072. this.width = width;
  21073. this.height = height;
  21074. this.canvas.width = width;
  21075. this.canvas.height = height;
  21076. this.textureFrame.width = width;
  21077. this.textureFrame.height = height;
  21078. this.imageData = this.context.getImageData(0, 0, width, height);
  21079. }
  21080. this.dirty = true;
  21081. },
  21082. /**
  21083. * @method Phaser.BitmapData#refreshBuffer
  21084. */
  21085. refreshBuffer: function () {
  21086. this.imageData = this.context.getImageData(0, 0, this.width, this.height);
  21087. this.pixels = new Int32Array(this.imageData.data.buffer);
  21088. // this.data8 = new Uint8ClampedArray(this.imageData.buffer);
  21089. // this.data32 = new Uint32Array(this.imageData.buffer);
  21090. },
  21091. /**
  21092. * Sets the color of the given pixel to the specified red, green, blue and alpha values.
  21093. * @method Phaser.BitmapData#setPixel32
  21094. * @param {number} x - The X coordinate of the pixel to be set.
  21095. * @param {number} y - The Y coordinate of the pixel to be set.
  21096. * @param {number} red - The red color value, between 0 and 0xFF (255).
  21097. * @param {number} green - The green color value, between 0 and 0xFF (255).
  21098. * @param {number} blue - The blue color value, between 0 and 0xFF (255).
  21099. * @param {number} alpha - The alpha color value, between 0 and 0xFF (255).
  21100. */
  21101. setPixel32: function (x, y, red, green, blue, alpha) {
  21102. if (x >= 0 && x <= this.width && y >= 0 && y <= this.height)
  21103. {
  21104. this.pixels[y * this.width + x] = (alpha << 24) | (blue << 16) | (green << 8) | red;
  21105. /*
  21106. if (this.isLittleEndian)
  21107. {
  21108. this.data32[y * this.width + x] = (alpha << 24) | (blue << 16) | (green << 8) | red;
  21109. }
  21110. else
  21111. {
  21112. this.data32[y * this.width + x] = (red << 24) | (green << 16) | (blue << 8) | alpha;
  21113. }
  21114. */
  21115. // this.imageData.data.set(this.data8);
  21116. this.context.putImageData(this.imageData, 0, 0);
  21117. this.dirty = true;
  21118. }
  21119. },
  21120. /**
  21121. * Sets the color of the given pixel to the specified red, green and blue values.
  21122. *
  21123. * @method Phaser.BitmapData#setPixel
  21124. * @param {number} x - The X coordinate of the pixel to be set.
  21125. * @param {number} y - The Y coordinate of the pixel to be set.
  21126. * @param {number} red - The red color value (between 0 and 255)
  21127. * @param {number} green - The green color value (between 0 and 255)
  21128. * @param {number} blue - The blue color value (between 0 and 255)
  21129. */
  21130. setPixel: function (x, y, red, green, blue) {
  21131. this.setPixel32(x, y, red, green, blue, 255);
  21132. },
  21133. /**
  21134. * Get the color of a specific pixel.
  21135. *
  21136. * @param {number} x - The X coordinate of the pixel to get.
  21137. * @param {number} y - The Y coordinate of the pixel to get.
  21138. * @return {number} A native color value integer (format: 0xRRGGBB)
  21139. */
  21140. getPixel: function (x, y) {
  21141. if (x >= 0 && x <= this.width && y >= 0 && y <= this.height)
  21142. {
  21143. return this.data32[y * this.width + x];
  21144. }
  21145. },
  21146. /**
  21147. * Get the color of a specific pixel including its alpha value.
  21148. *
  21149. * @param {number} x - The X coordinate of the pixel to get.
  21150. * @param {number} y - The Y coordinate of the pixel to get.
  21151. * @return {number} A native color value integer (format: 0xAARRGGBB)
  21152. */
  21153. getPixel32: function (x, y) {
  21154. if (x >= 0 && x <= this.width && y >= 0 && y <= this.height)
  21155. {
  21156. return this.data32[y * this.width + x];
  21157. }
  21158. },
  21159. /**
  21160. * Gets all the pixels from the region specified by the given Rectangle object.
  21161. *
  21162. * @param {Phaser.Rectangle} rect - The Rectangle region to get.
  21163. * @return {array} CanvasPixelArray.
  21164. */
  21165. getPixels: function (rect) {
  21166. return this.context.getImageData(rect.x, rect.y, rect.width, rect.height);
  21167. },
  21168. /**
  21169. * Copies the pixels from the source image to this BitmapData based on the given area and destination.
  21170. *
  21171. * @param {HTMLImage|string} source - The Image to draw. If you give a key it will try and find the Image in the Game.Cache.
  21172. * @param {Phaser.Rectangle} area - The Rectangle region to copy from the source image.
  21173. * @param {number} destX - The destination x coordinate to copy the image to.
  21174. * @param {number} destY - The destination y coordinate to copy the image to.
  21175. */
  21176. copyPixels: function (source, area, destX, destY) {
  21177. if (typeof source === 'string')
  21178. {
  21179. source = this.game.cache.getImage(source);
  21180. }
  21181. if (source)
  21182. {
  21183. this.context.drawImage(source, area.x, area.y, area.width, area.height, destX, destY, area.width, area.height);
  21184. }
  21185. },
  21186. /**
  21187. * Draws the given image to this BitmapData at the coordinates specified. If you need to only draw a part of the image use BitmapData.copyPixels instead.
  21188. *
  21189. * @param {HTMLImage|string} source - The Image to draw. If you give a key it will try and find the Image in the Game.Cache.
  21190. * @param {number} destX - The destination x coordinate to draw the image to.
  21191. * @param {number} destY - The destination y coordinate to draw the image to.
  21192. */
  21193. draw: function (source, destX, destY) {
  21194. if (typeof source === 'string')
  21195. {
  21196. source = this.game.cache.getImage(source);
  21197. }
  21198. if (source)
  21199. {
  21200. this.context.drawImage(source, 0, 0, source.width, source.height, destX, destY, source.width, source.height);
  21201. }
  21202. },
  21203. /**
  21204. * Draws the given image onto this BitmapData using an image as an alpha mask.
  21205. *
  21206. * @param {HTMLImage|string} source - The Image to draw. If you give a key it will try and find the Image in the Game.Cache.
  21207. * @param {HTMLImage|string} mask - The Image to use as the alpha mask. If you give a key it will try and find the Image in the Game.Cache.
  21208. */
  21209. alphaMask: function (source, mask) {
  21210. var temp = this.context.globalCompositeOperation;
  21211. if (typeof mask === 'string')
  21212. {
  21213. mask = this.game.cache.getImage(mask);
  21214. }
  21215. if (mask)
  21216. {
  21217. this.context.drawImage(mask, 0, 0);
  21218. }
  21219. this.context.globalCompositeOperation = 'source-atop';
  21220. if (typeof source === 'string')
  21221. {
  21222. source = this.game.cache.getImage(source);
  21223. }
  21224. if (source)
  21225. {
  21226. this.context.drawImage(source, 0, 0);
  21227. }
  21228. this.context.globalCompositeOperation = temp;
  21229. },
  21230. /**
  21231. * If the game is running in WebGL this will push the texture up to the GPU if it's dirty.
  21232. * This is called automatically if the BitmapData is being used by a Sprite, otherwise you need to remember to call it in your render function.
  21233. *
  21234. * @method Phaser.BitmapData#render
  21235. */
  21236. render: function () {
  21237. if (this.game.renderType === Phaser.WEBGL && this.dirty)
  21238. {
  21239. // Only needed if running in WebGL, otherwise this array will never get cleared down
  21240. // should use the rendersession
  21241. PIXI.updateWebGLTexture(this.baseTexture, this.game.renderer.gl);
  21242. this.dirty = false;
  21243. }
  21244. }
  21245. };
  21246. Phaser.BitmapData.prototype.constructor = Phaser.BitmapData;
  21247. /**
  21248. * @author Richard Davey <rich@photonstorm.com>
  21249. * @copyright 2014 Photon Storm Ltd.
  21250. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  21251. */
  21252. /**
  21253. * @class Phaser.Sprite
  21254. *
  21255. * @classdesc Create a new `Sprite` object. Sprites are the lifeblood of your game, used for nearly everything visual.
  21256. *
  21257. * At its most basic a Sprite consists of a set of coordinates and a texture that is rendered to the canvas.
  21258. * They also contain additional properties allowing for physics motion (via Sprite.body), input handling (via Sprite.input),
  21259. * events (via Sprite.events), animation (via Sprite.animations), camera culling and more. Please see the Examples for use cases.
  21260. *
  21261. * @constructor
  21262. * @extends PIXI.Sprite
  21263. * @param {Phaser.Game} game - A reference to the currently running game.
  21264. * @param {number} x - The x coordinate (in world space) to position the Sprite at.
  21265. * @param {number} y - The y coordinate (in world space) to position the Sprite at.
  21266. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  21267. * @param {string|number} frame - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  21268. */
  21269. Phaser.Sprite = function (game, x, y, key, frame) {
  21270. x = x || 0;
  21271. y = y || 0;
  21272. key = key || null;
  21273. frame = frame || null;
  21274. /**
  21275. * @property {Phaser.Game} game - A reference to the currently running Game.
  21276. */
  21277. this.game = game;
  21278. /**
  21279. * @property {string} name - The user defined name given to this Sprite.
  21280. * @default
  21281. */
  21282. this.name = '';
  21283. /**
  21284. * @property {number} type - The const type of this object.
  21285. * @readonly
  21286. */
  21287. this.type = Phaser.SPRITE;
  21288. /**
  21289. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  21290. */
  21291. this.z = 0;
  21292. /**
  21293. * @property {Phaser.Events} events - The Events you can subscribe to that are dispatched when certain things happen on this Sprite or its components.
  21294. */
  21295. this.events = new Phaser.Events(this);
  21296. /**
  21297. * @property {Phaser.AnimationManager} animations - This manages animations of the sprite. You can modify animations through it (see Phaser.AnimationManager)
  21298. */
  21299. this.animations = new Phaser.AnimationManager(this);
  21300. /**
  21301. * @property {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  21302. */
  21303. this.key = key;
  21304. /**
  21305. * @property {number} _frame - Internal cache var.
  21306. * @private
  21307. */
  21308. this._frame = 0;
  21309. /**
  21310. * @property {string} _frameName - Internal cache var.
  21311. * @private
  21312. */
  21313. this._frameName = '';
  21314. PIXI.Sprite.call(this, PIXI.TextureCache['__default']);
  21315. this.loadTexture(key, frame);
  21316. this.position.set(x, y);
  21317. /**
  21318. * @property {Phaser.Point} world - The world coordinates of this Sprite. This differs from the x/y coordinates which are relative to the Sprites container.
  21319. */
  21320. this.world = new Phaser.Point(x, y);
  21321. /**
  21322. * Should this Sprite be automatically culled if out of range of the camera?
  21323. * A culled sprite has its renderable property set to 'false'.
  21324. * Be advised this is quite an expensive operation, as it has to calculate the bounds of the object every frame, so only enable it if you really need it.
  21325. *
  21326. * @property {boolean} autoCull - A flag indicating if the Sprite should be automatically camera culled or not.
  21327. * @default
  21328. */
  21329. this.autoCull = false;
  21330. /**
  21331. * @property {Phaser.InputHandler|null} input - The Input Handler for this object. Needs to be enabled with image.inputEnabled = true before you can use it.
  21332. */
  21333. this.input = null;
  21334. /**
  21335. * By default Sprites won't add themselves to any physics system and their physics body will be `null`.
  21336. * To enable them for physics you need to call `game.physics.enable(sprite, system)` where `sprite` is this object
  21337. * and `system` is the Physics system you want to use to manage this body. Once enabled you can access all physics related properties via `Sprite.body`.
  21338. *
  21339. * Important: Enabling a Sprite for P2 or Ninja physics will automatically set `Sprite.anchor` to 0.5 so the physics body is centered on the Sprite.
  21340. * If you need a different result then adjust or re-create the Body shape offsets manually, and/or reset the anchor after enabling physics.
  21341. *
  21342. * @property {Phaser.Physics.Arcade.Body|Phaser.Physics.P2.Body|Phaser.Physics.Ninja.Body|null} body
  21343. * @default
  21344. */
  21345. this.body = null;
  21346. /**
  21347. * @property {number} health - Health value. Used in combination with damage() to allow for quick killing of Sprites.
  21348. */
  21349. this.health = 1;
  21350. /**
  21351. * If you would like the Sprite to have a lifespan once 'born' you can set this to a positive value. Handy for particles, bullets, etc.
  21352. * The lifespan is decremented by game.time.elapsed each update, once it reaches zero the kill() function is called.
  21353. * @property {number} lifespan - The lifespan of the Sprite (in ms) before it will be killed.
  21354. * @default
  21355. */
  21356. this.lifespan = 0;
  21357. /**
  21358. * If true the Sprite checks if it is still within the world each frame, when it leaves the world it dispatches Sprite.events.onOutOfBounds
  21359. * and optionally kills the sprite (if Sprite.outOfBoundsKill is true). By default this is disabled because the Sprite has to calculate its
  21360. * bounds every frame to support it, and not all games need it. Enable it by setting the value to true.
  21361. * @property {boolean} checkWorldBounds
  21362. * @default
  21363. */
  21364. this.checkWorldBounds = false;
  21365. /**
  21366. * @property {boolean} outOfBoundsKill - If true Sprite.kill is called as soon as Sprite.inWorld returns false, as long as Sprite.checkWorldBounds is true.
  21367. * @default
  21368. */
  21369. this.outOfBoundsKill = false;
  21370. /**
  21371. * @property {boolean} debug - Handy flag to use with Game.enableStep
  21372. * @default
  21373. */
  21374. this.debug = false;
  21375. /**
  21376. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  21377. */
  21378. this.cameraOffset = new Phaser.Point();
  21379. /**
  21380. * A small internal cache:
  21381. * 0 = previous position.x
  21382. * 1 = previous position.y
  21383. * 2 = previous rotation
  21384. * 3 = renderID
  21385. * 4 = fresh? (0 = no, 1 = yes)
  21386. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  21387. * 6 = exists (0 = no, 1 = yes)
  21388. * 7 = fixed to camera (0 = no, 1 = yes)
  21389. * @property {Array} _cache
  21390. * @private
  21391. */
  21392. this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0 ];
  21393. /**
  21394. * @property {Phaser.Rectangle} _bounds - Internal cache var.
  21395. * @private
  21396. */
  21397. this._bounds = new Phaser.Rectangle();
  21398. };
  21399. Phaser.Sprite.prototype = Object.create(PIXI.Sprite.prototype);
  21400. Phaser.Sprite.prototype.constructor = Phaser.Sprite;
  21401. /**
  21402. * Automatically called by World.preUpdate.
  21403. *
  21404. * @method Phaser.Sprite#preUpdate
  21405. * @memberof Phaser.Sprite
  21406. * @return {boolean} True if the Sprite was rendered, otherwise false.
  21407. */
  21408. Phaser.Sprite.prototype.preUpdate = function() {
  21409. if (this._cache[4] === 1 && this.exists)
  21410. {
  21411. this.world.setTo(this.parent.position.x + this.position.x, this.parent.position.y + this.position.y);
  21412. this.worldTransform.tx = this.world.x;
  21413. this.worldTransform.ty = this.world.y;
  21414. this._cache[0] = this.world.x;
  21415. this._cache[1] = this.world.y;
  21416. this._cache[2] = this.rotation;
  21417. if (this.body)
  21418. {
  21419. this.body.preUpdate();
  21420. }
  21421. this._cache[4] = 0;
  21422. return false;
  21423. }
  21424. this._cache[0] = this.world.x;
  21425. this._cache[1] = this.world.y;
  21426. this._cache[2] = this.rotation;
  21427. if (!this.exists || !this.parent.exists)
  21428. {
  21429. // Reset the renderOrderID
  21430. this._cache[3] = -1;
  21431. return false;
  21432. }
  21433. if (this.lifespan > 0)
  21434. {
  21435. this.lifespan -= this.game.time.elapsed;
  21436. if (this.lifespan <= 0)
  21437. {
  21438. this.kill();
  21439. return false;
  21440. }
  21441. }
  21442. // Cache the bounds if we need it
  21443. if (this.autoCull || this.checkWorldBounds)
  21444. {
  21445. this._bounds.copyFrom(this.getBounds());
  21446. }
  21447. if (this.autoCull)
  21448. {
  21449. // Won't get rendered but will still get its transform updated
  21450. this.renderable = this.game.world.camera.screenView.intersects(this._bounds);
  21451. }
  21452. if (this.checkWorldBounds)
  21453. {
  21454. // The Sprite is already out of the world bounds, so let's check to see if it has come back again
  21455. if (this._cache[5] === 1 && this.game.world.bounds.intersects(this._bounds))
  21456. {
  21457. this._cache[5] = 0;
  21458. this.events.onEnterBounds.dispatch(this);
  21459. }
  21460. else if (this._cache[5] === 0 && !this.game.world.bounds.intersects(this._bounds))
  21461. {
  21462. // The Sprite WAS in the screen, but has now left.
  21463. this._cache[5] = 1;
  21464. this.events.onOutOfBounds.dispatch(this);
  21465. if (this.outOfBoundsKill)
  21466. {
  21467. this.kill();
  21468. return false;
  21469. }
  21470. }
  21471. }
  21472. this.world.setTo(this.game.camera.x + this.worldTransform.tx, this.game.camera.y + this.worldTransform.ty);
  21473. if (this.visible)
  21474. {
  21475. this._cache[3] = this.game.stage.currentRenderOrderID++;
  21476. }
  21477. this.animations.update();
  21478. if (this.body)
  21479. {
  21480. this.body.preUpdate();
  21481. }
  21482. // Update any Children
  21483. for (var i = 0, len = this.children.length; i < len; i++)
  21484. {
  21485. this.children[i].preUpdate();
  21486. }
  21487. return true;
  21488. };
  21489. /**
  21490. * Override and use this function in your own custom objects to handle any update requirements you may have.
  21491. * Remember if this Sprite has any children you should call update on them too.
  21492. *
  21493. * @method Phaser.Sprite#update
  21494. * @memberof Phaser.Sprite
  21495. */
  21496. Phaser.Sprite.prototype.update = function() {
  21497. };
  21498. /**
  21499. * Internal function called by the World postUpdate cycle.
  21500. *
  21501. * @method Phaser.Sprite#postUpdate
  21502. * @memberof Phaser.Sprite
  21503. */
  21504. Phaser.Sprite.prototype.postUpdate = function() {
  21505. if (this.key instanceof Phaser.BitmapData)
  21506. {
  21507. this.key.render();
  21508. }
  21509. if (this.exists && this.body)
  21510. {
  21511. this.body.postUpdate();
  21512. }
  21513. // Fixed to Camera?
  21514. if (this._cache[7] === 1)
  21515. {
  21516. this.position.x = (this.game.camera.view.x + this.cameraOffset.x) / this.game.camera.scale.x;
  21517. this.position.y = (this.game.camera.view.y + this.cameraOffset.y) / this.game.camera.scale.y;
  21518. }
  21519. // Update any Children
  21520. for (var i = 0, len = this.children.length; i < len; i++)
  21521. {
  21522. this.children[i].postUpdate();
  21523. }
  21524. };
  21525. /**
  21526. * Changes the Texture the Sprite is using entirely. The old texture is removed and the new one is referenced or fetched from the Cache.
  21527. * This causes a WebGL texture update, so use sparingly or in low-intensity portions of your game.
  21528. *
  21529. * @method Phaser.Sprite#loadTexture
  21530. * @memberof Phaser.Sprite
  21531. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  21532. * @param {string|number} frame - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  21533. */
  21534. Phaser.Sprite.prototype.loadTexture = function (key, frame) {
  21535. frame = frame || 0;
  21536. if (key instanceof Phaser.RenderTexture)
  21537. {
  21538. this.key = key.key;
  21539. this.setTexture(key);
  21540. return;
  21541. }
  21542. else if (key instanceof Phaser.BitmapData)
  21543. {
  21544. this.key = key;
  21545. this.setTexture(key.texture);
  21546. return;
  21547. }
  21548. else if (key instanceof PIXI.Texture)
  21549. {
  21550. this.key = key;
  21551. this.setTexture(key);
  21552. return;
  21553. }
  21554. else
  21555. {
  21556. if (key === null || typeof key === 'undefined')
  21557. {
  21558. this.key = '__default';
  21559. this.setTexture(PIXI.TextureCache[this.key]);
  21560. return;
  21561. }
  21562. else if (typeof key === 'string' && !this.game.cache.checkImageKey(key))
  21563. {
  21564. this.key = '__missing';
  21565. this.setTexture(PIXI.TextureCache[this.key]);
  21566. return;
  21567. }
  21568. if (this.game.cache.isSpriteSheet(key))
  21569. {
  21570. this.key = key;
  21571. // var frameData = this.game.cache.getFrameData(key);
  21572. this.animations.loadFrameData(this.game.cache.getFrameData(key));
  21573. if (typeof frame === 'string')
  21574. {
  21575. this.frameName = frame;
  21576. }
  21577. else
  21578. {
  21579. this.frame = frame;
  21580. }
  21581. }
  21582. else
  21583. {
  21584. this.key = key;
  21585. this.setTexture(PIXI.TextureCache[key]);
  21586. return;
  21587. }
  21588. }
  21589. };
  21590. /**
  21591. * Crop allows you to crop the texture used to display this Sprite.
  21592. * Cropping takes place from the top-left of the Sprite and can be modified in real-time by providing an updated rectangle object.
  21593. * Note that cropping a Sprite will reset its animation to the first frame. You cannot currently crop an animated Sprite.
  21594. *
  21595. * @method Phaser.Sprite#crop
  21596. * @memberof Phaser.Sprite
  21597. * @param {Phaser.Rectangle} rect - The Rectangle to crop the Sprite to. Pass null or no parameters to clear a previously set crop rectangle.
  21598. */
  21599. Phaser.Sprite.prototype.crop = function(rect) {
  21600. if (typeof rect === 'undefined' || rect === null)
  21601. {
  21602. // Clear any crop that may be set
  21603. if (this.texture.hasOwnProperty('sourceWidth'))
  21604. {
  21605. this.texture.setFrame(new Phaser.Rectangle(0, 0, this.texture.sourceWidth, this.texture.sourceHeight));
  21606. }
  21607. }
  21608. else
  21609. {
  21610. // Do we need to clone the PIXI.Texture object?
  21611. if (this.texture instanceof PIXI.Texture)
  21612. {
  21613. // Yup, let's rock it ...
  21614. var local = {};
  21615. Phaser.Utils.extend(true, local, this.texture);
  21616. local.sourceWidth = local.width;
  21617. local.sourceHeight = local.height;
  21618. local.frame = rect;
  21619. local.width = rect.width;
  21620. local.height = rect.height;
  21621. this.texture = local;
  21622. this.texture.updateFrame = true;
  21623. PIXI.Texture.frameUpdates.push(this.texture);
  21624. }
  21625. else
  21626. {
  21627. this.texture.setFrame(rect);
  21628. }
  21629. }
  21630. };
  21631. /**
  21632. * Brings a 'dead' Sprite back to life, optionally giving it the health value specified.
  21633. * A resurrected Sprite has its alive, exists and visible properties all set to true.
  21634. * It will dispatch the onRevived event, you can listen to Sprite.events.onRevived for the signal.
  21635. *
  21636. * @method Phaser.Sprite#revive
  21637. * @memberof Phaser.Sprite
  21638. * @param {number} [health=1] - The health to give the Sprite.
  21639. * @return (Phaser.Sprite) This instance.
  21640. */
  21641. Phaser.Sprite.prototype.revive = function(health) {
  21642. if (typeof health === 'undefined') { health = 1; }
  21643. this.alive = true;
  21644. this.exists = true;
  21645. this.visible = true;
  21646. this.health = health;
  21647. if (this.events)
  21648. {
  21649. this.events.onRevived.dispatch(this);
  21650. }
  21651. return this;
  21652. };
  21653. /**
  21654. * Kills a Sprite. A killed Sprite has its alive, exists and visible properties all set to false.
  21655. * It will dispatch the onKilled event, you can listen to Sprite.events.onKilled for the signal.
  21656. * Note that killing a Sprite is a way for you to quickly recycle it in a Sprite pool, it doesn't free it up from memory.
  21657. * If you don't need this Sprite any more you should call Sprite.destroy instead.
  21658. *
  21659. * @method Phaser.Sprite#kill
  21660. * @memberof Phaser.Sprite
  21661. * @return (Phaser.Sprite) This instance.
  21662. */
  21663. Phaser.Sprite.prototype.kill = function() {
  21664. this.alive = false;
  21665. this.exists = false;
  21666. this.visible = false;
  21667. if (this.events)
  21668. {
  21669. this.events.onKilled.dispatch(this);
  21670. }
  21671. return this;
  21672. };
  21673. /**
  21674. * Destroys the Sprite. This removes it from its parent group, destroys the input, event and animation handlers if present
  21675. * and nulls its reference to game, freeing it up for garbage collection.
  21676. *
  21677. * @method Phaser.Sprite#destroy
  21678. * @memberof Phaser.Sprite
  21679. * @param {boolean} [destroyChildren=true] - Should every child of this object have its destroy method called?
  21680. */
  21681. Phaser.Sprite.prototype.destroy = function(destroyChildren) {
  21682. if (this.game === null) { return; }
  21683. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  21684. if (this.parent)
  21685. {
  21686. if (this.parent instanceof Phaser.Group)
  21687. {
  21688. this.parent.remove(this);
  21689. }
  21690. else
  21691. {
  21692. this.parent.removeChild(this);
  21693. }
  21694. }
  21695. if (this.input)
  21696. {
  21697. this.input.destroy();
  21698. }
  21699. if (this.animations)
  21700. {
  21701. this.animations.destroy();
  21702. }
  21703. if (this.body)
  21704. {
  21705. this.body.destroy();
  21706. }
  21707. if (this.events)
  21708. {
  21709. this.events.destroy();
  21710. }
  21711. var i = this.children.length;
  21712. if (destroyChildren)
  21713. {
  21714. while (i--)
  21715. {
  21716. this.children[i].destroy(destroyChildren);
  21717. }
  21718. }
  21719. else
  21720. {
  21721. while (i--)
  21722. {
  21723. this.removeChild(this.children[i]);
  21724. }
  21725. }
  21726. this.alive = false;
  21727. this.exists = false;
  21728. this.visible = false;
  21729. this.filters = null;
  21730. this.mask = null;
  21731. this.game = null;
  21732. };
  21733. /**
  21734. * Damages the Sprite, this removes the given amount from the Sprites health property.
  21735. * If health is then taken below or is equal to zero `Sprite.kill` is called.
  21736. *
  21737. * @method Phaser.Sprite#damage
  21738. * @memberof Phaser.Sprite
  21739. * @param {number} amount - The amount to subtract from the Sprite.health value.
  21740. * @return (Phaser.Sprite) This instance.
  21741. */
  21742. Phaser.Sprite.prototype.damage = function(amount) {
  21743. if (this.alive)
  21744. {
  21745. this.health -= amount;
  21746. if (this.health <= 0)
  21747. {
  21748. this.kill();
  21749. }
  21750. }
  21751. return this;
  21752. };
  21753. /**
  21754. * Resets the Sprite. This places the Sprite at the given x/y world coordinates and then
  21755. * sets alive, exists, visible and renderable all to true. Also resets the outOfBounds state and health values.
  21756. * If the Sprite has a physics body that too is reset.
  21757. *
  21758. * @method Phaser.Sprite#reset
  21759. * @memberof Phaser.Sprite
  21760. * @param {number} x - The x coordinate (in world space) to position the Sprite at.
  21761. * @param {number} y - The y coordinate (in world space) to position the Sprite at.
  21762. * @param {number} [health=1] - The health to give the Sprite.
  21763. * @return (Phaser.Sprite) This instance.
  21764. */
  21765. Phaser.Sprite.prototype.reset = function(x, y, health) {
  21766. if (typeof health === 'undefined') { health = 1; }
  21767. this.world.setTo(x, y);
  21768. this.position.x = x;
  21769. this.position.y = y;
  21770. this.alive = true;
  21771. this.exists = true;
  21772. this.visible = true;
  21773. this.renderable = true;
  21774. this._outOfBoundsFired = false;
  21775. this.health = health;
  21776. if (this.body)
  21777. {
  21778. this.body.reset(x, y, false, false);
  21779. }
  21780. this._cache[4] = 1;
  21781. return this;
  21782. };
  21783. /**
  21784. * Brings the Sprite to the top of the display list it is a child of. Sprites that are members of a Phaser.Group are only
  21785. * bought to the top of that Group, not the entire display list.
  21786. *
  21787. * @method Phaser.Sprite#bringToTop
  21788. * @memberof Phaser.Sprite
  21789. * @return (Phaser.Sprite) This instance.
  21790. */
  21791. Phaser.Sprite.prototype.bringToTop = function() {
  21792. if (this.parent)
  21793. {
  21794. this.parent.bringToTop(this);
  21795. }
  21796. return this;
  21797. };
  21798. /**
  21799. * Play an animation based on the given key. The animation should previously have been added via sprite.animations.add()
  21800. * If the requested animation is already playing this request will be ignored. If you need to reset an already running animation do so directly on the Animation object itself.
  21801. *
  21802. * @method Phaser.Sprite#play
  21803. * @memberof Phaser.Sprite
  21804. * @param {string} name - The name of the animation to be played, e.g. "fire", "walk", "jump".
  21805. * @param {number} [frameRate=null] - The framerate to play the animation at. The speed is given in frames per second. If not provided the previously set frameRate of the Animation is used.
  21806. * @param {boolean} [loop=false] - Should the animation be looped after playback. If not provided the previously set loop value of the Animation is used.
  21807. * @param {boolean} [killOnComplete=false] - If set to true when the animation completes (only happens if loop=false) the parent Sprite will be killed.
  21808. * @return {Phaser.Animation} A reference to playing Animation instance.
  21809. */
  21810. Phaser.Sprite.prototype.play = function (name, frameRate, loop, killOnComplete) {
  21811. if (this.animations)
  21812. {
  21813. return this.animations.play(name, frameRate, loop, killOnComplete);
  21814. }
  21815. };
  21816. /**
  21817. * Checks to see if the bounds of this Sprite overlaps with the bounds of the given Display Object, which can be a Sprite, Image, TileSprite or anything that extends those such as a Button.
  21818. * This check ignores the Sprites hitArea property and runs a Sprite.getBounds comparison on both objects to determine the result.
  21819. * Therefore it's relatively expensive to use in large quantities (i.e. with lots of Sprites at a high frequency), but should be fine for low-volume testing where physics isn't required.
  21820. *
  21821. * @method Phaser.Sprite#overlap
  21822. * @memberof Phaser.Sprite
  21823. * @param {Phaser.Sprite|Phaser.Image|Phaser.TileSprite|Phaser.Button|PIXI.DisplayObject} displayObject - The display object to check against.
  21824. * @return {boolean} True if the bounds of this Sprite intersects at any point with the bounds of the given display object.
  21825. */
  21826. Phaser.Sprite.prototype.overlap = function (displayObject) {
  21827. return Phaser.Rectangle.intersects(this.getBounds(), displayObject.getBounds());
  21828. };
  21829. /**
  21830. * Indicates the rotation of the Sprite, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation.
  21831. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90.
  21832. * If you wish to work in radians instead of degrees use the property Sprite.rotation instead. Working in radians is also a little faster as it doesn't have to convert the angle.
  21833. *
  21834. * @name Phaser.Sprite#angle
  21835. * @property {number} angle - The angle of this Sprite in degrees.
  21836. */
  21837. Object.defineProperty(Phaser.Sprite.prototype, "angle", {
  21838. get: function() {
  21839. return Phaser.Math.wrapAngle(Phaser.Math.radToDeg(this.rotation));
  21840. },
  21841. set: function(value) {
  21842. this.rotation = Phaser.Math.degToRad(Phaser.Math.wrapAngle(value));
  21843. }
  21844. });
  21845. /**
  21846. * Returns the delta x value. The difference between world.x now and in the previous step.
  21847. *
  21848. * @name Phaser.Sprite#deltaX
  21849. * @property {number} deltaX - The delta value. Positive if the motion was to the right, negative if to the left.
  21850. * @readonly
  21851. */
  21852. Object.defineProperty(Phaser.Sprite.prototype, "deltaX", {
  21853. get: function() {
  21854. return this.world.x - this._cache[0];
  21855. }
  21856. });
  21857. /**
  21858. * Returns the delta y value. The difference between world.y now and in the previous step.
  21859. *
  21860. * @name Phaser.Sprite#deltaY
  21861. * @property {number} deltaY - The delta value. Positive if the motion was downwards, negative if upwards.
  21862. * @readonly
  21863. */
  21864. Object.defineProperty(Phaser.Sprite.prototype, "deltaY", {
  21865. get: function() {
  21866. return this.world.y - this._cache[1];
  21867. }
  21868. });
  21869. /**
  21870. * Returns the delta z value. The difference between rotation now and in the previous step.
  21871. *
  21872. * @name Phaser.Sprite#deltaZ
  21873. * @property {number} deltaZ - The delta value.
  21874. * @readonly
  21875. */
  21876. Object.defineProperty(Phaser.Sprite.prototype, "deltaZ", {
  21877. get: function() {
  21878. return this.rotation - this._cache[2];
  21879. }
  21880. });
  21881. /**
  21882. * Checks if the Sprite bounds are within the game world, otherwise false if fully outside of it.
  21883. *
  21884. * @name Phaser.Sprite#inWorld
  21885. * @property {boolean} inWorld - True if the Sprite bounds is within the game world, even if only partially. Otherwise false if fully outside of it.
  21886. * @readonly
  21887. */
  21888. Object.defineProperty(Phaser.Sprite.prototype, "inWorld", {
  21889. get: function() {
  21890. return this.game.world.bounds.intersects(this.getBounds());
  21891. }
  21892. });
  21893. /**
  21894. * Checks if the Sprite bounds are within the game camera, otherwise false if fully outside of it.
  21895. *
  21896. * @name Phaser.Sprite#inCamera
  21897. * @property {boolean} inCamera - True if the Sprite bounds is within the game camera, even if only partially. Otherwise false if fully outside of it.
  21898. * @readonly
  21899. */
  21900. Object.defineProperty(Phaser.Sprite.prototype, "inCamera", {
  21901. get: function() {
  21902. return this.game.world.camera.screenView.intersects(this.getBounds());
  21903. }
  21904. });
  21905. /**
  21906. * @name Phaser.Sprite#frame
  21907. * @property {number} frame - Gets or sets the current frame index and updates the Texture Cache for display.
  21908. */
  21909. Object.defineProperty(Phaser.Sprite.prototype, "frame", {
  21910. get: function () {
  21911. return this.animations.frame;
  21912. },
  21913. set: function (value) {
  21914. this.animations.frame = value;
  21915. }
  21916. });
  21917. /**
  21918. * @name Phaser.Sprite#frameName
  21919. * @property {string} frameName - Gets or sets the current frame name and updates the Texture Cache for display.
  21920. */
  21921. Object.defineProperty(Phaser.Sprite.prototype, "frameName", {
  21922. get: function () {
  21923. return this.animations.frameName;
  21924. },
  21925. set: function (value) {
  21926. this.animations.frameName = value;
  21927. }
  21928. });
  21929. /**
  21930. * @name Phaser.Sprite#renderOrderID
  21931. * @property {number} renderOrderID - The render order ID, reset every frame.
  21932. * @readonly
  21933. */
  21934. Object.defineProperty(Phaser.Sprite.prototype, "renderOrderID", {
  21935. get: function() {
  21936. return this._cache[3];
  21937. }
  21938. });
  21939. /**
  21940. * By default a Sprite won't process any input events at all. By setting inputEnabled to true the Phaser.InputHandler is
  21941. * activated for this object and it will then start to process click/touch events and more.
  21942. *
  21943. * @name Phaser.Sprite#inputEnabled
  21944. * @property {boolean} inputEnabled - Set to true to allow this object to receive input events.
  21945. */
  21946. Object.defineProperty(Phaser.Sprite.prototype, "inputEnabled", {
  21947. get: function () {
  21948. return (this.input && this.input.enabled);
  21949. },
  21950. set: function (value) {
  21951. if (value)
  21952. {
  21953. if (this.input === null)
  21954. {
  21955. this.input = new Phaser.InputHandler(this);
  21956. this.input.start();
  21957. }
  21958. else if (this.input && !this.input.enabled)
  21959. {
  21960. this.input.start();
  21961. }
  21962. }
  21963. else
  21964. {
  21965. if (this.input && this.input.enabled)
  21966. {
  21967. this.input.stop();
  21968. }
  21969. }
  21970. }
  21971. });
  21972. /**
  21973. * Sprite.exists controls if the core game loop and physics update this Sprite or not.
  21974. * When you set Sprite.exists to false it will remove its Body from the physics world (if it has one) and also set Sprite.visible to false.
  21975. * Setting Sprite.exists to true will re-add the Body to the physics world (if it has a body) and set Sprite.visible to true.
  21976. *
  21977. * @name Phaser.Sprite#exists
  21978. * @property {boolean} exists - If the Sprite is processed by the core game update and physics.
  21979. */
  21980. Object.defineProperty(Phaser.Sprite.prototype, "exists", {
  21981. get: function () {
  21982. return !!this._cache[6];
  21983. },
  21984. set: function (value) {
  21985. if (value)
  21986. {
  21987. // exists = true
  21988. this._cache[6] = 1;
  21989. if (this.body && this.body.type === Phaser.Physics.P2JS)
  21990. {
  21991. this.body.addToWorld();
  21992. }
  21993. this.visible = true;
  21994. }
  21995. else
  21996. {
  21997. // exists = false
  21998. this._cache[6] = 0;
  21999. if (this.body && this.body.type === Phaser.Physics.P2JS)
  22000. {
  22001. this.body.removeFromWorld();
  22002. }
  22003. this.visible = false;
  22004. }
  22005. }
  22006. });
  22007. /**
  22008. * An Sprite that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in Sprite.cameraOffset.
  22009. * Note that the cameraOffset values are in addition to any parent in the display list.
  22010. * So if this Sprite was in a Group that has x: 200, then this will be added to the cameraOffset.x
  22011. *
  22012. * @name Phaser.Sprite#fixedToCamera
  22013. * @property {boolean} fixedToCamera - Set to true to fix this Sprite to the Camera at its current world coordinates.
  22014. */
  22015. Object.defineProperty(Phaser.Sprite.prototype, "fixedToCamera", {
  22016. get: function () {
  22017. return !!this._cache[7];
  22018. },
  22019. set: function (value) {
  22020. if (value)
  22021. {
  22022. this._cache[7] = 1;
  22023. this.cameraOffset.set(this.x, this.y);
  22024. }
  22025. else
  22026. {
  22027. this._cache[7] = 0;
  22028. }
  22029. }
  22030. });
  22031. /**
  22032. * Enable or disable texture smoothing for this Sprite. Only works for bitmap/image textures. Smoothing is enabled by default.
  22033. *
  22034. * @name Phaser.Sprite#smoothed
  22035. * @property {boolean} smoothed - Set to true to smooth the texture of this Sprite, or false to disable smoothing (great for pixel art)
  22036. */
  22037. Object.defineProperty(Phaser.Sprite.prototype, "smoothed", {
  22038. get: function () {
  22039. return !this.texture.baseTexture.scaleMode;
  22040. },
  22041. set: function (value) {
  22042. if (value)
  22043. {
  22044. if (this.texture)
  22045. {
  22046. this.texture.baseTexture.scaleMode = 0;
  22047. }
  22048. }
  22049. else
  22050. {
  22051. if (this.texture)
  22052. {
  22053. this.texture.baseTexture.scaleMode = 1;
  22054. }
  22055. }
  22056. }
  22057. });
  22058. /**
  22059. * The position of the Sprite on the x axis relative to the local coordinates of the parent.
  22060. *
  22061. * @name Phaser.Sprite#x
  22062. * @property {number} x - The position of the Sprite on the x axis relative to the local coordinates of the parent.
  22063. */
  22064. Object.defineProperty(Phaser.Sprite.prototype, "x", {
  22065. get: function () {
  22066. return this.position.x;
  22067. },
  22068. set: function (value) {
  22069. this.position.x = value;
  22070. if (this.body && this.body.type === Phaser.Physics.ARCADE && this.body.phase === 2)
  22071. {
  22072. this.body._reset = 1;
  22073. }
  22074. }
  22075. });
  22076. /**
  22077. * The position of the Sprite on the y axis relative to the local coordinates of the parent.
  22078. *
  22079. * @name Phaser.Sprite#y
  22080. * @property {number} y - The position of the Sprite on the y axis relative to the local coordinates of the parent.
  22081. */
  22082. Object.defineProperty(Phaser.Sprite.prototype, "y", {
  22083. get: function () {
  22084. return this.position.y;
  22085. },
  22086. set: function (value) {
  22087. this.position.y = value;
  22088. if (this.body && this.body.type === Phaser.Physics.ARCADE && this.body.phase === 2)
  22089. {
  22090. this.body._reset = 1;
  22091. }
  22092. }
  22093. });
  22094. /**
  22095. * @author Richard Davey <rich@photonstorm.com>
  22096. * @copyright 2014 Photon Storm Ltd.
  22097. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  22098. */
  22099. /**
  22100. * @class Phaser.Image
  22101. *
  22102. * @classdesc Create a new `Image` object. An Image is a light-weight object you can use to display anything that doesn't need physics or animation.
  22103. * It can still rotate, scale, crop and receive input events. This makes it perfect for logos, backgrounds, simple buttons and other non-Sprite graphics.
  22104. *
  22105. * @constructor
  22106. * @param {Phaser.Game} game - A reference to the currently running game.
  22107. * @param {number} x - The x coordinate of the Imaget. The coordinate is relative to any parent container this Image may be in.
  22108. * @param {number} y - The y coordinate of the Image. The coordinate is relative to any parent container this Image may be in.
  22109. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - The texture used by the Image during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  22110. * @param {string|number} frame - If this Image is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  22111. */
  22112. Phaser.Image = function (game, x, y, key, frame) {
  22113. x = x || 0;
  22114. y = y || 0;
  22115. key = key || null;
  22116. frame = frame || null;
  22117. /**
  22118. * @property {Phaser.Game} game - A reference to the currently running Game.
  22119. */
  22120. this.game = game;
  22121. /**
  22122. * @property {boolean} exists - If exists = false then the Image isn't updated by the core game loop.
  22123. * @default
  22124. */
  22125. this.exists = true;
  22126. /**
  22127. * @property {string} name - The user defined name given to this Image.
  22128. * @default
  22129. */
  22130. this.name = '';
  22131. /**
  22132. * @property {number} type - The const type of this object.
  22133. * @readonly
  22134. */
  22135. this.type = Phaser.IMAGE;
  22136. /**
  22137. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  22138. */
  22139. this.z = 0;
  22140. /**
  22141. * @property {Phaser.Events} events - The Events you can subscribe to that are dispatched when certain things happen on this Image or its components.
  22142. */
  22143. this.events = new Phaser.Events(this);
  22144. /**
  22145. * @property {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Image during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  22146. */
  22147. this.key = key;
  22148. /**
  22149. * @property {number} _frame - Internal cache var.
  22150. * @private
  22151. */
  22152. this._frame = 0;
  22153. /**
  22154. * @property {string} _frameName - Internal cache var.
  22155. * @private
  22156. */
  22157. this._frameName = '';
  22158. PIXI.Sprite.call(this, PIXI.TextureCache['__default']);
  22159. this.loadTexture(key, frame);
  22160. this.position.set(x, y);
  22161. /**
  22162. * @property {Phaser.Point} world - The world coordinates of this Image. This differs from the x/y coordinates which are relative to the Images container.
  22163. */
  22164. this.world = new Phaser.Point(x, y);
  22165. /**
  22166. * Should this Image be automatically culled if out of range of the camera?
  22167. * A culled sprite has its renderable property set to 'false'.
  22168. * Be advised this is quite an expensive operation, as it has to calculate the bounds of the object every frame, so only enable it if you really need it.
  22169. *
  22170. * @property {boolean} autoCull - A flag indicating if the Image should be automatically camera culled or not.
  22171. * @default
  22172. */
  22173. this.autoCull = false;
  22174. /**
  22175. * @property {Phaser.InputHandler|null} input - The Input Handler for this object. Needs to be enabled with image.inputEnabled = true before you can use it.
  22176. */
  22177. this.input = null;
  22178. /**
  22179. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  22180. */
  22181. this.cameraOffset = new Phaser.Point();
  22182. /**
  22183. * A small internal cache:
  22184. * 0 = previous position.x
  22185. * 1 = previous position.y
  22186. * 2 = previous rotation
  22187. * 3 = renderID
  22188. * 4 = fresh? (0 = no, 1 = yes)
  22189. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  22190. * 6 = exists (0 = no, 1 = yes)
  22191. * 7 = fixed to camera (0 = no, 1 = yes)
  22192. * @property {Array} _cache
  22193. * @private
  22194. */
  22195. this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0 ];
  22196. };
  22197. Phaser.Image.prototype = Object.create(PIXI.Sprite.prototype);
  22198. Phaser.Image.prototype.constructor = Phaser.Image;
  22199. /**
  22200. * Automatically called by World.preUpdate.
  22201. *
  22202. * @method Phaser.Image#preUpdate
  22203. * @memberof Phaser.Image
  22204. */
  22205. Phaser.Image.prototype.preUpdate = function() {
  22206. this._cache[0] = this.world.x;
  22207. this._cache[1] = this.world.y;
  22208. this._cache[2] = this.rotation;
  22209. if (!this.exists || !this.parent.exists)
  22210. {
  22211. this._cache[3] = -1;
  22212. return false;
  22213. }
  22214. if (this.autoCull)
  22215. {
  22216. // Won't get rendered but will still get its transform updated
  22217. this.renderable = this.game.world.camera.screenView.intersects(this.getBounds());
  22218. }
  22219. this.world.setTo(this.game.camera.x + this.worldTransform[2], this.game.camera.y + this.worldTransform[5]);
  22220. if (this.visible)
  22221. {
  22222. this._cache[3] = this.game.stage.currentRenderOrderID++;
  22223. }
  22224. // Update any Children
  22225. for (var i = 0, len = this.children.length; i < len; i++)
  22226. {
  22227. this.children[i].preUpdate();
  22228. }
  22229. return true;
  22230. };
  22231. /**
  22232. * Override and use this function in your own custom objects to handle any update requirements you may have.
  22233. *
  22234. * @method Phaser.Image#update
  22235. * @memberof Phaser.Image
  22236. */
  22237. Phaser.Image.prototype.update = function() {
  22238. };
  22239. /**
  22240. * Internal function called by the World postUpdate cycle.
  22241. *
  22242. * @method Phaser.Image#postUpdate
  22243. * @memberof Phaser.Image
  22244. */
  22245. Phaser.Image.prototype.postUpdate = function() {
  22246. if (this.key instanceof Phaser.BitmapData)
  22247. {
  22248. this.key.render();
  22249. }
  22250. // Fixed to Camera?
  22251. if (this._cache[7] === 1)
  22252. {
  22253. this.position.x = (this.game.camera.view.x + this.cameraOffset.x) / this.game.camera.scale.x;
  22254. this.position.y = (this.game.camera.view.y + this.cameraOffset.y) / this.game.camera.scale.y;
  22255. }
  22256. // Update any Children
  22257. for (var i = 0, len = this.children.length; i < len; i++)
  22258. {
  22259. this.children[i].postUpdate();
  22260. }
  22261. };
  22262. /**
  22263. * Changes the Texture the Image is using entirely. The old texture is removed and the new one is referenced or fetched from the Cache.
  22264. * This causes a WebGL texture update, so use sparingly or in low-intensity portions of your game.
  22265. *
  22266. * @method Phaser.Image#loadTexture
  22267. * @memberof Phaser.Image
  22268. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Image during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  22269. * @param {string|number} frame - If this Image is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  22270. */
  22271. Phaser.Image.prototype.loadTexture = function (key, frame) {
  22272. frame = frame || 0;
  22273. if (key instanceof Phaser.RenderTexture)
  22274. {
  22275. this.key = key.key;
  22276. this.setTexture(key);
  22277. return;
  22278. }
  22279. else if (key instanceof Phaser.BitmapData)
  22280. {
  22281. this.key = key;
  22282. this.setTexture(key.texture);
  22283. return;
  22284. }
  22285. else if (key instanceof PIXI.Texture)
  22286. {
  22287. this.key = key;
  22288. this.setTexture(key);
  22289. return;
  22290. }
  22291. else
  22292. {
  22293. if (key === null || typeof key === 'undefined')
  22294. {
  22295. this.key = '__default';
  22296. this.setTexture(PIXI.TextureCache[this.key]);
  22297. return;
  22298. }
  22299. else if (typeof key === 'string' && !this.game.cache.checkImageKey(key))
  22300. {
  22301. this.key = '__missing';
  22302. this.setTexture(PIXI.TextureCache[this.key]);
  22303. return;
  22304. }
  22305. if (this.game.cache.isSpriteSheet(key))
  22306. {
  22307. this.key = key;
  22308. var frameData = this.game.cache.getFrameData(key);
  22309. if (typeof frame === 'string')
  22310. {
  22311. this._frame = 0;
  22312. this._frameName = frame;
  22313. this.setTexture(PIXI.TextureCache[frameData.getFrameByName(frame).uuid]);
  22314. return;
  22315. }
  22316. else
  22317. {
  22318. this._frame = frame;
  22319. this._frameName = '';
  22320. this.setTexture(PIXI.TextureCache[frameData.getFrame(frame).uuid]);
  22321. return;
  22322. }
  22323. }
  22324. else
  22325. {
  22326. this.key = key;
  22327. this.setTexture(PIXI.TextureCache[key]);
  22328. return;
  22329. }
  22330. }
  22331. };
  22332. /**
  22333. * Crop allows you to crop the texture used to display this Image.
  22334. * Cropping takes place from the top-left of the Image and can be modified in real-time by providing an updated rectangle object.
  22335. *
  22336. * @method Phaser.Image#crop
  22337. * @memberof Phaser.Image
  22338. * @param {Phaser.Rectangle} rect - The Rectangle to crop the Image to. Pass null or no parameters to clear a previously set crop rectangle.
  22339. */
  22340. Phaser.Image.prototype.crop = function(rect) {
  22341. if (typeof rect === 'undefined' || rect === null)
  22342. {
  22343. // Clear any crop that may be set
  22344. if (this.texture.hasOwnProperty('sourceWidth'))
  22345. {
  22346. this.texture.setFrame(new Phaser.Rectangle(0, 0, this.texture.sourceWidth, this.texture.sourceHeight));
  22347. }
  22348. }
  22349. else
  22350. {
  22351. // Do we need to clone the PIXI.Texture object?
  22352. if (this.texture instanceof PIXI.Texture)
  22353. {
  22354. // Yup, let's rock it ...
  22355. var local = {};
  22356. Phaser.Utils.extend(true, local, this.texture);
  22357. local.sourceWidth = local.width;
  22358. local.sourceHeight = local.height;
  22359. local.frame = rect;
  22360. local.width = rect.width;
  22361. local.height = rect.height;
  22362. this.texture = local;
  22363. this.texture.updateFrame = true;
  22364. PIXI.Texture.frameUpdates.push(this.texture);
  22365. }
  22366. else
  22367. {
  22368. this.texture.setFrame(rect);
  22369. }
  22370. }
  22371. };
  22372. /**
  22373. * Brings a 'dead' Image back to life, optionally giving it the health value specified.
  22374. * A resurrected Image has its alive, exists and visible properties all set to true.
  22375. * It will dispatch the onRevived event, you can listen to Image.events.onRevived for the signal.
  22376. *
  22377. * @method Phaser.Image#revive
  22378. * @memberof Phaser.Image
  22379. * @return {Phaser.Image} This instance.
  22380. */
  22381. Phaser.Image.prototype.revive = function() {
  22382. this.alive = true;
  22383. this.exists = true;
  22384. this.visible = true;
  22385. if (this.events)
  22386. {
  22387. this.events.onRevived.dispatch(this);
  22388. }
  22389. return this;
  22390. };
  22391. /**
  22392. * Kills a Image. A killed Image has its alive, exists and visible properties all set to false.
  22393. * It will dispatch the onKilled event, you can listen to Image.events.onKilled for the signal.
  22394. * Note that killing a Image is a way for you to quickly recycle it in a Image pool, it doesn't free it up from memory.
  22395. * If you don't need this Image any more you should call Image.destroy instead.
  22396. *
  22397. * @method Phaser.Image#kill
  22398. * @memberof Phaser.Image
  22399. * @return {Phaser.Image} This instance.
  22400. */
  22401. Phaser.Image.prototype.kill = function() {
  22402. this.alive = false;
  22403. this.exists = false;
  22404. this.visible = false;
  22405. if (this.events)
  22406. {
  22407. this.events.onKilled.dispatch(this);
  22408. }
  22409. return this;
  22410. };
  22411. /**
  22412. * Destroys the Image. This removes it from its parent group, destroys the input, event and animation handlers if present
  22413. * and nulls its reference to game, freeing it up for garbage collection.
  22414. *
  22415. * @method Phaser.Image#destroy
  22416. * @memberof Phaser.Image
  22417. * @param {boolean} [destroyChildren=true] - Should every child of this object have its destroy method called?
  22418. */
  22419. Phaser.Image.prototype.destroy = function(destroyChildren) {
  22420. if (this.game === null) { return; }
  22421. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  22422. if (this.parent)
  22423. {
  22424. if (this.parent instanceof Phaser.Group)
  22425. {
  22426. this.parent.remove(this);
  22427. }
  22428. else
  22429. {
  22430. this.parent.removeChild(this);
  22431. }
  22432. }
  22433. if (this.events)
  22434. {
  22435. this.events.destroy();
  22436. }
  22437. if (this.input)
  22438. {
  22439. this.input.destroy();
  22440. }
  22441. var i = this.children.length;
  22442. if (destroyChildren)
  22443. {
  22444. while (i--)
  22445. {
  22446. this.children[i].destroy(destroyChildren);
  22447. }
  22448. }
  22449. else
  22450. {
  22451. while (i--)
  22452. {
  22453. this.removeChild(this.children[i]);
  22454. }
  22455. }
  22456. this.alive = false;
  22457. this.exists = false;
  22458. this.visible = false;
  22459. this.filters = null;
  22460. this.mask = null;
  22461. this.game = null;
  22462. };
  22463. /**
  22464. * Resets the Image. This places the Image at the given x/y world coordinates and then sets alive, exists, visible and renderable all to true.
  22465. *
  22466. * @method Phaser.Image#reset
  22467. * @memberof Phaser.Image
  22468. * @param {number} x - The x coordinate (in world space) to position the Image at.
  22469. * @param {number} y - The y coordinate (in world space) to position the Image at.
  22470. * @return {Phaser.Image} This instance.
  22471. */
  22472. Phaser.Image.prototype.reset = function(x, y) {
  22473. this.world.setTo(x, y);
  22474. this.position.x = x;
  22475. this.position.y = y;
  22476. this.alive = true;
  22477. this.exists = true;
  22478. this.visible = true;
  22479. this.renderable = true;
  22480. return this;
  22481. };
  22482. /**
  22483. * Brings the Image to the top of the display list it is a child of. Images that are members of a Phaser.Group are only
  22484. * bought to the top of that Group, not the entire display list.
  22485. *
  22486. * @method Phaser.Image#bringToTop
  22487. * @memberof Phaser.Image
  22488. * @return {Phaser.Image} This instance.
  22489. */
  22490. Phaser.Image.prototype.bringToTop = function() {
  22491. if (this.parent)
  22492. {
  22493. this.parent.bringToTop(this);
  22494. }
  22495. return this;
  22496. };
  22497. /**
  22498. * Indicates the rotation of the Image, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation.
  22499. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90.
  22500. * If you wish to work in radians instead of degrees use the property Image.rotation instead. Working in radians is also a little faster as it doesn't have to convert the angle.
  22501. *
  22502. * @name Phaser.Image#angle
  22503. * @property {number} angle - The angle of this Image in degrees.
  22504. */
  22505. Object.defineProperty(Phaser.Image.prototype, "angle", {
  22506. get: function() {
  22507. return Phaser.Math.wrapAngle(Phaser.Math.radToDeg(this.rotation));
  22508. },
  22509. set: function(value) {
  22510. this.rotation = Phaser.Math.degToRad(Phaser.Math.wrapAngle(value));
  22511. }
  22512. });
  22513. /**
  22514. * Returns the delta x value. The difference between world.x now and in the previous step.
  22515. *
  22516. * @name Phaser.Image#deltaX
  22517. * @property {number} deltaX - The delta value. Positive if the motion was to the right, negative if to the left.
  22518. * @readonly
  22519. */
  22520. Object.defineProperty(Phaser.Image.prototype, "deltaX", {
  22521. get: function() {
  22522. return this.world.x - this._cache[0];
  22523. }
  22524. });
  22525. /**
  22526. * Returns the delta y value. The difference between world.y now and in the previous step.
  22527. *
  22528. * @name Phaser.Image#deltaY
  22529. * @property {number} deltaY - The delta value. Positive if the motion was downwards, negative if upwards.
  22530. * @readonly
  22531. */
  22532. Object.defineProperty(Phaser.Image.prototype, "deltaY", {
  22533. get: function() {
  22534. return this.world.y - this._cache[1];
  22535. }
  22536. });
  22537. /**
  22538. * Returns the delta z value. The difference between rotation now and in the previous step.
  22539. *
  22540. * @name Phaser.Image#deltaZ
  22541. * @property {number} deltaZ - The delta value.
  22542. * @readonly
  22543. */
  22544. Object.defineProperty(Phaser.Image.prototype, "deltaZ", {
  22545. get: function() {
  22546. return this.rotation - this._cache[2];
  22547. }
  22548. });
  22549. /**
  22550. * Checks if the Image bounds are within the game world, otherwise false if fully outside of it.
  22551. *
  22552. * @name Phaser.Image#inWorld
  22553. * @property {boolean} inWorld - True if the Image bounds is within the game world, even if only partially. Otherwise false if fully outside of it.
  22554. * @readonly
  22555. */
  22556. Object.defineProperty(Phaser.Image.prototype, "inWorld", {
  22557. get: function() {
  22558. return this.game.world.bounds.intersects(this.getBounds());
  22559. }
  22560. });
  22561. /**
  22562. * Checks if the Image bounds are within the game camera, otherwise false if fully outside of it.
  22563. *
  22564. * @name Phaser.Image#inCamera
  22565. * @property {boolean} inCamera - True if the Image bounds is within the game camera, even if only partially. Otherwise false if fully outside of it.
  22566. * @readonly
  22567. */
  22568. Object.defineProperty(Phaser.Image.prototype, "inCamera", {
  22569. get: function() {
  22570. return this.game.world.camera.screenView.intersects(this.getBounds());
  22571. }
  22572. });
  22573. /**
  22574. * @name Phaser.Image#frame
  22575. * @property {number} frame - Gets or sets the current frame index and updates the Texture for display.
  22576. */
  22577. Object.defineProperty(Phaser.Image.prototype, "frame", {
  22578. get: function() {
  22579. return this._frame;
  22580. },
  22581. set: function(value) {
  22582. if (value !== this.frame && this.game.cache.isSpriteSheet(this.key))
  22583. {
  22584. var frameData = this.game.cache.getFrameData(this.key);
  22585. if (frameData && value < frameData.total && frameData.getFrame(value))
  22586. {
  22587. this.setTexture(PIXI.TextureCache[frameData.getFrame(value).uuid]);
  22588. this._frame = value;
  22589. }
  22590. }
  22591. }
  22592. });
  22593. /**
  22594. * @name Phaser.Image#frameName
  22595. * @property {string} frameName - Gets or sets the current frame by name and updates the Texture for display.
  22596. */
  22597. Object.defineProperty(Phaser.Image.prototype, "frameName", {
  22598. get: function() {
  22599. return this._frameName;
  22600. },
  22601. set: function(value) {
  22602. if (value !== this.frameName && this.game.cache.isSpriteSheet(this.key))
  22603. {
  22604. var frameData = this.game.cache.getFrameData(this.key);
  22605. if (frameData && frameData.getFrameByName(value))
  22606. {
  22607. this.setTexture(PIXI.TextureCache[frameData.getFrameByName(value).uuid]);
  22608. this._frameName = value;
  22609. }
  22610. }
  22611. }
  22612. });
  22613. /**
  22614. * @name Phaser.Image#renderOrderID
  22615. * @property {number} renderOrderID - The render order ID, reset every frame.
  22616. * @readonly
  22617. */
  22618. Object.defineProperty(Phaser.Image.prototype, "renderOrderID", {
  22619. get: function() {
  22620. return this._cache[3];
  22621. }
  22622. });
  22623. /**
  22624. * By default an Image won't process any input events at all. By setting inputEnabled to true the Phaser.InputHandler is
  22625. * activated for this object and it will then start to process click/touch events and more.
  22626. *
  22627. * @name Phaser.Image#inputEnabled
  22628. * @property {boolean} inputEnabled - Set to true to allow this object to receive input events.
  22629. */
  22630. Object.defineProperty(Phaser.Image.prototype, "inputEnabled", {
  22631. get: function () {
  22632. return (this.input && this.input.enabled);
  22633. },
  22634. set: function (value) {
  22635. if (value)
  22636. {
  22637. if (this.input === null)
  22638. {
  22639. this.input = new Phaser.InputHandler(this);
  22640. this.input.start();
  22641. }
  22642. else if (this.input && !this.input.enabled)
  22643. {
  22644. this.input.start();
  22645. }
  22646. }
  22647. else
  22648. {
  22649. if (this.input && this.input.enabled)
  22650. {
  22651. this.input.stop();
  22652. }
  22653. }
  22654. }
  22655. });
  22656. /**
  22657. * An Image that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in Image.cameraOffset.
  22658. * Note that the cameraOffset values are in addition to any parent in the display list.
  22659. * So if this Image was in a Group that has x: 200, then this will be added to the cameraOffset.x
  22660. *
  22661. * @name Phaser.Image#fixedToCamera
  22662. * @property {boolean} fixedToCamera - Set to true to fix this Image to the Camera at its current world coordinates.
  22663. */
  22664. Object.defineProperty(Phaser.Image.prototype, "fixedToCamera", {
  22665. get: function () {
  22666. return !!this._cache[7];
  22667. },
  22668. set: function (value) {
  22669. if (value)
  22670. {
  22671. this._cache[7] = 1;
  22672. this.cameraOffset.set(this.x, this.y);
  22673. }
  22674. else
  22675. {
  22676. this._cache[7] = 0;
  22677. }
  22678. }
  22679. });
  22680. /**
  22681. * Enable or disable texture smoothing for this Image. Only works for bitmap/image textures. Smoothing is enabled by default.
  22682. *
  22683. * @name Phaser.Image#smoothed
  22684. * @property {boolean} smoothed - Set to true to smooth the texture of this Image, or false to disable smoothing (great for pixel art)
  22685. */
  22686. Object.defineProperty(Phaser.Image.prototype, "smoothed", {
  22687. get: function () {
  22688. return !this.texture.baseTexture.scaleMode;
  22689. },
  22690. set: function (value) {
  22691. if (value)
  22692. {
  22693. if (this.texture)
  22694. {
  22695. this.texture.baseTexture.scaleMode = 0;
  22696. }
  22697. }
  22698. else
  22699. {
  22700. if (this.texture)
  22701. {
  22702. this.texture.baseTexture.scaleMode = 1;
  22703. }
  22704. }
  22705. }
  22706. });
  22707. /**
  22708. * @author Richard Davey <rich@photonstorm.com>
  22709. * @copyright 2014 Photon Storm Ltd.
  22710. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  22711. */
  22712. /**
  22713. * A TileSprite is a Sprite that has a repeating texture. The texture can be scrolled and scaled and will automatically wrap on the edges as it does so.
  22714. * Please note that TileSprites, as with normal Sprites, have no input handler or physics bodies by default. Both need enabling.
  22715. *
  22716. * @class Phaser.TileSprite
  22717. * @constructor
  22718. * @param {Phaser.Game} game - A reference to the currently running game.
  22719. * @param {number} x - The x coordinate (in world space) to position the TileSprite at.
  22720. * @param {number} y - The y coordinate (in world space) to position the TileSprite at.
  22721. * @param {number} width - The width of the TileSprite.
  22722. * @param {number} height - The height of the TileSprite.
  22723. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the TileSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  22724. * @param {string|number} frame - If this TileSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  22725. */
  22726. Phaser.TileSprite = function (game, x, y, width, height, key, frame) {
  22727. x = x || 0;
  22728. y = y || 0;
  22729. width = width || 256;
  22730. height = height || 256;
  22731. key = key || null;
  22732. frame = frame || null;
  22733. /**
  22734. * @property {Phaser.Game} game - A reference to the currently running Game.
  22735. */
  22736. this.game = game;
  22737. /**
  22738. * @property {string} name - The user defined name given to this Sprite.
  22739. * @default
  22740. */
  22741. this.name = '';
  22742. /**
  22743. * @property {number} type - The const type of this object.
  22744. * @readonly
  22745. */
  22746. this.type = Phaser.TILESPRITE;
  22747. /**
  22748. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  22749. */
  22750. this.z = 0;
  22751. /**
  22752. * @property {Phaser.Events} events - The Events you can subscribe to that are dispatched when certain things happen on this Sprite or its components.
  22753. */
  22754. this.events = new Phaser.Events(this);
  22755. /**
  22756. * @property {Phaser.AnimationManager} animations - This manages animations of the sprite. You can modify animations through it (see Phaser.AnimationManager)
  22757. */
  22758. this.animations = new Phaser.AnimationManager(this);
  22759. /**
  22760. * @property {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  22761. */
  22762. this.key = key;
  22763. /**
  22764. * @property {number} _frame - Internal cache var.
  22765. * @private
  22766. */
  22767. this._frame = 0;
  22768. /**
  22769. * @property {string} _frameName - Internal cache var.
  22770. * @private
  22771. */
  22772. this._frameName = '';
  22773. /**
  22774. * @property {Phaser.Point} _scroll - Internal cache var.
  22775. * @private
  22776. */
  22777. this._scroll = new Phaser.Point();
  22778. PIXI.TilingSprite.call(this, PIXI.TextureCache['__default'], width, height);
  22779. this.loadTexture(key, frame);
  22780. this.position.set(x, y);
  22781. /**
  22782. * @property {Phaser.InputHandler|null} input - The Input Handler for this object. Needs to be enabled with image.inputEnabled = true before you can use it.
  22783. */
  22784. this.input = null;
  22785. /**
  22786. * @property {Phaser.Point} world - The world coordinates of this Sprite. This differs from the x/y coordinates which are relative to the Sprites container.
  22787. */
  22788. this.world = new Phaser.Point(x, y);
  22789. /**
  22790. * Should this Sprite be automatically culled if out of range of the camera?
  22791. * A culled sprite has its renderable property set to 'false'.
  22792. * Be advised this is quite an expensive operation, as it has to calculate the bounds of the object every frame, so only enable it if you really need it.
  22793. *
  22794. * @property {boolean} autoCull - A flag indicating if the Sprite should be automatically camera culled or not.
  22795. * @default
  22796. */
  22797. this.autoCull = false;
  22798. /**
  22799. * If true the Sprite checks if it is still within the world each frame, when it leaves the world it dispatches Sprite.events.onOutOfBounds
  22800. * and optionally kills the sprite (if Sprite.outOfBoundsKill is true). By default this is disabled because the Sprite has to calculate its
  22801. * bounds every frame to support it, and not all games need it. Enable it by setting the value to true.
  22802. * @property {boolean} checkWorldBounds
  22803. * @default
  22804. */
  22805. this.checkWorldBounds = false;
  22806. /**
  22807. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  22808. */
  22809. this.cameraOffset = new Phaser.Point();
  22810. /**
  22811. * By default Sprites won't add themselves to any physics system and their physics body will be `null`.
  22812. * To enable them for physics you need to call `game.physics.enable(sprite, system)` where `sprite` is this object
  22813. * and `system` is the Physics system you want to use to manage this body. Once enabled you can access all physics related properties via `Sprite.body`.
  22814. *
  22815. * Important: Enabling a Sprite for P2 or Ninja physics will automatically set `Sprite.anchor` to 0.5 so the physics body is centered on the Sprite.
  22816. * If you need a different result then adjust or re-create the Body shape offsets manually, and/or reset the anchor after enabling physics.
  22817. *
  22818. * @property {Phaser.Physics.Arcade.Body|Phaser.Physics.P2.Body|Phaser.Physics.Ninja.Body|null} body
  22819. * @default
  22820. */
  22821. this.body = null;
  22822. /**
  22823. * A small internal cache:
  22824. * 0 = previous position.x
  22825. * 1 = previous position.y
  22826. * 2 = previous rotation
  22827. * 3 = renderID
  22828. * 4 = fresh? (0 = no, 1 = yes)
  22829. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  22830. * 6 = exists (0 = no, 1 = yes)
  22831. * 7 = fixed to camera (0 = no, 1 = yes)
  22832. * @property {Array} _cache
  22833. * @private
  22834. */
  22835. this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0 ];
  22836. };
  22837. Phaser.TileSprite.prototype = Object.create(PIXI.TilingSprite.prototype);
  22838. Phaser.TileSprite.prototype.constructor = Phaser.TileSprite;
  22839. /**
  22840. * Automatically called by World.preUpdate.
  22841. *
  22842. * @method Phaser.TileSprite#preUpdate
  22843. * @memberof Phaser.TileSprite
  22844. */
  22845. Phaser.TileSprite.prototype.preUpdate = function() {
  22846. if (this._cache[4] === 1 && this.exists)
  22847. {
  22848. this.world.setTo(this.parent.position.x + this.position.x, this.parent.position.y + this.position.y);
  22849. this.worldTransform.tx = this.world.x;
  22850. this.worldTransform.ty = this.world.y;
  22851. this._cache[0] = this.world.x;
  22852. this._cache[1] = this.world.y;
  22853. this._cache[2] = this.rotation;
  22854. if (this.body)
  22855. {
  22856. this.body.preUpdate();
  22857. }
  22858. this._cache[4] = 0;
  22859. return false;
  22860. }
  22861. this._cache[0] = this.world.x;
  22862. this._cache[1] = this.world.y;
  22863. this._cache[2] = this.rotation;
  22864. if (!this.exists || !this.parent.exists)
  22865. {
  22866. // Reset the renderOrderID
  22867. this._cache[3] = -1;
  22868. return false;
  22869. }
  22870. // Cache the bounds if we need it
  22871. if (this.autoCull || this.checkWorldBounds)
  22872. {
  22873. this._bounds.copyFrom(this.getBounds());
  22874. }
  22875. if (this.autoCull)
  22876. {
  22877. // Won't get rendered but will still get its transform updated
  22878. this.renderable = this.game.world.camera.screenView.intersects(this._bounds);
  22879. }
  22880. if (this.checkWorldBounds)
  22881. {
  22882. // The Sprite is already out of the world bounds, so let's check to see if it has come back again
  22883. if (this._cache[5] === 1 && this.game.world.bounds.intersects(this._bounds))
  22884. {
  22885. this._cache[5] = 0;
  22886. this.events.onEnterBounds.dispatch(this);
  22887. }
  22888. else if (this._cache[5] === 0 && !this.game.world.bounds.intersects(this._bounds))
  22889. {
  22890. // The Sprite WAS in the screen, but has now left.
  22891. this._cache[5] = 1;
  22892. this.events.onOutOfBounds.dispatch(this);
  22893. }
  22894. }
  22895. this.world.setTo(this.game.camera.x + this.worldTransform.tx, this.game.camera.y + this.worldTransform.ty);
  22896. if (this.visible)
  22897. {
  22898. this._cache[3] = this.game.stage.currentRenderOrderID++;
  22899. }
  22900. this.animations.update();
  22901. if (this._scroll.x !== 0)
  22902. {
  22903. this.tilePosition.x += this._scroll.x * this.game.time.physicsElapsed;
  22904. }
  22905. if (this._scroll.y !== 0)
  22906. {
  22907. this.tilePosition.y += this._scroll.y * this.game.time.physicsElapsed;
  22908. }
  22909. if (this.body)
  22910. {
  22911. this.body.preUpdate();
  22912. }
  22913. // Update any Children
  22914. for (var i = 0, len = this.children.length; i < len; i++)
  22915. {
  22916. this.children[i].preUpdate();
  22917. }
  22918. return true;
  22919. };
  22920. /**
  22921. * Override and use this function in your own custom objects to handle any update requirements you may have.
  22922. *
  22923. * @method Phaser.TileSprite#update
  22924. * @memberof Phaser.TileSprite
  22925. */
  22926. Phaser.TileSprite.prototype.update = function() {
  22927. };
  22928. /**
  22929. * Internal function called by the World postUpdate cycle.
  22930. *
  22931. * @method Phaser.TileSprite#postUpdate
  22932. * @memberof Phaser.TileSprite
  22933. */
  22934. Phaser.TileSprite.prototype.postUpdate = function() {
  22935. if (this.exists && this.body)
  22936. {
  22937. this.body.postUpdate();
  22938. }
  22939. // Fixed to Camera?
  22940. if (this._cache[7] === 1)
  22941. {
  22942. this.position.x = this.game.camera.view.x + this.cameraOffset.x;
  22943. this.position.y = this.game.camera.view.y + this.cameraOffset.y;
  22944. }
  22945. // Update any Children
  22946. for (var i = 0, len = this.children.length; i < len; i++)
  22947. {
  22948. this.children[i].postUpdate();
  22949. }
  22950. };
  22951. /**
  22952. * Sets this TileSprite to automatically scroll in the given direction until stopped via TileSprite.stopScroll().
  22953. * The scroll speed is specified in pixels per second.
  22954. * A negative x value will scroll to the left. A positive x value will scroll to the right.
  22955. * A negative y value will scroll up. A positive y value will scroll down.
  22956. *
  22957. * @method Phaser.TileSprite#autoScroll
  22958. * @memberof Phaser.TileSprite
  22959. */
  22960. Phaser.TileSprite.prototype.autoScroll = function(x, y) {
  22961. this._scroll.set(x, y);
  22962. };
  22963. /**
  22964. * Stops an automatically scrolling TileSprite.
  22965. *
  22966. * @method Phaser.TileSprite#stopScroll
  22967. * @memberof Phaser.TileSprite
  22968. */
  22969. Phaser.TileSprite.prototype.stopScroll = function() {
  22970. this._scroll.set(0, 0);
  22971. };
  22972. /**
  22973. * Changes the Texture the TileSprite is using entirely. The old texture is removed and the new one is referenced or fetched from the Cache.
  22974. * This causes a WebGL texture update, so use sparingly or in low-intensity portions of your game.
  22975. *
  22976. * @method Phaser.TileSprite#loadTexture
  22977. * @memberof Phaser.TileSprite
  22978. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture, BitmapData or PIXI.Texture.
  22979. * @param {string|number} frame - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  22980. */
  22981. Phaser.TileSprite.prototype.loadTexture = function (key, frame) {
  22982. frame = frame || 0;
  22983. if (key instanceof Phaser.RenderTexture)
  22984. {
  22985. this.key = key.key;
  22986. this.setTexture(key);
  22987. return;
  22988. }
  22989. else if (key instanceof Phaser.BitmapData)
  22990. {
  22991. this.key = key;
  22992. this.setTexture(key.texture);
  22993. return;
  22994. }
  22995. else if (key instanceof PIXI.Texture)
  22996. {
  22997. this.key = key;
  22998. this.setTexture(key);
  22999. return;
  23000. }
  23001. else
  23002. {
  23003. if (key === null || typeof key === 'undefined')
  23004. {
  23005. this.key = '__default';
  23006. this.setTexture(PIXI.TextureCache[this.key]);
  23007. return;
  23008. }
  23009. else if (typeof key === 'string' && !this.game.cache.checkImageKey(key))
  23010. {
  23011. this.key = '__missing';
  23012. this.setTexture(PIXI.TextureCache[this.key]);
  23013. return;
  23014. }
  23015. if (this.game.cache.isSpriteSheet(key))
  23016. {
  23017. this.key = key;
  23018. // var frameData = this.game.cache.getFrameData(key);
  23019. this.animations.loadFrameData(this.game.cache.getFrameData(key));
  23020. if (typeof frame === 'string')
  23021. {
  23022. this.frameName = frame;
  23023. }
  23024. else
  23025. {
  23026. this.frame = frame;
  23027. }
  23028. }
  23029. else
  23030. {
  23031. this.key = key;
  23032. this.setTexture(PIXI.TextureCache[key]);
  23033. return;
  23034. }
  23035. }
  23036. };
  23037. /**
  23038. * Destroys the TileSprite. This removes it from its parent group, destroys the event and animation handlers if present
  23039. * and nulls its reference to game, freeing it up for garbage collection.
  23040. *
  23041. * @method Phaser.TileSprite#destroy
  23042. * @memberof Phaser.TileSprite
  23043. * @param {boolean} [destroyChildren=true] - Should every child of this object have its destroy method called?
  23044. */
  23045. Phaser.TileSprite.prototype.destroy = function(destroyChildren) {
  23046. if (this.game === null) { return; }
  23047. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  23048. if (this.filters)
  23049. {
  23050. this.filters = null;
  23051. }
  23052. if (this.parent)
  23053. {
  23054. if (this.parent instanceof Phaser.Group)
  23055. {
  23056. this.parent.remove(this);
  23057. }
  23058. else
  23059. {
  23060. this.parent.removeChild(this);
  23061. }
  23062. }
  23063. this.animations.destroy();
  23064. this.events.destroy();
  23065. var i = this.children.length;
  23066. if (destroyChildren)
  23067. {
  23068. while (i--)
  23069. {
  23070. this.children[i].destroy(destroyChildren);
  23071. }
  23072. }
  23073. else
  23074. {
  23075. while (i--)
  23076. {
  23077. this.removeChild(this.children[i]);
  23078. }
  23079. }
  23080. this.exists = false;
  23081. this.visible = false;
  23082. this.filters = null;
  23083. this.mask = null;
  23084. this.game = null;
  23085. };
  23086. /**
  23087. * Play an animation based on the given key. The animation should previously have been added via sprite.animations.add()
  23088. * If the requested animation is already playing this request will be ignored. If you need to reset an already running animation do so directly on the Animation object itself.
  23089. *
  23090. * @method Phaser.TileSprite#play
  23091. * @memberof Phaser.TileSprite
  23092. * @param {string} name - The name of the animation to be played, e.g. "fire", "walk", "jump".
  23093. * @param {number} [frameRate=null] - The framerate to play the animation at. The speed is given in frames per second. If not provided the previously set frameRate of the Animation is used.
  23094. * @param {boolean} [loop=false] - Should the animation be looped after playback. If not provided the previously set loop value of the Animation is used.
  23095. * @param {boolean} [killOnComplete=false] - If set to true when the animation completes (only happens if loop=false) the parent Sprite will be killed.
  23096. * @return {Phaser.Animation} A reference to playing Animation instance.
  23097. */
  23098. Phaser.TileSprite.prototype.play = function (name, frameRate, loop, killOnComplete) {
  23099. return this.animations.play(name, frameRate, loop, killOnComplete);
  23100. };
  23101. /**
  23102. * Resets the TileSprite. This places the TileSprite at the given x/y world coordinates, resets the tilePosition and then
  23103. * sets alive, exists, visible and renderable all to true. Also resets the outOfBounds state.
  23104. * If the TileSprite has a physics body that too is reset.
  23105. *
  23106. * @method Phaser.TileSprite#reset
  23107. * @memberof Phaser.TileSprite
  23108. * @param {number} x - The x coordinate (in world space) to position the Sprite at.
  23109. * @param {number} y - The y coordinate (in world space) to position the Sprite at.
  23110. * @return (Phaser.TileSprite) This instance.
  23111. */
  23112. Phaser.TileSprite.prototype.reset = function(x, y) {
  23113. this.world.setTo(x, y);
  23114. this.position.x = x;
  23115. this.position.y = y;
  23116. this.alive = true;
  23117. this.exists = true;
  23118. this.visible = true;
  23119. this.renderable = true;
  23120. this._outOfBoundsFired = false;
  23121. this.tilePosition.x = 0;
  23122. this.tilePosition.y = 0;
  23123. if (this.body)
  23124. {
  23125. this.body.reset(x, y, false, false);
  23126. }
  23127. this._cache[4] = 1;
  23128. return this;
  23129. };
  23130. /**
  23131. * Indicates the rotation of the Sprite, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation.
  23132. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90.
  23133. * If you wish to work in radians instead of degrees use the property Sprite.rotation instead. Working in radians is also a little faster as it doesn't have to convert the angle.
  23134. *
  23135. * @name Phaser.TileSprite#angle
  23136. * @property {number} angle - The angle of this Sprite in degrees.
  23137. */
  23138. Object.defineProperty(Phaser.TileSprite.prototype, "angle", {
  23139. get: function() {
  23140. return Phaser.Math.wrapAngle(Phaser.Math.radToDeg(this.rotation));
  23141. },
  23142. set: function(value) {
  23143. this.rotation = Phaser.Math.degToRad(Phaser.Math.wrapAngle(value));
  23144. }
  23145. });
  23146. /**
  23147. * @name Phaser.TileSprite#frame
  23148. * @property {number} frame - Gets or sets the current frame index and updates the Texture Cache for display.
  23149. */
  23150. Object.defineProperty(Phaser.TileSprite.prototype, "frame", {
  23151. get: function () {
  23152. return this.animations.frame;
  23153. },
  23154. set: function (value) {
  23155. if (value !== this.animations.frame)
  23156. {
  23157. this.animations.frame = value;
  23158. }
  23159. }
  23160. });
  23161. /**
  23162. * @name Phaser.TileSprite#frameName
  23163. * @property {string} frameName - Gets or sets the current frame name and updates the Texture Cache for display.
  23164. */
  23165. Object.defineProperty(Phaser.TileSprite.prototype, "frameName", {
  23166. get: function () {
  23167. return this.animations.frameName;
  23168. },
  23169. set: function (value) {
  23170. if (value !== this.animations.frameName)
  23171. {
  23172. this.animations.frameName = value;
  23173. }
  23174. }
  23175. });
  23176. /**
  23177. * An TileSprite that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in TileSprite.cameraOffset.
  23178. * Note that the cameraOffset values are in addition to any parent in the display list.
  23179. * So if this TileSprite was in a Group that has x: 200, then this will be added to the cameraOffset.x
  23180. *
  23181. * @name Phaser.TileSprite#fixedToCamera
  23182. * @property {boolean} fixedToCamera - Set to true to fix this TileSprite to the Camera at its current world coordinates.
  23183. */
  23184. Object.defineProperty(Phaser.TileSprite.prototype, "fixedToCamera", {
  23185. get: function () {
  23186. return !!this._cache[7];
  23187. },
  23188. set: function (value) {
  23189. if (value)
  23190. {
  23191. this._cache[7] = 1;
  23192. this.cameraOffset.set(this.x, this.y);
  23193. }
  23194. else
  23195. {
  23196. this._cache[7] = 0;
  23197. }
  23198. }
  23199. });
  23200. /**
  23201. * TileSprite.exists controls if the core game loop and physics update this TileSprite or not.
  23202. * When you set TileSprite.exists to false it will remove its Body from the physics world (if it has one) and also set TileSprite.visible to false.
  23203. * Setting TileSprite.exists to true will re-add the Body to the physics world (if it has a body) and set TileSprite.visible to true.
  23204. *
  23205. * @name Phaser.TileSprite#exists
  23206. * @property {boolean} exists - If the TileSprite is processed by the core game update and physics.
  23207. */
  23208. Object.defineProperty(Phaser.TileSprite.prototype, "exists", {
  23209. get: function () {
  23210. return !!this._cache[6];
  23211. },
  23212. set: function (value) {
  23213. if (value)
  23214. {
  23215. // exists = true
  23216. this._cache[6] = 1;
  23217. if (this.body && this.body.type === Phaser.Physics.P2JS)
  23218. {
  23219. this.body.addToWorld();
  23220. }
  23221. this.visible = true;
  23222. }
  23223. else
  23224. {
  23225. // exists = false
  23226. this._cache[6] = 0;
  23227. if (this.body && this.body.type === Phaser.Physics.P2JS)
  23228. {
  23229. this.body.safeRemove = true;
  23230. }
  23231. this.visible = false;
  23232. }
  23233. }
  23234. });
  23235. /**
  23236. * By default a TileSprite won't process any input events at all. By setting inputEnabled to true the Phaser.InputHandler is
  23237. * activated for this object and it will then start to process click/touch events and more.
  23238. *
  23239. * @name Phaser.TileSprite#inputEnabled
  23240. * @property {boolean} inputEnabled - Set to true to allow this object to receive input events.
  23241. */
  23242. Object.defineProperty(Phaser.TileSprite.prototype, "inputEnabled", {
  23243. get: function () {
  23244. return (this.input && this.input.enabled);
  23245. },
  23246. set: function (value) {
  23247. if (value)
  23248. {
  23249. if (this.input === null)
  23250. {
  23251. this.input = new Phaser.InputHandler(this);
  23252. this.input.start();
  23253. }
  23254. else if (this.input && !this.input.enabled)
  23255. {
  23256. this.input.start();
  23257. }
  23258. }
  23259. else
  23260. {
  23261. if (this.input && this.input.enabled)
  23262. {
  23263. this.input.stop();
  23264. }
  23265. }
  23266. }
  23267. });
  23268. /**
  23269. * The position of the TileSprite on the x axis relative to the local coordinates of the parent.
  23270. *
  23271. * @name Phaser.TileSprite#x
  23272. * @property {number} x - The position of the TileSprite on the x axis relative to the local coordinates of the parent.
  23273. */
  23274. Object.defineProperty(Phaser.TileSprite.prototype, "x", {
  23275. get: function () {
  23276. return this.position.x;
  23277. },
  23278. set: function (value) {
  23279. this.position.x = value;
  23280. if (this.body && this.body.type === Phaser.Physics.ARCADE && this.body.phase === 2)
  23281. {
  23282. this.body._reset = 1;
  23283. }
  23284. }
  23285. });
  23286. /**
  23287. * The position of the TileSprite on the y axis relative to the local coordinates of the parent.
  23288. *
  23289. * @name Phaser.TileSprite#y
  23290. * @property {number} y - The position of the TileSprite on the y axis relative to the local coordinates of the parent.
  23291. */
  23292. Object.defineProperty(Phaser.TileSprite.prototype, "y", {
  23293. get: function () {
  23294. return this.position.y;
  23295. },
  23296. set: function (value) {
  23297. this.position.y = value;
  23298. if (this.body && this.body.type === Phaser.Physics.ARCADE && this.body.phase === 2)
  23299. {
  23300. this.body._reset = 1;
  23301. }
  23302. }
  23303. });
  23304. /**
  23305. * @author Richard Davey <rich@photonstorm.com>
  23306. * @copyright 2014 Photon Storm Ltd.
  23307. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  23308. */
  23309. /**
  23310. * Create a new `Text` object. This uses a local hidden Canvas object and renders the type into it. It then makes a texture from this for renderning to the view.
  23311. * Because of this you can only display fonts that are currently loaded and available to the browser. It won't load the fonts for you.
  23312. * Here is a compatibility table showing the available default fonts across different mobile browsers: http://www.jordanm.co.uk/tinytype
  23313. *
  23314. * @class Phaser.Text
  23315. * @extends PIXI.Text
  23316. * @constructor
  23317. * @param {Phaser.Game} game - Current game instance.
  23318. * @param {number} x - X position of the new text object.
  23319. * @param {number} y - Y position of the new text object.
  23320. * @param {string} text - The actual text that will be written.
  23321. * @param {object} style - The style object containing style attributes like font, font size ,
  23322. */
  23323. Phaser.Text = function (game, x, y, text, style) {
  23324. x = x || 0;
  23325. y = y || 0;
  23326. text = text || ' ';
  23327. style = style || {};
  23328. if (text.length === 0)
  23329. {
  23330. text = ' ';
  23331. }
  23332. else
  23333. {
  23334. text = text.toString();
  23335. }
  23336. /**
  23337. * @property {Phaser.Game} game - A reference to the currently running Game.
  23338. */
  23339. this.game = game;
  23340. /**
  23341. * @property {boolean} exists - If exists = false then the Text isn't updated by the core game loop.
  23342. * @default
  23343. */
  23344. this.exists = true;
  23345. /**
  23346. * @property {string} name - The user defined name given to this object.
  23347. * @default
  23348. */
  23349. this.name = '';
  23350. /**
  23351. * @property {number} type - The const type of this object.
  23352. * @default
  23353. */
  23354. this.type = Phaser.TEXT;
  23355. /**
  23356. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  23357. */
  23358. this.z = 0;
  23359. /**
  23360. * @property {Phaser.Point} world - The world coordinates of this Sprite. This differs from the x/y coordinates which are relative to the Sprites container.
  23361. */
  23362. this.world = new Phaser.Point(x, y);
  23363. /**
  23364. * @property {string} _text - Internal cache var.
  23365. * @private
  23366. */
  23367. this._text = text;
  23368. /**
  23369. * @property {string} _font - Internal cache var.
  23370. * @private
  23371. */
  23372. this._font = '';
  23373. /**
  23374. * @property {number} _fontSize - Internal cache var.
  23375. * @private
  23376. */
  23377. this._fontSize = 32;
  23378. /**
  23379. * @property {string} _fontWeight - Internal cache var.
  23380. * @private
  23381. */
  23382. this._fontWeight = 'normal';
  23383. /**
  23384. * @property {number} lineSpacing - Additional spacing (in pixels) between each line of text if multi-line.
  23385. * @private
  23386. */
  23387. this._lineSpacing = 0;
  23388. /**
  23389. * @property {Phaser.Events} events - The Events you can subscribe to that are dispatched when certain things happen on this Sprite or its components.
  23390. */
  23391. this.events = new Phaser.Events(this);
  23392. /**
  23393. * @property {Phaser.InputHandler|null} input - The Input Handler for this object. Needs to be enabled with image.inputEnabled = true before you can use it.
  23394. */
  23395. this.input = null;
  23396. /**
  23397. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  23398. */
  23399. this.cameraOffset = new Phaser.Point();
  23400. this.setStyle(style);
  23401. PIXI.Text.call(this, text, this.style);
  23402. this.position.set(x, y);
  23403. /**
  23404. * A small internal cache:
  23405. * 0 = previous position.x
  23406. * 1 = previous position.y
  23407. * 2 = previous rotation
  23408. * 3 = renderID
  23409. * 4 = fresh? (0 = no, 1 = yes)
  23410. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  23411. * 6 = exists (0 = no, 1 = yes)
  23412. * 7 = fixed to camera (0 = no, 1 = yes)
  23413. * @property {Array} _cache
  23414. * @private
  23415. */
  23416. this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0 ];
  23417. };
  23418. Phaser.Text.prototype = Object.create(PIXI.Text.prototype);
  23419. Phaser.Text.prototype.constructor = Phaser.Text;
  23420. /**
  23421. * Automatically called by World.preUpdate.
  23422. * @method Phaser.Text.prototype.preUpdate
  23423. */
  23424. Phaser.Text.prototype.preUpdate = function () {
  23425. this._cache[0] = this.world.x;
  23426. this._cache[1] = this.world.y;
  23427. this._cache[2] = this.rotation;
  23428. if (!this.exists || !this.parent.exists)
  23429. {
  23430. this.renderOrderID = -1;
  23431. return false;
  23432. }
  23433. if (this.autoCull)
  23434. {
  23435. // Won't get rendered but will still get its transform updated
  23436. this.renderable = this.game.world.camera.screenView.intersects(this.getBounds());
  23437. }
  23438. this.world.setTo(this.game.camera.x + this.worldTransform[2], this.game.camera.y + this.worldTransform[5]);
  23439. if (this.visible)
  23440. {
  23441. this._cache[3] = this.game.stage.currentRenderOrderID++;
  23442. }
  23443. // Update any Children
  23444. for (var i = 0, len = this.children.length; i < len; i++)
  23445. {
  23446. this.children[i].preUpdate();
  23447. }
  23448. return true;
  23449. };
  23450. /**
  23451. * Override and use this function in your own custom objects to handle any update requirements you may have.
  23452. *
  23453. * @method Phaser.Text#update
  23454. * @memberof Phaser.Text
  23455. */
  23456. Phaser.Text.prototype.update = function() {
  23457. };
  23458. /**
  23459. * Automatically called by World.postUpdate.
  23460. * @method Phaser.Text.prototype.postUpdate
  23461. */
  23462. Phaser.Text.prototype.postUpdate = function () {
  23463. if (this._cache[7] === 1)
  23464. {
  23465. this.position.x = (this.game.camera.view.x + this.cameraOffset.x) / this.game.camera.scale.x;
  23466. this.position.y = (this.game.camera.view.y + this.cameraOffset.y) / this.game.camera.scale.y;
  23467. }
  23468. // Update any Children
  23469. for (var i = 0, len = this.children.length; i < len; i++)
  23470. {
  23471. this.children[i].postUpdate();
  23472. }
  23473. };
  23474. /**
  23475. * @method Phaser.Text.prototype.destroy
  23476. * @param {boolean} [destroyChildren=true] - Should every child of this object have its destroy method called?
  23477. */
  23478. Phaser.Text.prototype.destroy = function (destroyChildren) {
  23479. if (this.game === null) { return; }
  23480. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  23481. if (this.parent)
  23482. {
  23483. if (this.parent instanceof Phaser.Group)
  23484. {
  23485. this.parent.remove(this);
  23486. }
  23487. else
  23488. {
  23489. this.parent.removeChild(this);
  23490. }
  23491. }
  23492. this.texture.destroy();
  23493. if (this.canvas.parentNode)
  23494. {
  23495. this.canvas.parentNode.removeChild(this.canvas);
  23496. }
  23497. else
  23498. {
  23499. this.canvas = null;
  23500. this.context = null;
  23501. }
  23502. var i = this.children.length;
  23503. if (destroyChildren)
  23504. {
  23505. while (i--)
  23506. {
  23507. this.children[i].destroy(destroyChildren);
  23508. }
  23509. }
  23510. else
  23511. {
  23512. while (i--)
  23513. {
  23514. this.removeChild(this.children[i]);
  23515. }
  23516. }
  23517. this.exists = false;
  23518. this.visible = false;
  23519. this.filters = null;
  23520. this.mask = null;
  23521. this.game = null;
  23522. };
  23523. /**
  23524. * @method Phaser.Text.prototype.setShadow
  23525. * @param {number} [x=0] - The shadowOffsetX value in pixels. This is how far offset horizontally the shadow effect will be.
  23526. * @param {number} [y=0] - The shadowOffsetY value in pixels. This is how far offset vertically the shadow effect will be.
  23527. * @param {string} [color='rgba(0,0,0,0)'] - The color of the shadow, as given in CSS rgba format. Set the alpha component to 0 to disable the shadow.
  23528. * @param {number} [blur=0] - The shadowBlur value. Make the shadow softer by applying a Gaussian blur to it. A number from 0 (no blur) up to approx. 10 (depending on scene).
  23529. */
  23530. Phaser.Text.prototype.setShadow = function (x, y, color, blur) {
  23531. this.style.shadowOffsetX = x || 0;
  23532. this.style.shadowOffsetY = y || 0;
  23533. this.style.shadowColor = color || 'rgba(0,0,0,0)';
  23534. this.style.shadowBlur = blur || 0;
  23535. this.dirty = true;
  23536. };
  23537. /**
  23538. * Set the style of the text by passing a single style object to it.
  23539. *
  23540. * @method Phaser.Text.prototype.setStyle
  23541. * @param [style] {Object} The style parameters
  23542. * @param [style.font='bold 20pt Arial'] {String} The style and size of the font
  23543. * @param [style.fill='black'] {Object} A canvas fillstyle that will be used on the text eg 'red', '#00FF00'
  23544. * @param [style.align='left'] {String} Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text
  23545. * @param [style.stroke='black'] {String} A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'
  23546. * @param [style.strokeThickness=0] {Number} A number that represents the thickness of the stroke. Default is 0 (no stroke)
  23547. * @param [style.wordWrap=false] {Boolean} Indicates if word wrap should be used
  23548. * @param [style.wordWrapWidth=100] {Number} The width at which text will wrap
  23549. */
  23550. Phaser.Text.prototype.setStyle = function (style) {
  23551. style = style || {};
  23552. style.font = style.font || 'bold 20pt Arial';
  23553. style.fill = style.fill || 'black';
  23554. style.align = style.align || 'left';
  23555. style.stroke = style.stroke || 'black'; //provide a default, see: https://github.com/GoodBoyDigital/pixi.js/issues/136
  23556. style.strokeThickness = style.strokeThickness || 0;
  23557. style.wordWrap = style.wordWrap || false;
  23558. style.wordWrapWidth = style.wordWrapWidth || 100;
  23559. style.shadowOffsetX = style.shadowOffsetX || 0;
  23560. style.shadowOffsetY = style.shadowOffsetY || 0;
  23561. style.shadowColor = style.shadowColor || 'rgba(0,0,0,0)';
  23562. style.shadowBlur = style.shadowBlur || 0;
  23563. this.style = style;
  23564. this.dirty = true;
  23565. };
  23566. /**
  23567. * Renders text. This replaces the Pixi.Text.updateText function as we need a few extra bits in here.
  23568. *
  23569. * @method Phaser.Text.prototype.updateText
  23570. * @private
  23571. */
  23572. Phaser.Text.prototype.updateText = function () {
  23573. this.context.font = this.style.font;
  23574. var outputText = this.text;
  23575. // word wrap
  23576. // preserve original text
  23577. if (this.style.wordWrap)
  23578. {
  23579. outputText = this.runWordWrap(this.text);
  23580. }
  23581. //split text into lines
  23582. var lines = outputText.split(/(?:\r\n|\r|\n)/);
  23583. //calculate text width
  23584. var lineWidths = [];
  23585. var maxLineWidth = 0;
  23586. for (var i = 0; i < lines.length; i++)
  23587. {
  23588. var lineWidth = this.context.measureText(lines[i]).width;
  23589. lineWidths[i] = lineWidth;
  23590. maxLineWidth = Math.max(maxLineWidth, lineWidth);
  23591. }
  23592. this.canvas.width = maxLineWidth + this.style.strokeThickness;
  23593. //calculate text height
  23594. var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness + this._lineSpacing + this.style.shadowOffsetY;
  23595. this.canvas.height = lineHeight * lines.length;
  23596. if (navigator.isCocoonJS)
  23597. {
  23598. this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  23599. }
  23600. //set canvas text styles
  23601. this.context.fillStyle = this.style.fill;
  23602. this.context.font = this.style.font;
  23603. this.context.strokeStyle = this.style.stroke;
  23604. this.context.lineWidth = this.style.strokeThickness;
  23605. this.context.shadowOffsetX = this.style.shadowOffsetX;
  23606. this.context.shadowOffsetY = this.style.shadowOffsetY;
  23607. this.context.shadowColor = this.style.shadowColor;
  23608. this.context.shadowBlur = this.style.shadowBlur;
  23609. this.context.textBaseline = 'top';
  23610. this.context.lineJoin = 'round';
  23611. //draw lines line by line
  23612. for (i = 0; i < lines.length; i++)
  23613. {
  23614. var linePosition = new PIXI.Point(this.style.strokeThickness / 2, this.style.strokeThickness / 2 + i * lineHeight);
  23615. if (this.style.align === 'right')
  23616. {
  23617. linePosition.x += maxLineWidth - lineWidths[i];
  23618. }
  23619. else if (this.style.align === 'center')
  23620. {
  23621. linePosition.x += (maxLineWidth - lineWidths[i]) / 2;
  23622. }
  23623. linePosition.y += this._lineSpacing;
  23624. if (this.style.stroke && this.style.strokeThickness)
  23625. {
  23626. this.context.strokeText(lines[i], linePosition.x, linePosition.y);
  23627. }
  23628. if (this.style.fill)
  23629. {
  23630. this.context.fillText(lines[i], linePosition.x, linePosition.y);
  23631. }
  23632. }
  23633. this.updateTexture();
  23634. };
  23635. /**
  23636. * Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal bounds.
  23637. *
  23638. * @method Phaser.Text.prototype.runWordWrap
  23639. * @private
  23640. */
  23641. Phaser.Text.prototype.runWordWrap = function (text) {
  23642. var result = '';
  23643. var lines = text.split('\n');
  23644. for (var i = 0; i < lines.length; i++)
  23645. {
  23646. var spaceLeft = this.style.wordWrapWidth;
  23647. var words = lines[i].split(' ');
  23648. for (var j = 0; j < words.length; j++)
  23649. {
  23650. var wordWidth = this.context.measureText(words[j]).width;
  23651. var wordWidthWithSpace = wordWidth + this.context.measureText(' ').width;
  23652. if (wordWidthWithSpace > spaceLeft)
  23653. {
  23654. // Skip printing the newline if it's the first word of the line that is greater than the word wrap width.
  23655. if (j > 0)
  23656. {
  23657. result += '\n';
  23658. }
  23659. result += words[j] + ' ';
  23660. spaceLeft = this.style.wordWrapWidth - wordWidth;
  23661. }
  23662. else
  23663. {
  23664. spaceLeft -= wordWidthWithSpace;
  23665. result += words[j] + ' ';
  23666. }
  23667. }
  23668. if (i < lines.length-1)
  23669. {
  23670. result += '\n';
  23671. }
  23672. }
  23673. return result;
  23674. };
  23675. /**
  23676. * Indicates the rotation of the Text, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation.
  23677. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90.
  23678. * If you wish to work in radians instead of degrees use the property Sprite.rotation instead.
  23679. * @name Phaser.Text#angle
  23680. * @property {number} angle - Gets or sets the angle of rotation in degrees.
  23681. */
  23682. Object.defineProperty(Phaser.Text.prototype, 'angle', {
  23683. get: function() {
  23684. return Phaser.Math.radToDeg(this.rotation);
  23685. },
  23686. set: function(value) {
  23687. this.rotation = Phaser.Math.degToRad(value);
  23688. }
  23689. });
  23690. /**
  23691. * The text string to be displayed by this Text object, taking into account the style settings.
  23692. * @name Phaser.Text#text
  23693. * @property {string} text - The text string to be displayed by this Text object, taking into account the style settings.
  23694. */
  23695. Object.defineProperty(Phaser.Text.prototype, 'text', {
  23696. get: function() {
  23697. return this._text;
  23698. },
  23699. set: function(value) {
  23700. if (value !== this._text)
  23701. {
  23702. this._text = value.toString() || ' ';
  23703. this.dirty = true;
  23704. this.updateTransform();
  23705. }
  23706. }
  23707. });
  23708. /**
  23709. * @name Phaser.Text#font
  23710. * @property {string} font - The font the text will be rendered in, i.e. 'Arial'. Must be loaded in the browser before use.
  23711. */
  23712. Object.defineProperty(Phaser.Text.prototype, 'font', {
  23713. get: function() {
  23714. return this._font;
  23715. },
  23716. set: function(value) {
  23717. if (value !== this._font)
  23718. {
  23719. this._font = value.trim();
  23720. this.style.font = this._fontWeight + ' ' + this._fontSize + "px '" + this._font + "'";
  23721. this.dirty = true;
  23722. this.updateTransform();
  23723. }
  23724. }
  23725. });
  23726. /**
  23727. * @name Phaser.Text#fontSize
  23728. * @property {number} fontSize - The size of the font in pixels.
  23729. */
  23730. Object.defineProperty(Phaser.Text.prototype, 'fontSize', {
  23731. get: function() {
  23732. return this._fontSize;
  23733. },
  23734. set: function(value) {
  23735. value = parseInt(value, 10);
  23736. if (value !== this._fontSize)
  23737. {
  23738. this._fontSize = value;
  23739. this.style.font = this._fontWeight + ' ' + this._fontSize + "px '" + this._font + "'";
  23740. this.dirty = true;
  23741. this.updateTransform();
  23742. }
  23743. }
  23744. });
  23745. /**
  23746. * @name Phaser.Text#fontWeight
  23747. * @property {number} fontWeight - The weight of the font: 'normal', 'bold', 'italic'. You can combine settings too, such as 'bold italic'.
  23748. */
  23749. Object.defineProperty(Phaser.Text.prototype, 'fontWeight', {
  23750. get: function() {
  23751. return this._fontWeight;
  23752. },
  23753. set: function(value) {
  23754. if (value !== this._fontWeight)
  23755. {
  23756. this._fontWeight = value;
  23757. this.style.font = this._fontWeight + ' ' + this._fontSize + "px '" + this._font + "'";
  23758. this.dirty = true;
  23759. this.updateTransform();
  23760. }
  23761. }
  23762. });
  23763. /**
  23764. * @name Phaser.Text#fill
  23765. * @property {object} fill - A canvas fillstyle that will be used on the text eg 'red', '#00FF00'.
  23766. */
  23767. Object.defineProperty(Phaser.Text.prototype, 'fill', {
  23768. get: function() {
  23769. return this.style.fill;
  23770. },
  23771. set: function(value) {
  23772. if (value !== this.style.fill)
  23773. {
  23774. this.style.fill = value;
  23775. this.dirty = true;
  23776. }
  23777. }
  23778. });
  23779. /**
  23780. * @name Phaser.Text#align
  23781. * @property {string} align - Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text.
  23782. */
  23783. Object.defineProperty(Phaser.Text.prototype, 'align', {
  23784. get: function() {
  23785. return this.style.align;
  23786. },
  23787. set: function(value) {
  23788. if (value !== this.style.align)
  23789. {
  23790. this.style.align = value;
  23791. this.dirty = true;
  23792. }
  23793. }
  23794. });
  23795. /**
  23796. * @name Phaser.Text#stroke
  23797. * @property {string} stroke - A canvas fillstyle that will be used on the text stroke eg 'blue', '#FCFF00'.
  23798. */
  23799. Object.defineProperty(Phaser.Text.prototype, 'stroke', {
  23800. get: function() {
  23801. return this.style.stroke;
  23802. },
  23803. set: function(value) {
  23804. if (value !== this.style.stroke)
  23805. {
  23806. this.style.stroke = value;
  23807. this.dirty = true;
  23808. }
  23809. }
  23810. });
  23811. /**
  23812. * @name Phaser.Text#strokeThickness
  23813. * @property {number} strokeThickness - A number that represents the thickness of the stroke. Default is 0 (no stroke)
  23814. */
  23815. Object.defineProperty(Phaser.Text.prototype, 'strokeThickness', {
  23816. get: function() {
  23817. return this.style.strokeThickness;
  23818. },
  23819. set: function(value) {
  23820. if (value !== this.style.strokeThickness)
  23821. {
  23822. this.style.strokeThickness = value;
  23823. this.dirty = true;
  23824. }
  23825. }
  23826. });
  23827. /**
  23828. * @name Phaser.Text#wordWrap
  23829. * @property {boolean} wordWrap - Indicates if word wrap should be used.
  23830. */
  23831. Object.defineProperty(Phaser.Text.prototype, 'wordWrap', {
  23832. get: function() {
  23833. return this.style.wordWrap;
  23834. },
  23835. set: function(value) {
  23836. if (value !== this.style.wordWrap)
  23837. {
  23838. this.style.wordWrap = value;
  23839. this.dirty = true;
  23840. }
  23841. }
  23842. });
  23843. /**
  23844. * @name Phaser.Text#wordWrapWidth
  23845. * @property {number} wordWrapWidth - The width at which text will wrap.
  23846. */
  23847. Object.defineProperty(Phaser.Text.prototype, 'wordWrapWidth', {
  23848. get: function() {
  23849. return this.style.wordWrapWidth;
  23850. },
  23851. set: function(value) {
  23852. if (value !== this.style.wordWrapWidth)
  23853. {
  23854. this.style.wordWrapWidth = value;
  23855. this.dirty = true;
  23856. }
  23857. }
  23858. });
  23859. /**
  23860. * @name Phaser.Text#lineSpacing
  23861. * @property {number} lineSpacing - Additional spacing (in pixels) between each line of text if multi-line.
  23862. */
  23863. Object.defineProperty(Phaser.Text.prototype, 'lineSpacing', {
  23864. get: function() {
  23865. return this._lineSpacing;
  23866. },
  23867. set: function(value) {
  23868. if (value !== this._lineSpacing)
  23869. {
  23870. this._lineSpacing = parseFloat(value);
  23871. this.dirty = true;
  23872. this.updateTransform();
  23873. }
  23874. }
  23875. });
  23876. /**
  23877. * @name Phaser.Text#shadowOffsetX
  23878. * @property {number} shadowOffsetX - The shadowOffsetX value in pixels. This is how far offset horizontally the shadow effect will be.
  23879. */
  23880. Object.defineProperty(Phaser.Text.prototype, 'shadowOffsetX', {
  23881. get: function() {
  23882. return this.style.shadowOffsetX;
  23883. },
  23884. set: function(value) {
  23885. if (value !== this.style.shadowOffsetX)
  23886. {
  23887. this.style.shadowOffsetX = value;
  23888. this.dirty = true;
  23889. }
  23890. }
  23891. });
  23892. /**
  23893. * @name Phaser.Text#shadowOffsetY
  23894. * @property {number} shadowOffsetY - The shadowOffsetY value in pixels. This is how far offset vertically the shadow effect will be.
  23895. */
  23896. Object.defineProperty(Phaser.Text.prototype, 'shadowOffsetY', {
  23897. get: function() {
  23898. return this.style.shadowOffsetY;
  23899. },
  23900. set: function(value) {
  23901. if (value !== this.style.shadowOffsetY)
  23902. {
  23903. this.style.shadowOffsetY = value;
  23904. this.dirty = true;
  23905. }
  23906. }
  23907. });
  23908. /**
  23909. * @name Phaser.Text#shadowColor
  23910. * @property {string} shadowColor - The color of the shadow, as given in CSS rgba format. Set the alpha component to 0 to disable the shadow.
  23911. */
  23912. Object.defineProperty(Phaser.Text.prototype, 'shadowColor', {
  23913. get: function() {
  23914. return this.style.shadowColor;
  23915. },
  23916. set: function(value) {
  23917. if (value !== this.style.shadowColor)
  23918. {
  23919. this.style.shadowColor = value;
  23920. this.dirty = true;
  23921. }
  23922. }
  23923. });
  23924. /**
  23925. * @name Phaser.Text#shadowBlur
  23926. * @property {number} shadowBlur - The shadowBlur value. Make the shadow softer by applying a Gaussian blur to it. A number from 0 (no blur) up to approx. 10 (depending on scene).
  23927. */
  23928. Object.defineProperty(Phaser.Text.prototype, 'shadowBlur', {
  23929. get: function() {
  23930. return this.style.shadowBlur;
  23931. },
  23932. set: function(value) {
  23933. if (value !== this.style.shadowBlur)
  23934. {
  23935. this.style.shadowBlur = value;
  23936. this.dirty = true;
  23937. }
  23938. }
  23939. });
  23940. /**
  23941. * By default a Text object won't process any input events at all. By setting inputEnabled to true the Phaser.InputHandler is
  23942. * activated for this object and it will then start to process click/touch events and more.
  23943. *
  23944. * @name Phaser.Text#inputEnabled
  23945. * @property {boolean} inputEnabled - Set to true to allow this object to receive input events.
  23946. */
  23947. Object.defineProperty(Phaser.Text.prototype, "inputEnabled", {
  23948. get: function () {
  23949. return (this.input && this.input.enabled);
  23950. },
  23951. set: function (value) {
  23952. if (value)
  23953. {
  23954. if (this.input === null)
  23955. {
  23956. this.input = new Phaser.InputHandler(this);
  23957. this.input.start();
  23958. }
  23959. else if (this.input && !this.input.enabled)
  23960. {
  23961. this.input.start();
  23962. }
  23963. }
  23964. else
  23965. {
  23966. if (this.input && this.input.enabled)
  23967. {
  23968. this.input.stop();
  23969. }
  23970. }
  23971. }
  23972. });
  23973. /**
  23974. * An Text that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in Text.cameraOffset.
  23975. * Note that the cameraOffset values are in addition to any parent in the display list.
  23976. * So if this Text was in a Group that has x: 200, then this will be added to the cameraOffset.x
  23977. *
  23978. * @name Phaser.Text#fixedToCamera
  23979. * @property {boolean} fixedToCamera - Set to true to fix this Text to the Camera at its current world coordinates.
  23980. */
  23981. Object.defineProperty(Phaser.Text.prototype, "fixedToCamera", {
  23982. get: function () {
  23983. return !!this._cache[7];
  23984. },
  23985. set: function (value) {
  23986. if (value)
  23987. {
  23988. this._cache[7] = 1;
  23989. this.cameraOffset.set(this.x, this.y);
  23990. }
  23991. else
  23992. {
  23993. this._cache[7] = 0;
  23994. }
  23995. }
  23996. });
  23997. /**
  23998. * @author Richard Davey <rich@photonstorm.com>
  23999. * @copyright 2014 Photon Storm Ltd.
  24000. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  24001. */
  24002. /**
  24003. * Creates a new BitmapText object.
  24004. *
  24005. * @class Phaser.BitmapText
  24006. *
  24007. * @classdesc BitmapText objects work by taking a texture file and an XML file that describes the font layout.
  24008. *
  24009. * On Windows you can use the free app BMFont: http://www.angelcode.com/products/bmfont/
  24010. * On OS X we recommend Glyph Designer: http://www.71squared.com/en/glyphdesigner
  24011. * For Web there is the great Littera: http://kvazars.com/littera/
  24012. *
  24013. * @constructor
  24014. * @param {Phaser.Game} game - A reference to the currently running game.
  24015. * @param {number} x - X position of the new bitmapText object.
  24016. * @param {number} y - Y position of the new bitmapText object.
  24017. * @param {string} font - The key of the BitmapFont as stored in Game.Cache.
  24018. * @param {string} [text=''] - The actual text that will be rendered. Can be set later via BitmapText.text.
  24019. * @param {number} [size=32] - The size the font will be rendered in, in pixels.
  24020. */
  24021. Phaser.BitmapText = function (game, x, y, font, text, size) {
  24022. x = x || 0;
  24023. y = y || 0;
  24024. font = font || '';
  24025. text = text || '';
  24026. size = size || 32;
  24027. /**
  24028. * @property {Phaser.Game} game - A reference to the currently running Game.
  24029. */
  24030. this.game = game;
  24031. /**
  24032. * @property {boolean} exists - If exists = false then the Sprite isn't updated by the core game loop or physics subsystem at all.
  24033. * @default
  24034. */
  24035. this.exists = true;
  24036. /**
  24037. * @property {string} name - The user defined name given to this BitmapText.
  24038. * @default
  24039. */
  24040. this.name = '';
  24041. /**
  24042. * @property {number} type - The const type of this object.
  24043. * @readonly
  24044. */
  24045. this.type = Phaser.BITMAPTEXT;
  24046. /**
  24047. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  24048. */
  24049. this.z = 0;
  24050. /**
  24051. * @property {Phaser.Point} world - The world coordinates of this Sprite. This differs from the x/y coordinates which are relative to the Sprites container.
  24052. */
  24053. this.world = new Phaser.Point(x, y);
  24054. /**
  24055. * @property {string} _text - Internal cache var.
  24056. * @private
  24057. */
  24058. this._text = text;
  24059. /**
  24060. * @property {string} _font - Internal cache var.
  24061. * @private
  24062. */
  24063. this._font = font;
  24064. /**
  24065. * @property {number} _fontSize - Internal cache var.
  24066. * @private
  24067. */
  24068. this._fontSize = size;
  24069. /**
  24070. * @property {string} _align - Internal cache var.
  24071. * @private
  24072. */
  24073. this._align = 'left';
  24074. /**
  24075. * @property {number} _tint - Internal cache var.
  24076. * @private
  24077. */
  24078. this._tint = 0xFFFFFF;
  24079. /**
  24080. * @property {Phaser.Events} events - The Events you can subscribe to that are dispatched when certain things happen on this Sprite or its components.
  24081. */
  24082. this.events = new Phaser.Events(this);
  24083. /**
  24084. * @property {Phaser.InputHandler|null} input - The Input Handler for this object. Needs to be enabled with image.inputEnabled = true before you can use it.
  24085. */
  24086. this.input = null;
  24087. /**
  24088. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  24089. */
  24090. this.cameraOffset = new Phaser.Point();
  24091. PIXI.BitmapText.call(this, text);
  24092. this.position.set(x, y);
  24093. /**
  24094. * A small internal cache:
  24095. * 0 = previous position.x
  24096. * 1 = previous position.y
  24097. * 2 = previous rotation
  24098. * 3 = renderID
  24099. * 4 = fresh? (0 = no, 1 = yes)
  24100. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  24101. * 6 = exists (0 = no, 1 = yes)
  24102. * 7 = fixed to camera (0 = no, 1 = yes)
  24103. * @property {Array} _cache
  24104. * @private
  24105. */
  24106. this._cache = [0, 0, 0, 0, 1, 0, 1, 0];
  24107. };
  24108. Phaser.BitmapText.prototype = Object.create(PIXI.BitmapText.prototype);
  24109. Phaser.BitmapText.prototype.constructor = Phaser.BitmapText;
  24110. /**
  24111. * @method Phaser.BitmapText.prototype.setStyle
  24112. * @private
  24113. */
  24114. Phaser.BitmapText.prototype.setStyle = function() {
  24115. this.style = { align: this._align };
  24116. this.fontName = this._font;
  24117. this.fontSize = this._fontSize;
  24118. this.dirty = true;
  24119. };
  24120. /**
  24121. * Automatically called by World.preUpdate.
  24122. * @method Phaser.BitmapText.prototype.preUpdate
  24123. */
  24124. Phaser.BitmapText.prototype.preUpdate = function () {
  24125. this._cache[0] = this.world.x;
  24126. this._cache[1] = this.world.y;
  24127. this._cache[2] = this.rotation;
  24128. if (!this.exists || !this.parent.exists)
  24129. {
  24130. this.renderOrderID = -1;
  24131. return false;
  24132. }
  24133. if (this.autoCull)
  24134. {
  24135. // Won't get rendered but will still get its transform updated
  24136. this.renderable = this.game.world.camera.screenView.intersects(this.getBounds());
  24137. }
  24138. this.world.setTo(this.game.camera.x + this.worldTransform[2], this.game.camera.y + this.worldTransform[5]);
  24139. if (this.visible)
  24140. {
  24141. this._cache[3] = this.game.stage.currentRenderOrderID++;
  24142. }
  24143. return true;
  24144. };
  24145. /**
  24146. * Override and use this function in your own custom objects to handle any update requirements you may have.
  24147. *
  24148. * @method Phaser.BitmapText.prototype.update
  24149. */
  24150. Phaser.BitmapText.prototype.update = function() {
  24151. };
  24152. /**
  24153. * Automatically called by World.postUpdate.
  24154. * @method Phaser.BitmapText.prototype.postUpdate
  24155. */
  24156. Phaser.BitmapText.prototype.postUpdate = function () {
  24157. // Fixed to Camera?
  24158. if (this._cache[7] === 1)
  24159. {
  24160. this.position.x = (this.game.camera.view.x + this.cameraOffset.x) / this.game.camera.scale.x;
  24161. this.position.y = (this.game.camera.view.y + this.cameraOffset.y) / this.game.camera.scale.y;
  24162. }
  24163. };
  24164. /**
  24165. * Destroy this BitmapText instance. This will remove any filters and un-parent any children.
  24166. * @method Phaser.BitmapText.prototype.destroy
  24167. * @param {boolean} [destroyChildren=true] - Should every child of this object have its destroy method called?
  24168. */
  24169. Phaser.BitmapText.prototype.destroy = function(destroyChildren) {
  24170. if (this.game === null) { return; }
  24171. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  24172. if (this.parent)
  24173. {
  24174. if (this.parent instanceof Phaser.Group)
  24175. {
  24176. this.parent.remove(this);
  24177. }
  24178. else
  24179. {
  24180. this.parent.removeChild(this);
  24181. }
  24182. }
  24183. var i = this.children.length;
  24184. if (destroyChildren)
  24185. {
  24186. while (i--)
  24187. {
  24188. if (this.children[i].destroy)
  24189. {
  24190. this.children[i].destroy(destroyChildren);
  24191. }
  24192. else
  24193. {
  24194. this.removeChild(this.children[i]);
  24195. }
  24196. }
  24197. }
  24198. else
  24199. {
  24200. while (i--)
  24201. {
  24202. this.removeChild(this.children[i]);
  24203. }
  24204. }
  24205. this.exists = false;
  24206. this.visible = false;
  24207. this.filters = null;
  24208. this.mask = null;
  24209. this.game = null;
  24210. };
  24211. /**
  24212. * @name Phaser.BitmapText#align
  24213. * @property {string} align - Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text.
  24214. */
  24215. Object.defineProperty(Phaser.BitmapText.prototype, 'align', {
  24216. get: function() {
  24217. return this._align;
  24218. },
  24219. set: function(value) {
  24220. if (value !== this._align)
  24221. {
  24222. this._align = value;
  24223. this.setStyle();
  24224. }
  24225. }
  24226. });
  24227. /**
  24228. * @name Phaser.BitmapText#tint
  24229. * @property {number} tint - The tint applied to the BitmapText. This is a hex value. Set to white to disable (0xFFFFFF)
  24230. */
  24231. Object.defineProperty(Phaser.BitmapText.prototype, 'tint', {
  24232. get: function() {
  24233. return this._tint;
  24234. },
  24235. set: function(value) {
  24236. if (value !== this._tint)
  24237. {
  24238. this._tint = value;
  24239. this.dirty = true;
  24240. }
  24241. }
  24242. });
  24243. /**
  24244. * Indicates the rotation of the Text, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation.
  24245. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90.
  24246. * If you wish to work in radians instead of degrees use the property Sprite.rotation instead.
  24247. * @name Phaser.BitmapText#angle
  24248. * @property {number} angle - Gets or sets the angle of rotation in degrees.
  24249. */
  24250. Object.defineProperty(Phaser.BitmapText.prototype, 'angle', {
  24251. get: function() {
  24252. return Phaser.Math.radToDeg(this.rotation);
  24253. },
  24254. set: function(value) {
  24255. this.rotation = Phaser.Math.degToRad(value);
  24256. }
  24257. });
  24258. /**
  24259. * @name Phaser.BitmapText#font
  24260. * @property {string} font - The font the text will be rendered in, i.e. 'Arial'. Must be loaded in the browser before use.
  24261. */
  24262. Object.defineProperty(Phaser.BitmapText.prototype, 'font', {
  24263. get: function() {
  24264. return this._font;
  24265. },
  24266. set: function(value) {
  24267. if (value !== this._font)
  24268. {
  24269. this._font = value.trim();
  24270. this.style.font = this._fontSize + "px '" + this._font + "'";
  24271. this.dirty = true;
  24272. }
  24273. }
  24274. });
  24275. /**
  24276. * @name Phaser.BitmapText#fontSize
  24277. * @property {number} fontSize - The size of the font in pixels.
  24278. */
  24279. Object.defineProperty(Phaser.BitmapText.prototype, 'fontSize', {
  24280. get: function() {
  24281. return this._fontSize;
  24282. },
  24283. set: function(value) {
  24284. value = parseInt(value, 10);
  24285. if (value !== this._fontSize)
  24286. {
  24287. this._fontSize = value;
  24288. this.style.font = this._fontSize + "px '" + this._font + "'";
  24289. this.dirty = true;
  24290. }
  24291. }
  24292. });
  24293. /**
  24294. * The text string to be displayed by this Text object, taking into account the style settings.
  24295. * @name Phaser.BitmapText#text
  24296. * @property {string} text - The text string to be displayed by this Text object, taking into account the style settings.
  24297. */
  24298. Object.defineProperty(Phaser.BitmapText.prototype, 'text', {
  24299. get: function() {
  24300. return this._text;
  24301. },
  24302. set: function(value) {
  24303. if (value !== this._text)
  24304. {
  24305. this._text = value.toString() || ' ';
  24306. this.dirty = true;
  24307. }
  24308. }
  24309. });
  24310. /**
  24311. * By default a Text object won't process any input events at all. By setting inputEnabled to true the Phaser.InputHandler is
  24312. * activated for this object and it will then start to process click/touch events and more.
  24313. *
  24314. * @name Phaser.BitmapText#inputEnabled
  24315. * @property {boolean} inputEnabled - Set to true to allow this object to receive input events.
  24316. */
  24317. Object.defineProperty(Phaser.BitmapText.prototype, "inputEnabled", {
  24318. get: function () {
  24319. return (this.input && this.input.enabled);
  24320. },
  24321. set: function (value) {
  24322. if (value)
  24323. {
  24324. if (this.input === null)
  24325. {
  24326. this.input = new Phaser.InputHandler(this);
  24327. this.input.start();
  24328. }
  24329. else if (this.input && !this.input.enabled)
  24330. {
  24331. this.input.start();
  24332. }
  24333. }
  24334. else
  24335. {
  24336. if (this.input && this.input.enabled)
  24337. {
  24338. this.input.stop();
  24339. }
  24340. }
  24341. }
  24342. });
  24343. /**
  24344. * An BitmapText that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in BitmapText.cameraOffset.
  24345. * Note that the cameraOffset values are in addition to any parent in the display list.
  24346. * So if this BitmapText was in a Group that has x: 200, then this will be added to the cameraOffset.x
  24347. *
  24348. * @name Phaser.BitmapText#fixedToCamera
  24349. * @property {boolean} fixedToCamera - Set to true to fix this BitmapText to the Camera at its current world coordinates.
  24350. */
  24351. Object.defineProperty(Phaser.BitmapText.prototype, "fixedToCamera", {
  24352. get: function () {
  24353. return !!this._cache[7];
  24354. },
  24355. set: function (value) {
  24356. if (value)
  24357. {
  24358. this._cache[7] = 1;
  24359. this.cameraOffset.set(this.x, this.y);
  24360. }
  24361. else
  24362. {
  24363. this._cache[7] = 0;
  24364. }
  24365. }
  24366. });
  24367. /**
  24368. * @author Richard Davey <rich@photonstorm.com>
  24369. * @copyright 2014 Photon Storm Ltd.
  24370. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  24371. */
  24372. /**
  24373. * @class Phaser.Button
  24374. *
  24375. * @classdesc Create a new `Button` object. A Button is a special type of Sprite that is set-up to handle Pointer events automatically. The four states a Button responds to are:
  24376. *
  24377. * * 'Over' - when the Pointer moves over the Button. This is also commonly known as 'hover'.
  24378. * * 'Out' - when the Pointer that was previously over the Button moves out of it.
  24379. * * 'Down' - when the Pointer is pressed down on the Button. I.e. touched on a touch enabled device or clicked with the mouse.
  24380. * * 'Up' - when the Pointer that was pressed down on the Button is released again.
  24381. *
  24382. * You can set a unique texture frame and Sound for any of these states.
  24383. *
  24384. * @constructor
  24385. * @extends Phaser.Image
  24386. *
  24387. * @param {Phaser.Game} game Current game instance.
  24388. * @param {number} [x=0] - X position of the Button.
  24389. * @param {number} [y=0] - Y position of the Button.
  24390. * @param {string} [key] - The image key as defined in the Game.Cache to use as the texture for this Button.
  24391. * @param {function} [callback] - The function to call when this Button is pressed.
  24392. * @param {object} [callbackContext] - The context in which the callback will be called (usually 'this').
  24393. * @param {string|number} [overFrame] - This is the frame or frameName that will be set when this button is in an over state. Give either a number to use a frame ID or a string for a frame name.
  24394. * @param {string|number} [outFrame] - This is the frame or frameName that will be set when this button is in an out state. Give either a number to use a frame ID or a string for a frame name.
  24395. * @param {string|number} [downFrame] - This is the frame or frameName that will be set when this button is in a down state. Give either a number to use a frame ID or a string for a frame name.
  24396. * @param {string|number} [upFrame] - This is the frame or frameName that will be set when this button is in an up state. Give either a number to use a frame ID or a string for a frame name.
  24397. */
  24398. Phaser.Button = function (game, x, y, key, callback, callbackContext, overFrame, outFrame, downFrame, upFrame) {
  24399. x = x || 0;
  24400. y = y || 0;
  24401. key = key || null;
  24402. callback = callback || null;
  24403. callbackContext = callbackContext || this;
  24404. Phaser.Image.call(this, game, x, y, key, outFrame);
  24405. /**
  24406. * @property {number} type - The Phaser Object Type.
  24407. */
  24408. this.type = Phaser.BUTTON;
  24409. /**
  24410. * @property {string} _onOverFrameName - Internal variable.
  24411. * @private
  24412. * @default
  24413. */
  24414. this._onOverFrameName = null;
  24415. /**
  24416. * @property {string} _onOutFrameName - Internal variable.
  24417. * @private
  24418. * @default
  24419. */
  24420. this._onOutFrameName = null;
  24421. /**
  24422. * @property {string} _onDownFrameName - Internal variable.
  24423. * @private
  24424. * @default
  24425. */
  24426. this._onDownFrameName = null;
  24427. /**
  24428. * @property {string} _onUpFrameName - Internal variable.
  24429. * @private
  24430. * @default
  24431. */
  24432. this._onUpFrameName = null;
  24433. /**
  24434. * @property {number} _onOverFrameID - Internal variable.
  24435. * @private
  24436. * @default
  24437. */
  24438. this._onOverFrameID = null;
  24439. /**
  24440. * @property {number} _onOutFrameID - Internal variable.
  24441. * @private
  24442. * @default
  24443. */
  24444. this._onOutFrameID = null;
  24445. /**
  24446. * @property {number} _onDownFrameID - Internal variable.
  24447. * @private
  24448. * @default
  24449. */
  24450. this._onDownFrameID = null;
  24451. /**
  24452. * @property {number} _onUpFrameID - Internal variable.
  24453. * @private
  24454. * @default
  24455. */
  24456. this._onUpFrameID = null;
  24457. /**
  24458. * @property {Phaser.Sound} onOverSound - The Sound to be played when this Buttons Over state is activated.
  24459. * @default
  24460. */
  24461. this.onOverSound = null;
  24462. /**
  24463. * @property {Phaser.Sound} onOutSound - The Sound to be played when this Buttons Out state is activated.
  24464. * @default
  24465. */
  24466. this.onOutSound = null;
  24467. /**
  24468. * @property {Phaser.Sound} onDownSound - The Sound to be played when this Buttons Down state is activated.
  24469. * @default
  24470. */
  24471. this.onDownSound = null;
  24472. /**
  24473. * @property {Phaser.Sound} onUpSound - The Sound to be played when this Buttons Up state is activated.
  24474. * @default
  24475. */
  24476. this.onUpSound = null;
  24477. /**
  24478. * @property {string} onOverSoundMarker - The Sound Marker used in conjunction with the onOverSound.
  24479. * @default
  24480. */
  24481. this.onOverSoundMarker = '';
  24482. /**
  24483. * @property {string} onOutSoundMarker - The Sound Marker used in conjunction with the onOutSound.
  24484. * @default
  24485. */
  24486. this.onOutSoundMarker = '';
  24487. /**
  24488. * @property {string} onDownSoundMarker - The Sound Marker used in conjunction with the onDownSound.
  24489. * @default
  24490. */
  24491. this.onDownSoundMarker = '';
  24492. /**
  24493. * @property {string} onUpSoundMarker - The Sound Marker used in conjunction with the onUpSound.
  24494. * @default
  24495. */
  24496. this.onUpSoundMarker = '';
  24497. /**
  24498. * @property {Phaser.Signal} onInputOver - The Signal (or event) dispatched when this Button is in an Over state.
  24499. */
  24500. this.onInputOver = new Phaser.Signal();
  24501. /**
  24502. * @property {Phaser.Signal} onInputOut - The Signal (or event) dispatched when this Button is in an Out state.
  24503. */
  24504. this.onInputOut = new Phaser.Signal();
  24505. /**
  24506. * @property {Phaser.Signal} onInputDown - The Signal (or event) dispatched when this Button is in an Down state.
  24507. */
  24508. this.onInputDown = new Phaser.Signal();
  24509. /**
  24510. * @property {Phaser.Signal} onInputUp - The Signal (or event) dispatched when this Button is in an Up state.
  24511. */
  24512. this.onInputUp = new Phaser.Signal();
  24513. /**
  24514. * @property {boolean} freezeFrames - When true the Button will cease to change texture frame on all events (over, out, up, down).
  24515. */
  24516. this.freezeFrames = false;
  24517. /**
  24518. * When the Button is touched / clicked and then released you can force it to enter a state of "out" instead of "up".
  24519. * @property {boolean} forceOut
  24520. * @default
  24521. */
  24522. this.forceOut = false;
  24523. this.inputEnabled = true;
  24524. this.input.start(0, true);
  24525. this.setFrames(overFrame, outFrame, downFrame, upFrame);
  24526. if (callback !== null)
  24527. {
  24528. this.onInputUp.add(callback, callbackContext);
  24529. }
  24530. // Redirect the input events to here so we can handle animation updates, etc
  24531. this.events.onInputOver.add(this.onInputOverHandler, this);
  24532. this.events.onInputOut.add(this.onInputOutHandler, this);
  24533. this.events.onInputDown.add(this.onInputDownHandler, this);
  24534. this.events.onInputUp.add(this.onInputUpHandler, this);
  24535. };
  24536. Phaser.Button.prototype = Object.create(Phaser.Image.prototype);
  24537. Phaser.Button.prototype.constructor = Phaser.Button;
  24538. /**
  24539. * Clears all of the frames set on this Button.
  24540. *
  24541. * @method Phaser.Button.prototype.clearFrames
  24542. */
  24543. Phaser.Button.prototype.clearFrames = function () {
  24544. this._onOverFrameName = null;
  24545. this._onOverFrameID = null;
  24546. this._onOutFrameName = null;
  24547. this._onOutFrameID = null;
  24548. this._onDownFrameName = null;
  24549. this._onDownFrameID = null;
  24550. this._onUpFrameName = null;
  24551. this._onUpFrameID = null;
  24552. };
  24553. /**
  24554. * Used to manually set the frames that will be used for the different states of the Button.
  24555. *
  24556. * @method Phaser.Button.prototype.setFrames
  24557. * @param {string|number} [overFrame] - This is the frame or frameName that will be set when this button is in an over state. Give either a number to use a frame ID or a string for a frame name.
  24558. * @param {string|number} [outFrame] - This is the frame or frameName that will be set when this button is in an out state. Give either a number to use a frame ID or a string for a frame name.
  24559. * @param {string|number} [downFrame] - This is the frame or frameName that will be set when this button is in a down state. Give either a number to use a frame ID or a string for a frame name.
  24560. * @param {string|number} [upFrame] - This is the frame or frameName that will be set when this button is in an up state. Give either a number to use a frame ID or a string for a frame name.
  24561. */
  24562. Phaser.Button.prototype.setFrames = function (overFrame, outFrame, downFrame, upFrame) {
  24563. this.clearFrames();
  24564. if (overFrame !== null)
  24565. {
  24566. if (typeof overFrame === 'string')
  24567. {
  24568. this._onOverFrameName = overFrame;
  24569. if (this.input.pointerOver())
  24570. {
  24571. this.frameName = overFrame;
  24572. }
  24573. }
  24574. else
  24575. {
  24576. this._onOverFrameID = overFrame;
  24577. if (this.input.pointerOver())
  24578. {
  24579. this.frame = overFrame;
  24580. }
  24581. }
  24582. }
  24583. if (outFrame !== null)
  24584. {
  24585. if (typeof outFrame === 'string')
  24586. {
  24587. this._onOutFrameName = outFrame;
  24588. if (this.input.pointerOver() === false)
  24589. {
  24590. this.frameName = outFrame;
  24591. }
  24592. }
  24593. else
  24594. {
  24595. this._onOutFrameID = outFrame;
  24596. if (this.input.pointerOver() === false)
  24597. {
  24598. this.frame = outFrame;
  24599. }
  24600. }
  24601. }
  24602. if (downFrame !== null)
  24603. {
  24604. if (typeof downFrame === 'string')
  24605. {
  24606. this._onDownFrameName = downFrame;
  24607. if (this.input.pointerDown())
  24608. {
  24609. this.frameName = downFrame;
  24610. }
  24611. }
  24612. else
  24613. {
  24614. this._onDownFrameID = downFrame;
  24615. if (this.input.pointerDown())
  24616. {
  24617. this.frame = downFrame;
  24618. }
  24619. }
  24620. }
  24621. if (upFrame !== null)
  24622. {
  24623. if (typeof upFrame === 'string')
  24624. {
  24625. this._onUpFrameName = upFrame;
  24626. if (this.input.pointerUp())
  24627. {
  24628. this.frameName = upFrame;
  24629. }
  24630. }
  24631. else
  24632. {
  24633. this._onUpFrameID = upFrame;
  24634. if (this.input.pointerUp())
  24635. {
  24636. this.frame = upFrame;
  24637. }
  24638. }
  24639. }
  24640. };
  24641. /**
  24642. * Sets the sounds to be played whenever this Button is interacted with. Sounds can be either full Sound objects, or markers pointing to a section of a Sound object.
  24643. * The most common forms of sounds are 'hover' effects and 'click' effects, which is why the order of the parameters is overSound then downSound.
  24644. * Call this function with no parameters at all to reset all sounds on this Button.
  24645. *
  24646. * @method Phaser.Button.prototype.setSounds
  24647. * @param {Phaser.Sound} [overSound] - Over Button Sound.
  24648. * @param {string} [overMarker] - Over Button Sound Marker.
  24649. * @param {Phaser.Sound} [downSound] - Down Button Sound.
  24650. * @param {string} [downMarker] - Down Button Sound Marker.
  24651. * @param {Phaser.Sound} [outSound] - Out Button Sound.
  24652. * @param {string} [outMarker] - Out Button Sound Marker.
  24653. * @param {Phaser.Sound} [upSound] - Up Button Sound.
  24654. * @param {string} [upMarker] - Up Button Sound Marker.
  24655. */
  24656. Phaser.Button.prototype.setSounds = function (overSound, overMarker, downSound, downMarker, outSound, outMarker, upSound, upMarker) {
  24657. this.setOverSound(overSound, overMarker);
  24658. this.setOutSound(outSound, outMarker);
  24659. this.setDownSound(downSound, downMarker);
  24660. this.setUpSound(upSound, upMarker);
  24661. };
  24662. /**
  24663. * The Sound to be played when a Pointer moves over this Button.
  24664. *
  24665. * @method Phaser.Button.prototype.setOverSound
  24666. * @param {Phaser.Sound} sound - The Sound that will be played.
  24667. * @param {string} [marker] - A Sound Marker that will be used in the playback.
  24668. */
  24669. Phaser.Button.prototype.setOverSound = function (sound, marker) {
  24670. this.onOverSound = null;
  24671. this.onOverSoundMarker = '';
  24672. if (sound instanceof Phaser.Sound)
  24673. {
  24674. this.onOverSound = sound;
  24675. }
  24676. if (typeof marker === 'string')
  24677. {
  24678. this.onOverSoundMarker = marker;
  24679. }
  24680. };
  24681. /**
  24682. * The Sound to be played when a Pointer moves out of this Button.
  24683. *
  24684. * @method Phaser.Button.prototype.setOutSound
  24685. * @param {Phaser.Sound} sound - The Sound that will be played.
  24686. * @param {string} [marker] - A Sound Marker that will be used in the playback.
  24687. */
  24688. Phaser.Button.prototype.setOutSound = function (sound, marker) {
  24689. this.onOutSound = null;
  24690. this.onOutSoundMarker = '';
  24691. if (sound instanceof Phaser.Sound)
  24692. {
  24693. this.onOutSound = sound;
  24694. }
  24695. if (typeof marker === 'string')
  24696. {
  24697. this.onOutSoundMarker = marker;
  24698. }
  24699. };
  24700. /**
  24701. * The Sound to be played when a Pointer presses down on this Button.
  24702. *
  24703. * @method Phaser.Button.prototype.setDownSound
  24704. * @param {Phaser.Sound} sound - The Sound that will be played.
  24705. * @param {string} [marker] - A Sound Marker that will be used in the playback.
  24706. */
  24707. Phaser.Button.prototype.setDownSound = function (sound, marker) {
  24708. this.onDownSound = null;
  24709. this.onDownSoundMarker = '';
  24710. if (sound instanceof Phaser.Sound)
  24711. {
  24712. this.onDownSound = sound;
  24713. }
  24714. if (typeof marker === 'string')
  24715. {
  24716. this.onDownSoundMarker = marker;
  24717. }
  24718. };
  24719. /**
  24720. * The Sound to be played when a Pointer has pressed down and is released from this Button.
  24721. *
  24722. * @method Phaser.Button.prototype.setUpSound
  24723. * @param {Phaser.Sound} sound - The Sound that will be played.
  24724. * @param {string} [marker] - A Sound Marker that will be used in the playback.
  24725. */
  24726. Phaser.Button.prototype.setUpSound = function (sound, marker) {
  24727. this.onUpSound = null;
  24728. this.onUpSoundMarker = '';
  24729. if (sound instanceof Phaser.Sound)
  24730. {
  24731. this.onUpSound = sound;
  24732. }
  24733. if (typeof marker === 'string')
  24734. {
  24735. this.onUpSoundMarker = marker;
  24736. }
  24737. };
  24738. /**
  24739. * Internal function that handles input events.
  24740. *
  24741. * @protected
  24742. * @method Phaser.Button.prototype.onInputOverHandler
  24743. * @param {Phaser.Button} sprite - The Button that the event occured on.
  24744. * @param {Phaser.Pointer} pointer - The Pointer that activated the Button.
  24745. */
  24746. Phaser.Button.prototype.onInputOverHandler = function (sprite, pointer) {
  24747. if (this.freezeFrames === false)
  24748. {
  24749. this.setState(1);
  24750. }
  24751. if (this.onOverSound)
  24752. {
  24753. this.onOverSound.play(this.onOverSoundMarker);
  24754. }
  24755. if (this.onInputOver)
  24756. {
  24757. this.onInputOver.dispatch(this, pointer);
  24758. }
  24759. };
  24760. /**
  24761. * Internal function that handles input events.
  24762. *
  24763. * @protected
  24764. * @method Phaser.Button.prototype.onInputOutHandler
  24765. * @param {Phaser.Button} sprite - The Button that the event occured on.
  24766. * @param {Phaser.Pointer} pointer - The Pointer that activated the Button.
  24767. */
  24768. Phaser.Button.prototype.onInputOutHandler = function (sprite, pointer) {
  24769. if (this.freezeFrames === false)
  24770. {
  24771. this.setState(2);
  24772. }
  24773. if (this.onOutSound)
  24774. {
  24775. this.onOutSound.play(this.onOutSoundMarker);
  24776. }
  24777. if (this.onInputOut)
  24778. {
  24779. this.onInputOut.dispatch(this, pointer);
  24780. }
  24781. };
  24782. /**
  24783. * Internal function that handles input events.
  24784. *
  24785. * @protected
  24786. * @method Phaser.Button.prototype.onInputDownHandler
  24787. * @param {Phaser.Button} sprite - The Button that the event occured on.
  24788. * @param {Phaser.Pointer} pointer - The Pointer that activated the Button.
  24789. */
  24790. Phaser.Button.prototype.onInputDownHandler = function (sprite, pointer) {
  24791. if (this.freezeFrames === false)
  24792. {
  24793. this.setState(3);
  24794. }
  24795. if (this.onDownSound)
  24796. {
  24797. this.onDownSound.play(this.onDownSoundMarker);
  24798. }
  24799. if (this.onInputDown)
  24800. {
  24801. this.onInputDown.dispatch(this, pointer);
  24802. }
  24803. };
  24804. /**
  24805. * Internal function that handles input events.
  24806. *
  24807. * @protected
  24808. * @method Phaser.Button.prototype.onInputUpHandler
  24809. * @param {Phaser.Button} sprite - The Button that the event occured on.
  24810. * @param {Phaser.Pointer} pointer - The Pointer that activated the Button.
  24811. */
  24812. Phaser.Button.prototype.onInputUpHandler = function (sprite, pointer, isOver) {
  24813. if (this.onUpSound)
  24814. {
  24815. this.onUpSound.play(this.onUpSoundMarker);
  24816. }
  24817. if (this.onInputUp)
  24818. {
  24819. this.onInputUp.dispatch(this, pointer, isOver);
  24820. }
  24821. if (this.freezeFrames)
  24822. {
  24823. return;
  24824. }
  24825. if (this.forceOut)
  24826. {
  24827. // Button should be forced to the Out frame when released.
  24828. this.setState(2);
  24829. }
  24830. else
  24831. {
  24832. if (this._onUpFrameName !== null || this._onUpFrameID !== null)
  24833. {
  24834. this.setState(4);
  24835. }
  24836. else
  24837. {
  24838. if (isOver)
  24839. {
  24840. this.setState(1);
  24841. }
  24842. else
  24843. {
  24844. this.setState(2);
  24845. }
  24846. }
  24847. }
  24848. };
  24849. /**
  24850. * Internal function that handles Button state changes.
  24851. *
  24852. * @protected
  24853. * @method Phaser.Button.prototype.setState
  24854. * @param {number} newState - The new State of the Button.
  24855. */
  24856. Phaser.Button.prototype.setState = function (newState) {
  24857. if (newState === 1)
  24858. {
  24859. // Over
  24860. if (this._onOverFrameName != null)
  24861. {
  24862. this.frameName = this._onOverFrameName;
  24863. }
  24864. else if (this._onOverFrameID != null)
  24865. {
  24866. this.frame = this._onOverFrameID;
  24867. }
  24868. }
  24869. else if (newState === 2)
  24870. {
  24871. // Out
  24872. if (this._onOutFrameName != null)
  24873. {
  24874. this.frameName = this._onOutFrameName;
  24875. }
  24876. else if (this._onOutFrameID != null)
  24877. {
  24878. this.frame = this._onOutFrameID;
  24879. }
  24880. }
  24881. else if (newState === 3)
  24882. {
  24883. // Down
  24884. if (this._onDownFrameName != null)
  24885. {
  24886. this.frameName = this._onDownFrameName;
  24887. }
  24888. else if (this._onDownFrameID != null)
  24889. {
  24890. this.frame = this._onDownFrameID;
  24891. }
  24892. }
  24893. else if (newState === 4)
  24894. {
  24895. // Up
  24896. if (this._onUpFrameName != null)
  24897. {
  24898. this.frameName = this._onUpFrameName;
  24899. }
  24900. else if (this._onUpFrameID != null)
  24901. {
  24902. this.frame = this._onUpFrameID;
  24903. }
  24904. }
  24905. };
  24906. /**
  24907. * @author Richard Davey <rich@photonstorm.com>
  24908. * @copyright 2014 Photon Storm Ltd.
  24909. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  24910. */
  24911. /**
  24912. * Creates a new `Graphics` object.
  24913. *
  24914. * @class Phaser.Graphics
  24915. * @constructor
  24916. *
  24917. * @param {Phaser.Game} game Current game instance.
  24918. * @param {number} x - X position of the new graphics object.
  24919. * @param {number} y - Y position of the new graphics object.
  24920. */
  24921. Phaser.Graphics = function (game, x, y) {
  24922. x = x || 0;
  24923. y = y || 0;
  24924. /**
  24925. * @property {Phaser.Game} game - A reference to the currently running Game.
  24926. */
  24927. this.game = game;
  24928. /**
  24929. * @property {boolean} exists - If exists = false then the Text isn't updated by the core game loop.
  24930. * @default
  24931. */
  24932. this.exists = true;
  24933. /**
  24934. * @property {string} name - The user defined name given to this object.
  24935. * @default
  24936. */
  24937. this.name = '';
  24938. /**
  24939. * @property {number} type - The const type of this object.
  24940. * @default
  24941. */
  24942. this.type = Phaser.GRAPHICS;
  24943. /**
  24944. * @property {number} z - The z-depth value of this object within its Group (remember the World is a Group as well). No two objects in a Group can have the same z value.
  24945. */
  24946. this.z = 0;
  24947. /**
  24948. * @property {Phaser.Point} world - The world coordinates of this Sprite. This differs from the x/y coordinates which are relative to the Sprites container.
  24949. */
  24950. this.world = new Phaser.Point(x, y);
  24951. /**
  24952. * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view.
  24953. */
  24954. this.cameraOffset = new Phaser.Point();
  24955. PIXI.Graphics.call(this);
  24956. this.position.set(x, y);
  24957. /**
  24958. * A small internal cache:
  24959. * 0 = previous position.x
  24960. * 1 = previous position.y
  24961. * 2 = previous rotation
  24962. * 3 = renderID
  24963. * 4 = fresh? (0 = no, 1 = yes)
  24964. * 5 = outOfBoundsFired (0 = no, 1 = yes)
  24965. * 6 = exists (0 = no, 1 = yes)
  24966. * 7 = fixed to camera (0 = no, 1 = yes)
  24967. * @property {Array} _cache
  24968. * @private
  24969. */
  24970. this._cache = [ 0, 0, 0, 0, 1, 0, 1, 0 ];
  24971. };
  24972. Phaser.Graphics.prototype = Object.create(PIXI.Graphics.prototype);
  24973. Phaser.Graphics.prototype.constructor = Phaser.Graphics;
  24974. /**
  24975. * Automatically called by World.preUpdate.
  24976. * @method Phaser.Graphics.prototype.preUpdate
  24977. */
  24978. Phaser.Graphics.prototype.preUpdate = function () {
  24979. this._cache[0] = this.world.x;
  24980. this._cache[1] = this.world.y;
  24981. this._cache[2] = this.rotation;
  24982. if (!this.exists || !this.parent.exists)
  24983. {
  24984. this.renderOrderID = -1;
  24985. return false;
  24986. }
  24987. if (this.autoCull)
  24988. {
  24989. // Won't get rendered but will still get its transform updated
  24990. this.renderable = this.game.world.camera.screenView.intersects(this.getBounds());
  24991. }
  24992. this.world.setTo(this.game.camera.x + this.worldTransform[2], this.game.camera.y + this.worldTransform[5]);
  24993. if (this.visible)
  24994. {
  24995. this._cache[3] = this.game.stage.currentRenderOrderID++;
  24996. }
  24997. return true;
  24998. };
  24999. /**
  25000. * Override and use this function in your own custom objects to handle any update requirements you may have.
  25001. *
  25002. * @method Phaser.Graphics#update
  25003. * @memberof Phaser.Graphics
  25004. */
  25005. Phaser.Graphics.prototype.update = function() {
  25006. };
  25007. /**
  25008. * Automatically called by World.postUpdate.
  25009. * @method Phaser.Graphics.prototype.postUpdate
  25010. */
  25011. Phaser.Graphics.prototype.postUpdate = function () {
  25012. // Fixed to Camera?
  25013. if (this._cache[7] === 1)
  25014. {
  25015. this.position.x = (this.game.camera.view.x + this.cameraOffset.x) / this.game.camera.scale.x;
  25016. this.position.y = (this.game.camera.view.y + this.cameraOffset.y) / this.game.camera.scale.y;
  25017. }
  25018. };
  25019. /**
  25020. * Destroy this Graphics instance.
  25021. *
  25022. * @method Phaser.Graphics.prototype.destroy
  25023. * @param {boolean} [destroyChildren=true] - Should every child of this object have its destroy method called?
  25024. */
  25025. Phaser.Graphics.prototype.destroy = function(destroyChildren) {
  25026. if (typeof destroyChildren === 'undefined') { destroyChildren = true; }
  25027. this.clear();
  25028. if (this.parent)
  25029. {
  25030. if (this.parent instanceof Phaser.Group)
  25031. {
  25032. this.parent.remove(this);
  25033. }
  25034. else
  25035. {
  25036. this.parent.removeChild(this);
  25037. }
  25038. }
  25039. var i = this.children.length;
  25040. if (destroyChildren)
  25041. {
  25042. while (i--)
  25043. {
  25044. this.children[i].destroy(destroyChildren);
  25045. }
  25046. }
  25047. else
  25048. {
  25049. while (i--)
  25050. {
  25051. this.removeChild(this.children[i]);
  25052. }
  25053. }
  25054. this.exists = false;
  25055. this.visible = false;
  25056. this.game = null;
  25057. };
  25058. /*
  25059. * Draws a {Phaser.Polygon} or a {PIXI.Polygon} filled
  25060. *
  25061. * @method Phaser.Graphics.prototype.drawPolygon
  25062. */
  25063. Phaser.Graphics.prototype.drawPolygon = function (poly) {
  25064. this.moveTo(poly.points[0].x, poly.points[0].y);
  25065. for (var i = 1; i < poly.points.length; i += 1)
  25066. {
  25067. this.lineTo(poly.points[i].x, poly.points[i].y);
  25068. }
  25069. this.lineTo(poly.points[0].x, poly.points[0].y);
  25070. };
  25071. /**
  25072. * Indicates the rotation of the Graphics, in degrees, from its original orientation. Values from 0 to 180 represent clockwise rotation; values from 0 to -180 represent counterclockwise rotation.
  25073. * Values outside this range are added to or subtracted from 360 to obtain a value within the range. For example, the statement player.angle = 450 is the same as player.angle = 90.
  25074. * If you wish to work in radians instead of degrees use the property Sprite.rotation instead.
  25075. * @name Phaser.Graphics#angle
  25076. * @property {number} angle - Gets or sets the angle of rotation in degrees.
  25077. */
  25078. Object.defineProperty(Phaser.Graphics.prototype, 'angle', {
  25079. get: function() {
  25080. return Phaser.Math.radToDeg(this.rotation);
  25081. },
  25082. set: function(value) {
  25083. this.rotation = Phaser.Math.degToRad(value);
  25084. }
  25085. });
  25086. /**
  25087. * An Graphics that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in Graphics.cameraOffset.
  25088. * Note that the cameraOffset values are in addition to any parent in the display list.
  25089. * So if this Graphics was in a Group that has x: 200, then this will be added to the cameraOffset.x
  25090. *
  25091. * @name Phaser.Graphics#fixedToCamera
  25092. * @property {boolean} fixedToCamera - Set to true to fix this Graphics to the Camera at its current world coordinates.
  25093. */
  25094. Object.defineProperty(Phaser.Graphics.prototype, "fixedToCamera", {
  25095. get: function () {
  25096. return !!this._cache[7];
  25097. },
  25098. set: function (value) {
  25099. if (value)
  25100. {
  25101. this._cache[7] = 1;
  25102. this.cameraOffset.set(this.x, this.y);
  25103. }
  25104. else
  25105. {
  25106. this._cache[7] = 0;
  25107. }
  25108. }
  25109. });
  25110. /**
  25111. * @author Richard Davey <rich@photonstorm.com>
  25112. * @copyright 2014 Photon Storm Ltd.
  25113. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  25114. */
  25115. /**
  25116. * A RenderTexture is a special texture that allows any displayObject to be rendered to it.
  25117. * @class Phaser.RenderTexture
  25118. * @constructor
  25119. * @param {Phaser.Game} game - Current game instance.
  25120. * @param {string} key - Internal Phaser reference key for the render texture.
  25121. * @param {number} [width=100] - The width of the render texture.
  25122. * @param {number} [height=100] - The height of the render texture.
  25123. */
  25124. Phaser.RenderTexture = function (game, width, height, key) {
  25125. /**
  25126. * @property {Phaser.Game} game - A reference to the currently running game.
  25127. */
  25128. this.game = game;
  25129. /**
  25130. * @property {string} key - The key of the RenderTexture in the Cache, if stored there.
  25131. */
  25132. this.key = key;
  25133. /**
  25134. * @property {number} type - Base Phaser object type.
  25135. */
  25136. this.type = Phaser.RENDERTEXTURE;
  25137. /**
  25138. * @property {Phaser.Point} _temp - Internal var.
  25139. * @private
  25140. */
  25141. this._temp = new Phaser.Point();
  25142. PIXI.RenderTexture.call(this, width, height);
  25143. };
  25144. Phaser.RenderTexture.prototype = Object.create(PIXI.RenderTexture.prototype);
  25145. Phaser.RenderTexture.prototype.constructor = Phaser.RenderTexture;
  25146. /**
  25147. * This function will draw the display object to the texture.
  25148. *
  25149. * @method Phaser.RenderTexture.prototype.renderXY
  25150. * @param {Phaser.Sprite|Phaser.Image|Phaser.Text|Phaser.BitmapText|Phaser.Group} displayObject The display object to render to this texture.
  25151. * @param {number} x - The x position to render the object at.
  25152. * @param {number} y - The y position to render the object at.
  25153. * @param {boolean} clear - If true the texture will be cleared before the display object is drawn.
  25154. */
  25155. Phaser.RenderTexture.prototype.renderXY = function (displayObject, x, y, clear) {
  25156. this._temp.set(x, y);
  25157. this.render(displayObject, this._temp, clear);
  25158. };
  25159. // Documentation stubs
  25160. /**
  25161. * This function will draw the display object to the texture.
  25162. *
  25163. * @method Phaser.RenderTexture.prototype.render
  25164. * @param {Phaser.Sprite|Phaser.Image|Phaser.Text|Phaser.BitmapText|Phaser.Group} displayObject The display object to render to this texture.
  25165. * @param {Phaser.Point} position - A Point object containing the position to render the display object at.
  25166. * @param {boolean} clear - If true the texture will be cleared before the display object is drawn.
  25167. */
  25168. /**
  25169. * Resize this RenderTexture to the given width and height.
  25170. *
  25171. * @method Phaser.RenderTexture.prototype.resize
  25172. * @param {number} width - The new width of the RenderTexture.
  25173. * @param {number} height - The new height of the RenderTexture.
  25174. */
  25175. /**
  25176. * @author Richard Davey <rich@photonstorm.com>
  25177. * @copyright 2014 Photon Storm Ltd.
  25178. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  25179. */
  25180. /**
  25181. * Phaser SpriteBatch constructor.
  25182. *
  25183. * @classdesc The SpriteBatch class is a really fast version of the DisplayObjectContainer built solely for speed, so use when you need a lot of sprites or particles.
  25184. * @class Phaser.SpriteBatch
  25185. * @extends Phaser.Group
  25186. * @constructor
  25187. * @param {Phaser.Game} game - A reference to the currently running game.
  25188. * @param {Phaser.Group|Phaser.Sprite} parent - The parent Group, DisplayObject or DisplayObjectContainer that this Group will be added to. If undefined or null it will use game.world.
  25189. * @param {string} [name=group] - A name for this Group. Not used internally but useful for debugging.
  25190. * @param {boolean} [addToStage=false] - If set to true this Group will be added directly to the Game.Stage instead of Game.World.
  25191. */
  25192. Phaser.SpriteBatch = function (game, parent, name, addToStage) {
  25193. PIXI.SpriteBatch.call(this);
  25194. Phaser.Group.call(this, game, parent, name, addToStage);
  25195. /**
  25196. * @property {number} type - Internal Phaser Type value.
  25197. * @protected
  25198. */
  25199. this.type = Phaser.SPRITEBATCH;
  25200. };
  25201. Phaser.SpriteBatch.prototype = Phaser.Utils.extend(true, Phaser.SpriteBatch.prototype, Phaser.Group.prototype, PIXI.SpriteBatch.prototype);
  25202. Phaser.SpriteBatch.prototype.constructor = Phaser.SpriteBatch;
  25203. /**
  25204. * @author Richard Davey <rich@photonstorm.com>
  25205. * @copyright 2014 Photon Storm Ltd.
  25206. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  25207. */
  25208. /**
  25209. * @class Phaser.RetroFont
  25210. * @extends Phaser.RenderTexture
  25211. * @constructor
  25212. * @param {Phaser.Game} game - Current game instance.
  25213. * @param {string} key - The font set graphic set as stored in the Game.Cache.
  25214. * @param {number} characterWidth - The width of each character in the font set.
  25215. * @param {number} characterHeight - The height of each character in the font set.
  25216. * @param {string} chars - The characters used in the font set, in display order. You can use the TEXT_SET consts for common font set arrangements.
  25217. * @param {number} charsPerRow - The number of characters per row in the font set.
  25218. * @param {number} [xSpacing=0] - If the characters in the font set have horizontal spacing between them set the required amount here.
  25219. * @param {number} [ySpacing=0] - If the characters in the font set have vertical spacing between them set the required amount here.
  25220. * @param {number} [xOffset=0] - If the font set doesn't start at the top left of the given image, specify the X coordinate offset here.
  25221. * @param {number} [yOffset=0] - If the font set doesn't start at the top left of the given image, specify the Y coordinate offset here.
  25222. */
  25223. Phaser.RetroFont = function (game, key, characterWidth, characterHeight, chars, charsPerRow, xSpacing, ySpacing, xOffset, yOffset) {
  25224. /**
  25225. * @property {number} characterWidth - The width of each character in the font set.
  25226. */
  25227. this.characterWidth = characterWidth;
  25228. /**
  25229. * @property {number} characterHeight - The height of each character in the font set.
  25230. */
  25231. this.characterHeight = characterHeight;
  25232. /**
  25233. * @property {number} characterSpacingX - If the characters in the font set have horizontal spacing between them set the required amount here.
  25234. */
  25235. this.characterSpacingX = xSpacing || 0;
  25236. /**
  25237. * @property {number} characterSpacingY - If the characters in the font set have vertical spacing between them set the required amount here.
  25238. */
  25239. this.characterSpacingY = ySpacing || 0;
  25240. /**
  25241. * @property {number} characterPerRow - The number of characters per row in the font set.
  25242. */
  25243. this.characterPerRow = charsPerRow;
  25244. /**
  25245. * @property {number} offsetX - If the font set doesn't start at the top left of the given image, specify the X coordinate offset here.
  25246. */
  25247. this.offsetX = xOffset || 0;
  25248. /**
  25249. * @property {number} offsetY - If the font set doesn't start at the top left of the given image, specify the Y coordinate offset here.
  25250. */
  25251. this.offsetY = yOffset || 0;
  25252. /**
  25253. * @property {string} align - Alignment of the text when multiLine = true or a fixedWidth is set. Set to RetroFont.ALIGN_LEFT (default), RetroFont.ALIGN_RIGHT or RetroFont.ALIGN_CENTER.
  25254. */
  25255. this.align = "left";
  25256. /**
  25257. * @property {boolean} multiLine - If set to true all carriage-returns in text will form new lines (see align). If false the font will only contain one single line of text (the default)
  25258. * @default
  25259. */
  25260. this.multiLine = false;
  25261. /**
  25262. * @property {boolean} autoUpperCase - Automatically convert any text to upper case. Lots of old bitmap fonts only contain upper-case characters, so the default is true.
  25263. * @default
  25264. */
  25265. this.autoUpperCase = true;
  25266. /**
  25267. * @property {number} customSpacingX - Adds horizontal spacing between each character of the font, in pixels.
  25268. * @default
  25269. */
  25270. this.customSpacingX = 0;
  25271. /**
  25272. * @property {number} customSpacingY - Adds vertical spacing between each line of multi-line text, set in pixels.
  25273. * @default
  25274. */
  25275. this.customSpacingY = 0;
  25276. /**
  25277. * If you need this RetroFont image to have a fixed width you can set the width in this value.
  25278. * If text is wider than the width specified it will be cropped off.
  25279. * @property {number} fixedWidth
  25280. */
  25281. this.fixedWidth = 0;
  25282. /**
  25283. * @property {HTMLImage} fontSet - A reference to the image stored in the Game.Cache that contains the font.
  25284. */
  25285. this.fontSet = game.cache.getImage(key);
  25286. /**
  25287. * @property {string} _text - The text of the font image.
  25288. * @private
  25289. */
  25290. this._text = '';
  25291. /**
  25292. * @property {array} grabData - An array of rects for faster character pasting.
  25293. * @private
  25294. */
  25295. this.grabData = [];
  25296. // Now generate our rects for faster copying later on
  25297. var currentX = this.offsetX;
  25298. var currentY = this.offsetY;
  25299. var r = 0;
  25300. var data = new Phaser.FrameData();
  25301. for (var c = 0; c < chars.length; c++)
  25302. {
  25303. var uuid = game.rnd.uuid();
  25304. var frame = data.addFrame(new Phaser.Frame(c, currentX, currentY, this.characterWidth, this.characterHeight, '', uuid));
  25305. this.grabData[chars.charCodeAt(c)] = frame.index;
  25306. PIXI.TextureCache[uuid] = new PIXI.Texture(PIXI.BaseTextureCache[key], {
  25307. x: currentX,
  25308. y: currentY,
  25309. width: this.characterWidth,
  25310. height: this.characterHeight
  25311. });
  25312. r++;
  25313. if (r == this.characterPerRow)
  25314. {
  25315. r = 0;
  25316. currentX = this.offsetX;
  25317. currentY += this.characterHeight + this.characterSpacingY;
  25318. }
  25319. else
  25320. {
  25321. currentX += this.characterWidth + this.characterSpacingX;
  25322. }
  25323. }
  25324. game.cache.updateFrameData(key, data);
  25325. this.stamp = new Phaser.Image(game, 0, 0, key, 0);
  25326. Phaser.RenderTexture.call(this, game);
  25327. /**
  25328. * @property {number} type - Base Phaser object type.
  25329. */
  25330. this.type = Phaser.RETROFONT;
  25331. };
  25332. Phaser.RetroFont.prototype = Object.create(Phaser.RenderTexture.prototype);
  25333. Phaser.RetroFont.prototype.constructor = Phaser.RetroFont;
  25334. /**
  25335. * Align each line of multi-line text to the left.
  25336. * @constant
  25337. * @type {string}
  25338. */
  25339. Phaser.RetroFont.ALIGN_LEFT = "left";
  25340. /**
  25341. * Align each line of multi-line text to the right.
  25342. * @constant
  25343. * @type {string}
  25344. */
  25345. Phaser.RetroFont.ALIGN_RIGHT = "right";
  25346. /**
  25347. * Align each line of multi-line text in the center.
  25348. * @constant
  25349. * @type {string}
  25350. */
  25351. Phaser.RetroFont.ALIGN_CENTER = "center";
  25352. /**
  25353. * Text Set 1 = !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
  25354. * @constant
  25355. * @type {string}
  25356. */
  25357. Phaser.RetroFont.TEXT_SET1 = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
  25358. /**
  25359. * Text Set 2 = !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
  25360. * @constant
  25361. * @type {string}
  25362. */
  25363. Phaser.RetroFont.TEXT_SET2 = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  25364. /**
  25365. * Text Set 3 = ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
  25366. * @constant
  25367. * @type {string}
  25368. */
  25369. Phaser.RetroFont.TEXT_SET3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
  25370. /**
  25371. * Text Set 4 = ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789
  25372. * @constant
  25373. * @type {string}
  25374. */
  25375. Phaser.RetroFont.TEXT_SET4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789";
  25376. /**
  25377. * Text Set 5 = ABCDEFGHIJKLMNOPQRSTUVWXYZ.,/() '!?-*:0123456789
  25378. * @constant
  25379. * @type {string}
  25380. */
  25381. Phaser.RetroFont.TEXT_SET5 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,/() '!?-*:0123456789";
  25382. /**
  25383. * Text Set 6 = ABCDEFGHIJKLMNOPQRSTUVWXYZ!?:;0123456789\"(),-.'
  25384. * @constant
  25385. * @type {string}
  25386. */
  25387. Phaser.RetroFont.TEXT_SET6 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!?:;0123456789\"(),-.' ";
  25388. /**
  25389. * Text Set 7 = AGMSY+:4BHNTZ!;5CIOU.?06DJPV,(17EKQW\")28FLRX-'39
  25390. * @constant
  25391. * @type {string}
  25392. */
  25393. Phaser.RetroFont.TEXT_SET7 = "AGMSY+:4BHNTZ!;5CIOU.?06DJPV,(17EKQW\")28FLRX-'39";
  25394. /**
  25395. * Text Set 8 = 0123456789 .ABCDEFGHIJKLMNOPQRSTUVWXYZ
  25396. * @constant
  25397. * @type {string}
  25398. */
  25399. Phaser.RetroFont.TEXT_SET8 = "0123456789 .ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  25400. /**
  25401. * Text Set 9 = ABCDEFGHIJKLMNOPQRSTUVWXYZ()-0123456789.:,'\"?!
  25402. * @constant
  25403. * @type {string}
  25404. */
  25405. Phaser.RetroFont.TEXT_SET9 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ()-0123456789.:,'\"?!";
  25406. /**
  25407. * Text Set 10 = ABCDEFGHIJKLMNOPQRSTUVWXYZ
  25408. * @constant
  25409. * @type {string}
  25410. */
  25411. Phaser.RetroFont.TEXT_SET10 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  25412. /**
  25413. * Text Set 11 = ABCDEFGHIJKLMNOPQRSTUVWXYZ.,\"-+!?()':;0123456789
  25414. * @constant
  25415. * @type {string}
  25416. */
  25417. Phaser.RetroFont.TEXT_SET11 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,\"-+!?()':;0123456789";
  25418. /**
  25419. * If you need this FlxSprite to have a fixed width and custom alignment you can set the width here.<br>
  25420. * If text is wider than the width specified it will be cropped off.
  25421. *
  25422. * @method Phaser.RetroFont#setFixedWidth
  25423. * @memberof Phaser.RetroFont
  25424. * @param {number} width - Width in pixels of this RetroFont. Set to zero to disable and re-enable automatic resizing.
  25425. * @param {string} [lineAlignment='left'] - Align the text within this width. Set to RetroFont.ALIGN_LEFT (default), RetroFont.ALIGN_RIGHT or RetroFont.ALIGN_CENTER.
  25426. */
  25427. Phaser.RetroFont.prototype.setFixedWidth = function (width, lineAlignment) {
  25428. if (typeof lineAlignment === 'undefined') { lineAlignment = 'left'; }
  25429. this.fixedWidth = width;
  25430. this.align = lineAlignment;
  25431. };
  25432. /**
  25433. * A helper function that quickly sets lots of variables at once, and then updates the text.
  25434. *
  25435. * @method Phaser.RetroFont#setText
  25436. * @memberof Phaser.RetroFont
  25437. * @param {string} content - The text of this sprite.
  25438. * @param {boolean} [multiLine=false] - Set to true if you want to support carriage-returns in the text and create a multi-line sprite instead of a single line.
  25439. * @param {number} [characterSpacing=0] - To add horizontal spacing between each character specify the amount in pixels.
  25440. * @param {number} [lineSpacing=0] - To add vertical spacing between each line of text, set the amount in pixels.
  25441. * @param {string} [lineAlignment='left'] - Align each line of multi-line text. Set to RetroFont.ALIGN_LEFT, RetroFont.ALIGN_RIGHT or RetroFont.ALIGN_CENTER.
  25442. * @param {boolean} [allowLowerCase=false] - Lots of bitmap font sets only include upper-case characters, if yours needs to support lower case then set this to true.
  25443. */
  25444. Phaser.RetroFont.prototype.setText = function (content, multiLine, characterSpacing, lineSpacing, lineAlignment, allowLowerCase) {
  25445. this.multiLine = multiLine || false;
  25446. this.customSpacingX = characterSpacing || 0;
  25447. this.customSpacingY = lineSpacing || 0;
  25448. this.align = lineAlignment || 'left';
  25449. if (allowLowerCase)
  25450. {
  25451. this.autoUpperCase = false;
  25452. }
  25453. else
  25454. {
  25455. this.autoUpperCase = true;
  25456. }
  25457. if (content.length > 0)
  25458. {
  25459. this.text = content;
  25460. }
  25461. };
  25462. /**
  25463. * Over rides the default PIXI.RenderTexture resize event as we need our baseTexture resized as well.
  25464. *
  25465. * @method Phaser.RetroFont#resize
  25466. * @memberof Phaser.RetroFont
  25467. */
  25468. Phaser.RetroFont.prototype.resize = function (width, height) {
  25469. this.width = width;
  25470. this.height = height;
  25471. this.frame.width = this.width;
  25472. this.frame.height = this.height;
  25473. this.baseTexture.width = this.width;
  25474. this.baseTexture.height = this.height;
  25475. if (this.renderer.type === PIXI.WEBGL_RENDERER)
  25476. {
  25477. this.projection.x = this.width / 2;
  25478. this.projection.y = -this.height / 2;
  25479. var gl = this.renderer.gl;
  25480. gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTextures[gl.id]);
  25481. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  25482. }
  25483. else
  25484. {
  25485. this.textureBuffer.resize(this.width, this.height);
  25486. }
  25487. PIXI.Texture.frameUpdates.push(this);
  25488. };
  25489. /**
  25490. * Updates the BitmapData of the Sprite with the text
  25491. *
  25492. * @method Phaser.RetroFont#buildRetroFontText
  25493. * @memberof Phaser.RetroFont
  25494. */
  25495. Phaser.RetroFont.prototype.buildRetroFontText = function () {
  25496. var cx = 0;
  25497. var cy = 0;
  25498. if (this.multiLine)
  25499. {
  25500. var lines = this._text.split("\n");
  25501. if (this.fixedWidth > 0)
  25502. {
  25503. this.resize(this.fixedWidth, (lines.length * (this.characterHeight + this.customSpacingY)) - this.customSpacingY);
  25504. }
  25505. else
  25506. {
  25507. this.resize(this.getLongestLine() * (this.characterWidth + this.customSpacingX), (lines.length * (this.characterHeight + this.customSpacingY)) - this.customSpacingY);
  25508. }
  25509. this.textureBuffer.clear();
  25510. // Loop through each line of text
  25511. for (var i = 0; i < lines.length; i++)
  25512. {
  25513. // This line of text is held in lines[i] - need to work out the alignment
  25514. switch (this.align)
  25515. {
  25516. case Phaser.RetroFont.ALIGN_LEFT:
  25517. cx = 0;
  25518. break;
  25519. case Phaser.RetroFont.ALIGN_RIGHT:
  25520. cx = this.width - (lines[i].length * (this.characterWidth + this.customSpacingX));
  25521. break;
  25522. case Phaser.RetroFont.ALIGN_CENTER:
  25523. cx = (this.width / 2) - ((lines[i].length * (this.characterWidth + this.customSpacingX)) / 2);
  25524. cx += this.customSpacingX / 2;
  25525. break;
  25526. }
  25527. // Sanity checks
  25528. if (cx < 0)
  25529. {
  25530. cx = 0;
  25531. }
  25532. this.pasteLine(lines[i], cx, cy, this.customSpacingX);
  25533. cy += this.characterHeight + this.customSpacingY;
  25534. }
  25535. }
  25536. else
  25537. {
  25538. if (this.fixedWidth > 0)
  25539. {
  25540. this.resize(this.fixedWidth, this.characterHeight);
  25541. }
  25542. else
  25543. {
  25544. this.resize(this._text.length * (this.characterWidth + this.customSpacingX), this.characterHeight);
  25545. }
  25546. this.textureBuffer.clear();
  25547. switch (this.align)
  25548. {
  25549. case Phaser.RetroFont.ALIGN_LEFT:
  25550. cx = 0;
  25551. break;
  25552. case Phaser.RetroFont.ALIGN_RIGHT:
  25553. cx = this.width - (this._text.length * (this.characterWidth + this.customSpacingX));
  25554. break;
  25555. case Phaser.RetroFont.ALIGN_CENTER:
  25556. cx = (this.width / 2) - ((this._text.length * (this.characterWidth + this.customSpacingX)) / 2);
  25557. cx += this.customSpacingX / 2;
  25558. break;
  25559. }
  25560. this.pasteLine(this._text, cx, 0, this.customSpacingX);
  25561. }
  25562. };
  25563. /**
  25564. * Internal function that takes a single line of text (2nd parameter) and pastes it into the BitmapData at the given coordinates.
  25565. * Used by getLine and getMultiLine
  25566. *
  25567. * @method Phaser.RetroFont#buildRetroFontText
  25568. * @memberof Phaser.RetroFont
  25569. * @param {string} line - The single line of text to paste.
  25570. * @param {number} x - The x coordinate.
  25571. * @param {number} y - The y coordinate.
  25572. * @param {number} customSpacingX - Custom X spacing.
  25573. */
  25574. Phaser.RetroFont.prototype.pasteLine = function (line, x, y, customSpacingX) {
  25575. var p = new Phaser.Point();
  25576. for (var c = 0; c < line.length; c++)
  25577. {
  25578. // If it's a space then there is no point copying, so leave a blank space
  25579. if (line.charAt(c) == " ")
  25580. {
  25581. x += this.characterWidth + customSpacingX;
  25582. }
  25583. else
  25584. {
  25585. // If the character doesn't exist in the font then we don't want a blank space, we just want to skip it
  25586. if (this.grabData[line.charCodeAt(c)] >= 0)
  25587. {
  25588. this.stamp.frame = this.grabData[line.charCodeAt(c)];
  25589. p.set(x, y);
  25590. this.render(this.stamp, p, false);
  25591. x += this.characterWidth + customSpacingX;
  25592. if (x > this.width)
  25593. {
  25594. break;
  25595. }
  25596. }
  25597. }
  25598. }
  25599. };
  25600. /**
  25601. * Works out the longest line of text in _text and returns its length
  25602. *
  25603. * @method Phaser.RetroFont#getLongestLine
  25604. * @memberof Phaser.RetroFont
  25605. * @return {number} The length of the longest line of text.
  25606. */
  25607. Phaser.RetroFont.prototype.getLongestLine = function () {
  25608. var longestLine = 0;
  25609. if (this._text.length > 0)
  25610. {
  25611. var lines = this._text.split("\n");
  25612. for (var i = 0; i < lines.length; i++)
  25613. {
  25614. if (lines[i].length > longestLine)
  25615. {
  25616. longestLine = lines[i].length;
  25617. }
  25618. }
  25619. }
  25620. return longestLine;
  25621. };
  25622. /**
  25623. * Internal helper function that removes all unsupported characters from the _text String, leaving only characters contained in the font set.
  25624. *
  25625. * @method Phaser.RetroFont#removeUnsupportedCharacters
  25626. * @memberof Phaser.RetroFont
  25627. * @protected
  25628. * @param {boolean} [stripCR=true] - Should it strip carriage returns as well?
  25629. * @return {string} A clean version of the string.
  25630. */
  25631. Phaser.RetroFont.prototype.removeUnsupportedCharacters = function (stripCR) {
  25632. var newString = "";
  25633. for (var c = 0; c < this._text.length; c++)
  25634. {
  25635. var aChar = this._text[c];
  25636. var code = aChar.charCodeAt(0);
  25637. if (this.grabData[code] >= 0 || (!stripCR && aChar === "\n"))
  25638. {
  25639. newString = newString.concat(aChar);
  25640. }
  25641. }
  25642. return newString;
  25643. };
  25644. /**
  25645. * @name Phaser.BitmapText#text
  25646. * @property {string} text - Set this value to update the text in this sprite. Carriage returns are automatically stripped out if multiLine is false. Text is converted to upper case if autoUpperCase is true.
  25647. */
  25648. Object.defineProperty(Phaser.RetroFont.prototype, "text", {
  25649. get: function () {
  25650. return this._text;
  25651. },
  25652. set: function (value) {
  25653. var newText;
  25654. if (this.autoUpperCase)
  25655. {
  25656. newText = value.toUpperCase();
  25657. }
  25658. else
  25659. {
  25660. newText = value;
  25661. }
  25662. if (newText !== this._text)
  25663. {
  25664. this._text = newText;
  25665. this.removeUnsupportedCharacters(this.multiLine);
  25666. this.buildRetroFontText();
  25667. }
  25668. }
  25669. });
  25670. /**
  25671. * @author Richard Davey <rich@photonstorm.com>
  25672. * @copyright 2014 Photon Storm Ltd.
  25673. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  25674. */
  25675. /**
  25676. * @class Phaser.Particle
  25677. *
  25678. * @classdesc Create a new `Particle` object. Particles are extended Sprites that are emitted by a particle emitter such as Phaser.Particles.Arcade.Emitter.
  25679. *
  25680. * @constructor
  25681. * @extends Phaser.Sprite
  25682. * @param {Phaser.Game} game - A reference to the currently running game.
  25683. * @param {number} x - The x coordinate (in world space) to position the Particle at.
  25684. * @param {number} y - The y coordinate (in world space) to position the Particle at.
  25685. * @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Particle during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
  25686. * @param {string|number} frame - If this Particle is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
  25687. */
  25688. Phaser.Particle = function (game, x, y, key, frame) {
  25689. Phaser.Sprite.call(this, game, x, y, key, frame);
  25690. /**
  25691. * @property {boolean} autoScale - If this Particle automatically scales this is set to true by Particle.setScaleData.
  25692. * @protected
  25693. */
  25694. this.autoScale = false;
  25695. /**
  25696. * @property {array} scaleData - A reference to the scaleData array owned by the Emitter that emitted this Particle.
  25697. * @protected
  25698. */
  25699. this.scaleData = null;
  25700. /**
  25701. * @property {number} _s - Internal cache var for tracking auto scale.
  25702. * @private
  25703. */
  25704. this._s = 0;
  25705. /**
  25706. * @property {boolean} autoAlpha - If this Particle automatically changes alpha this is set to true by Particle.setAlphaData.
  25707. * @protected
  25708. */
  25709. this.autoAlpha = false;
  25710. /**
  25711. * @property {array} alphaData - A reference to the alphaData array owned by the Emitter that emitted this Particle.
  25712. * @protected
  25713. */
  25714. this.alphaData = null;
  25715. /**
  25716. * @property {number} _a - Internal cache var for tracking auto alpha.
  25717. * @private
  25718. */
  25719. this._a = 0;
  25720. };
  25721. Phaser.Particle.prototype = Object.create(Phaser.Sprite.prototype);
  25722. Phaser.Particle.prototype.constructor = Phaser.Particle;
  25723. /**
  25724. * Updates the Particle scale or alpha if autoScale and autoAlpha are set.
  25725. *
  25726. * @method Phaser.Particle#update
  25727. * @memberof Phaser.Particle
  25728. */
  25729. Phaser.Particle.prototype.update = function() {
  25730. if (this.autoScale)
  25731. {
  25732. this._s--;
  25733. if (this._s)
  25734. {
  25735. this.scale.set(this.scaleData[this._s].x, this.scaleData[this._s].y);
  25736. }
  25737. else
  25738. {
  25739. this.autoScale = false;
  25740. }
  25741. }
  25742. if (this.autoAlpha)
  25743. {
  25744. this._a--;
  25745. if (this._a)
  25746. {
  25747. this.alpha = this.alphaData[this._a].v;
  25748. }
  25749. else
  25750. {
  25751. this.autoAlpha = false;
  25752. }
  25753. }
  25754. };
  25755. /**
  25756. * Called by the Emitter when this particle is emitted. Left empty for you to over-ride as required.
  25757. *
  25758. * @method Phaser.Particle#onEmit
  25759. * @memberof Phaser.Particle
  25760. */
  25761. Phaser.Particle.prototype.onEmit = function() {
  25762. };
  25763. /**
  25764. * Called by the Emitter if autoAlpha has been enabled. Passes over the alpha ease data and resets the alpha counter.
  25765. *
  25766. * @method Phaser.Particle#setAlphaData
  25767. * @memberof Phaser.Particle
  25768. */
  25769. Phaser.Particle.prototype.setAlphaData = function(data) {
  25770. this.alphaData = data;
  25771. this._a = data.length - 1;
  25772. this.alpha = this.alphaData[this._a].v;
  25773. this.autoAlpha = true;
  25774. };
  25775. /**
  25776. * Called by the Emitter if autoScale has been enabled. Passes over the scale ease data and resets the scale counter.
  25777. *
  25778. * @method Phaser.Particle#setScaleData
  25779. * @memberof Phaser.Particle
  25780. */
  25781. Phaser.Particle.prototype.setScaleData = function(data) {
  25782. this.scaleData = data;
  25783. this._s = data.length - 1;
  25784. this.scale.set(this.scaleData[this._s].x, this.scaleData[this._s].y);
  25785. this.autoScale = true;
  25786. };
  25787. /**
  25788. * Resets the Particle. This places the Particle at the given x/y world coordinates and then
  25789. * sets alive, exists, visible and renderable all to true. Also resets the outOfBounds state and health values.
  25790. * If the Particle has a physics body that too is reset.
  25791. *
  25792. * @method Phaser.Particle#reset
  25793. * @memberof Phaser.Particle
  25794. * @param {number} x - The x coordinate (in world space) to position the Particle at.
  25795. * @param {number} y - The y coordinate (in world space) to position the Particle at.
  25796. * @param {number} [health=1] - The health to give the Particle.
  25797. * @return (Phaser.Particle) This instance.
  25798. */
  25799. Phaser.Particle.prototype.reset = function(x, y, health) {
  25800. if (typeof health === 'undefined') { health = 1; }
  25801. this.world.setTo(x, y);
  25802. this.position.x = x;
  25803. this.position.y = y;
  25804. this.alive = true;
  25805. this.exists = true;
  25806. this.visible = true;
  25807. this.renderable = true;
  25808. this._outOfBoundsFired = false;
  25809. this.health = health;
  25810. if (this.body)
  25811. {
  25812. this.body.reset(x, y, false, false);
  25813. }
  25814. this._cache[4] = 1;
  25815. this.alpha = 1;
  25816. this.scale.set(1);
  25817. this.autoScale = false;
  25818. this.autoAlpha = false;
  25819. return this;
  25820. };
  25821. /**
  25822. * @author Richard Davey <rich@photonstorm.com>
  25823. * @copyright 2014 Photon Storm Ltd.
  25824. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  25825. */
  25826. /**
  25827. * The Canvas class handles everything related to creating the `canvas` DOM tag that Phaser will use, including styles, offset and aspect ratio.
  25828. *
  25829. * @class Phaser.Canvas
  25830. * @static
  25831. */
  25832. Phaser.Canvas = {
  25833. /**
  25834. * Creates a `canvas` DOM element. The element is not automatically added to the document.
  25835. *
  25836. * @method Phaser.Canvas.create
  25837. * @param {number} [width=256] - The width of the canvas element.
  25838. * @param {number} [height=256] - The height of the canvas element..
  25839. * @param {string} [id=''] - If given this will be set as the ID of the canvas element, otherwise no ID will be set.
  25840. * @param {boolean} [noCocoon=false] - CocoonJS only allows 1 screencanvas object, which should be your game. If you need to create another canvas (i.e. for a texture) set this to 'true'.
  25841. * @return {HTMLCanvasElement} The newly created canvas element.
  25842. */
  25843. create: function (width, height, id, noCocoon) {
  25844. if (typeof noCocoon === 'undefined') { noCocoon = false; }
  25845. width = width || 256;
  25846. height = height || 256;
  25847. if (noCocoon)
  25848. {
  25849. var canvas = document.createElement('canvas');
  25850. }
  25851. else
  25852. {
  25853. var canvas = document.createElement(navigator.isCocoonJS ? 'screencanvas' : 'canvas');
  25854. }
  25855. if (typeof id === 'string' && id !== '')
  25856. {
  25857. canvas.id = id;
  25858. }
  25859. canvas.width = width;
  25860. canvas.height = height;
  25861. canvas.style.display = 'block';
  25862. return canvas;
  25863. },
  25864. /**
  25865. * Get the DOM offset values of any given element
  25866. * @method Phaser.Canvas.getOffset
  25867. * @param {HTMLElement} element - The targeted element that we want to retrieve the offset.
  25868. * @param {Phaser.Point} [point] - The point we want to take the x/y values of the offset.
  25869. * @return {Phaser.Point} - A point objet with the offsetX and Y as its properties.
  25870. */
  25871. getOffset: function (element, point) {
  25872. point = point || new Phaser.Point();
  25873. var box = element.getBoundingClientRect();
  25874. var clientTop = element.clientTop || document.body.clientTop || 0;
  25875. var clientLeft = element.clientLeft || document.body.clientLeft || 0;
  25876. // Without this check Chrome is now throwing console warnings about strict vs. quirks :(
  25877. var scrollTop = 0;
  25878. var scrollLeft = 0;
  25879. if (document.compatMode === 'CSS1Compat')
  25880. {
  25881. scrollTop = window.pageYOffset || document.documentElement.scrollTop || element.scrollTop || 0;
  25882. scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || element.scrollLeft || 0;
  25883. }
  25884. else
  25885. {
  25886. scrollTop = window.pageYOffset || document.body.scrollTop || element.scrollTop || 0;
  25887. scrollLeft = window.pageXOffset || document.body.scrollLeft || element.scrollLeft || 0;
  25888. }
  25889. point.x = box.left + scrollLeft - clientLeft;
  25890. point.y = box.top + scrollTop - clientTop;
  25891. return point;
  25892. },
  25893. /**
  25894. * Returns the aspect ratio of the given canvas.
  25895. *
  25896. * @method Phaser.Canvas.getAspectRatio
  25897. * @param {HTMLCanvasElement} canvas - The canvas to get the aspect ratio from.
  25898. * @return {number} The ratio between canvas' width and height.
  25899. */
  25900. getAspectRatio: function (canvas) {
  25901. return canvas.width / canvas.height;
  25902. },
  25903. /**
  25904. * Sets the background color behind the canvas. This changes the canvas style property.
  25905. *
  25906. * @method Phaser.Canvas.setBackgroundColor
  25907. * @param {HTMLCanvasElement} canvas - The canvas to set the background color on.
  25908. * @param {string} [color] - The color to set. Can be in the format 'rgb(r,g,b)', or '#RRGGBB' or any valid CSS color.
  25909. * @return {HTMLCanvasElement} Returns the source canvas.
  25910. */
  25911. setBackgroundColor: function (canvas, color) {
  25912. color = color || 'rgb(0,0,0)';
  25913. canvas.style.backgroundColor = color;
  25914. return canvas;
  25915. },
  25916. /**
  25917. * Sets the touch-action property on the canvas style. Can be used to disable default browser touch actions.
  25918. *
  25919. * @method Phaser.Canvas.setTouchAction
  25920. * @param {HTMLCanvasElement} canvas - The canvas to set the touch action on.
  25921. * @param {String} [value] - The touch action to set. Defaults to 'none'.
  25922. * @return {HTMLCanvasElement} The source canvas.
  25923. */
  25924. setTouchAction: function (canvas, value) {
  25925. value = value || 'none';
  25926. canvas.style.msTouchAction = value;
  25927. canvas.style['ms-touch-action'] = value;
  25928. canvas.style['touch-action'] = value;
  25929. return canvas;
  25930. },
  25931. /**
  25932. * Sets the user-select property on the canvas style. Can be used to disable default browser selection actions.
  25933. *
  25934. * @method Phaser.Canvas.setUserSelect
  25935. * @param {HTMLCanvasElement} canvas - The canvas to set the touch action on.
  25936. * @param {String} [value] - The touch action to set. Defaults to 'none'.
  25937. * @return {HTMLCanvasElement} The source canvas.
  25938. */
  25939. setUserSelect: function (canvas, value) {
  25940. value = value || 'none';
  25941. canvas.style['-webkit-touch-callout'] = value;
  25942. canvas.style['-webkit-user-select'] = value;
  25943. canvas.style['-khtml-user-select'] = value;
  25944. canvas.style['-moz-user-select'] = value;
  25945. canvas.style['-ms-user-select'] = value;
  25946. canvas.style['user-select'] = value;
  25947. canvas.style['-webkit-tap-highlight-color'] = 'rgba(0, 0, 0, 0)';
  25948. return canvas;
  25949. },
  25950. /**
  25951. * Adds the given canvas element to the DOM. The canvas will be added as a child of the given parent.
  25952. * If no parent is given it will be added as a child of the document.body.
  25953. *
  25954. * @method Phaser.Canvas.addToDOM
  25955. * @param {HTMLCanvasElement} canvas - The canvas to set the touch action on.
  25956. * @param {string|HTMLElement} parent - The DOM element to add the canvas to.
  25957. * @param {boolean} [overflowHidden=true] - If set to true it will add the overflow='hidden' style to the parent DOM element.
  25958. * @return {HTMLCanvasElement} Returns the source canvas.
  25959. */
  25960. addToDOM: function (canvas, parent, overflowHidden) {
  25961. var target;
  25962. if (typeof overflowHidden === 'undefined') { overflowHidden = true; }
  25963. if (parent)
  25964. {
  25965. if (typeof parent === 'string')
  25966. {
  25967. // hopefully an element ID
  25968. target = document.getElementById(parent);
  25969. }
  25970. else if (typeof parent === 'object' && parent.nodeType === 1)
  25971. {
  25972. // quick test for a HTMLelement
  25973. target = parent;
  25974. }
  25975. }
  25976. // Fallback, covers an invalid ID and a non HTMLelement object
  25977. if (!target)
  25978. {
  25979. target = document.body;
  25980. }
  25981. if (overflowHidden && target.style)
  25982. {
  25983. target.style.overflow = 'hidden';
  25984. }
  25985. target.appendChild(canvas);
  25986. return canvas;
  25987. },
  25988. /**
  25989. * Sets the transform of the given canvas to the matrix values provided.
  25990. *
  25991. * @method Phaser.Canvas.setTransform
  25992. * @param {CanvasRenderingContext2D} context - The context to set the transform on.
  25993. * @param {number} translateX - The value to translate horizontally by.
  25994. * @param {number} translateY - The value to translate vertically by.
  25995. * @param {number} scaleX - The value to scale horizontally by.
  25996. * @param {number} scaleY - The value to scale vertically by.
  25997. * @param {number} skewX - The value to skew horizontaly by.
  25998. * @param {number} skewY - The value to skew vertically by.
  25999. * @return {CanvasRenderingContext2D} Returns the source context.
  26000. */
  26001. setTransform: function (context, translateX, translateY, scaleX, scaleY, skewX, skewY) {
  26002. context.setTransform(scaleX, skewX, skewY, scaleY, translateX, translateY);
  26003. return context;
  26004. },
  26005. /**
  26006. * Sets the Image Smoothing property on the given context. Set to false to disable image smoothing.
  26007. * By default browsers have image smoothing enabled, which isn't always what you visually want, especially
  26008. * when using pixel art in a game. Note that this sets the property on the context itself, so that any image
  26009. * drawn to the context will be affected. This sets the property across all current browsers but support is
  26010. * patchy on earlier browsers, especially on mobile.
  26011. *
  26012. * @method Phaser.Canvas.setSmoothingEnabled
  26013. * @param {CanvasRenderingContext2D} context - The context to enable or disable the image smoothing on.
  26014. * @param {boolean} value - If set to true it will enable image smoothing, false will disable it.
  26015. * @return {CanvasRenderingContext2D} Returns the source context.
  26016. */
  26017. setSmoothingEnabled: function (context, value) {
  26018. context['imageSmoothingEnabled'] = value;
  26019. context['mozImageSmoothingEnabled'] = value;
  26020. context['oImageSmoothingEnabled'] = value;
  26021. context['webkitImageSmoothingEnabled'] = value;
  26022. context['msImageSmoothingEnabled'] = value;
  26023. return context;
  26024. },
  26025. /**
  26026. * Sets the CSS image-rendering property on the given canvas to be 'crisp' (aka 'optimize contrast on webkit').
  26027. * Note that if this doesn't given the desired result then see the setSmoothingEnabled.
  26028. *
  26029. * @method Phaser.Canvas.setImageRenderingCrisp
  26030. * @param {HTMLCanvasElement} canvas - The canvas to set image-rendering crisp on.
  26031. * @return {HTMLCanvasElement} Returns the source canvas.
  26032. */
  26033. setImageRenderingCrisp: function (canvas) {
  26034. canvas.style['image-rendering'] = 'optimizeSpeed';
  26035. canvas.style['image-rendering'] = 'crisp-edges';
  26036. canvas.style['image-rendering'] = '-moz-crisp-edges';
  26037. canvas.style['image-rendering'] = '-webkit-optimize-contrast';
  26038. canvas.style['image-rendering'] = 'optimize-contrast';
  26039. canvas.style.msInterpolationMode = 'nearest-neighbor';
  26040. return canvas;
  26041. },
  26042. /**
  26043. * Sets the CSS image-rendering property on the given canvas to be 'bicubic' (aka 'auto').
  26044. * Note that if this doesn't given the desired result then see the CanvasUtils.setSmoothingEnabled method.
  26045. *
  26046. * @method Phaser.Canvas.setImageRenderingBicubic
  26047. * @param {HTMLCanvasElement} canvas The canvas to set image-rendering bicubic on.
  26048. * @return {HTMLCanvasElement} Returns the source canvas.
  26049. */
  26050. setImageRenderingBicubic: function (canvas) {
  26051. canvas.style['image-rendering'] = 'auto';
  26052. canvas.style.msInterpolationMode = 'bicubic';
  26053. return canvas;
  26054. }
  26055. };
  26056. /**
  26057. * @author Richard Davey <rich@photonstorm.com>
  26058. * @copyright 2014 Photon Storm Ltd.
  26059. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  26060. */
  26061. /**
  26062. * Detects device support capabilities. Using some elements from System.js by MrDoob and Modernizr
  26063. *
  26064. * @class Phaser.Device
  26065. * @constructor
  26066. */
  26067. Phaser.Device = function (game) {
  26068. /**
  26069. * @property {Phaser.Game} game - A reference to the currently running game.
  26070. */
  26071. this.game = game;
  26072. // Operating System
  26073. /**
  26074. * @property {boolean} desktop - Is running desktop?
  26075. * @default
  26076. */
  26077. this.desktop = false;
  26078. /**
  26079. * @property {boolean} iOS - Is running on iOS?
  26080. * @default
  26081. */
  26082. this.iOS = false;
  26083. /**
  26084. * @property {boolean} cocoonJS - Is the game running under CocoonJS?
  26085. * @default
  26086. */
  26087. this.cocoonJS = false;
  26088. /**
  26089. * @property {boolean} ejecta - Is the game running under Ejecta?
  26090. * @default
  26091. */
  26092. this.ejecta = false;
  26093. /**
  26094. * @property {boolean} android - Is running on android?
  26095. * @default
  26096. */
  26097. this.android = false;
  26098. /**
  26099. * @property {boolean} chromeOS - Is running on chromeOS?
  26100. * @default
  26101. */
  26102. this.chromeOS = false;
  26103. /**
  26104. * @property {boolean} linux - Is running on linux?
  26105. * @default
  26106. */
  26107. this.linux = false;
  26108. /**
  26109. * @property {boolean} macOS - Is running on macOS?
  26110. * @default
  26111. */
  26112. this.macOS = false;
  26113. /**
  26114. * @property {boolean} windows - Is running on windows?
  26115. * @default
  26116. */
  26117. this.windows = false;
  26118. /**
  26119. * @property {boolean} windowsPhone - Is running on a Windows Phone?
  26120. * @default
  26121. */
  26122. this.windowsPhone = false;
  26123. // Features
  26124. /**
  26125. * @property {boolean} canvas - Is canvas available?
  26126. * @default
  26127. */
  26128. this.canvas = false;
  26129. /**
  26130. * @property {boolean} file - Is file available?
  26131. * @default
  26132. */
  26133. this.file = false;
  26134. /**
  26135. * @property {boolean} fileSystem - Is fileSystem available?
  26136. * @default
  26137. */
  26138. this.fileSystem = false;
  26139. /**
  26140. * @property {boolean} localStorage - Is localStorage available?
  26141. * @default
  26142. */
  26143. this.localStorage = false;
  26144. /**
  26145. * @property {boolean} webGL - Is webGL available?
  26146. * @default
  26147. */
  26148. this.webGL = false;
  26149. /**
  26150. * @property {boolean} worker - Is worker available?
  26151. * @default
  26152. */
  26153. this.worker = false;
  26154. /**
  26155. * @property {boolean} touch - Is touch available?
  26156. * @default
  26157. */
  26158. this.touch = false;
  26159. /**
  26160. * @property {boolean} mspointer - Is mspointer available?
  26161. * @default
  26162. */
  26163. this.mspointer = false;
  26164. /**
  26165. * @property {boolean} css3D - Is css3D available?
  26166. * @default
  26167. */
  26168. this.css3D = false;
  26169. /**
  26170. * @property {boolean} pointerLock - Is Pointer Lock available?
  26171. * @default
  26172. */
  26173. this.pointerLock = false;
  26174. /**
  26175. * @property {boolean} typedArray - Does the browser support TypedArrays?
  26176. * @default
  26177. */
  26178. this.typedArray = false;
  26179. /**
  26180. * @property {boolean} vibration - Does the device support the Vibration API?
  26181. * @default
  26182. */
  26183. this.vibration = false;
  26184. /**
  26185. * @property {boolean} getUserMedia - Does the device support the getUserMedia API?
  26186. * @default
  26187. */
  26188. this.getUserMedia = false;
  26189. /**
  26190. * @property {boolean} quirksMode - Is the browser running in strict mode (false) or quirks mode? (true)
  26191. * @default
  26192. */
  26193. this.quirksMode = false;
  26194. // Browser
  26195. /**
  26196. * @property {boolean} arora - Set to true if running in Arora.
  26197. * @default
  26198. */
  26199. this.arora = false;
  26200. /**
  26201. * @property {boolean} chrome - Set to true if running in Chrome.
  26202. * @default
  26203. */
  26204. this.chrome = false;
  26205. /**
  26206. * @property {boolean} epiphany - Set to true if running in Epiphany.
  26207. * @default
  26208. */
  26209. this.epiphany = false;
  26210. /**
  26211. * @property {boolean} firefox - Set to true if running in Firefox.
  26212. * @default
  26213. */
  26214. this.firefox = false;
  26215. /**
  26216. * @property {boolean} ie - Set to true if running in Internet Explorer.
  26217. * @default
  26218. */
  26219. this.ie = false;
  26220. /**
  26221. * @property {number} ieVersion - If running in Internet Explorer this will contain the major version number. Beyond IE10 you should use Device.trident and Device.tridentVersion.
  26222. * @default
  26223. */
  26224. this.ieVersion = 0;
  26225. /**
  26226. * @property {boolean} trident - Set to true if running a Trident version of Internet Explorer (IE11+)
  26227. * @default
  26228. */
  26229. this.trident = false;
  26230. /**
  26231. * @property {number} tridentVersion - If running in Internet Explorer 11 this will contain the major version number. See http://msdn.microsoft.com/en-us/library/ie/ms537503(v=vs.85).aspx
  26232. * @default
  26233. */
  26234. this.tridentVersion = 0;
  26235. /**
  26236. * @property {boolean} mobileSafari - Set to true if running in Mobile Safari.
  26237. * @default
  26238. */
  26239. this.mobileSafari = false;
  26240. /**
  26241. * @property {boolean} midori - Set to true if running in Midori.
  26242. * @default
  26243. */
  26244. this.midori = false;
  26245. /**
  26246. * @property {boolean} opera - Set to true if running in Opera.
  26247. * @default
  26248. */
  26249. this.opera = false;
  26250. /**
  26251. * @property {boolean} safari - Set to true if running in Safari.
  26252. * @default
  26253. */
  26254. this.safari = false;
  26255. /**
  26256. * @property {boolean} webApp - Set to true if running as a WebApp, i.e. within a WebView
  26257. * @default
  26258. */
  26259. this.webApp = false;
  26260. /**
  26261. * @property {boolean} silk - Set to true if running in the Silk browser (as used on the Amazon Kindle)
  26262. * @default
  26263. */
  26264. this.silk = false;
  26265. // Audio
  26266. /**
  26267. * @property {boolean} audioData - Are Audio tags available?
  26268. * @default
  26269. */
  26270. this.audioData = false;
  26271. /**
  26272. * @property {boolean} webAudio - Is the WebAudio API available?
  26273. * @default
  26274. */
  26275. this.webAudio = false;
  26276. /**
  26277. * @property {boolean} ogg - Can this device play ogg files?
  26278. * @default
  26279. */
  26280. this.ogg = false;
  26281. /**
  26282. * @property {boolean} opus - Can this device play opus files?
  26283. * @default
  26284. */
  26285. this.opus = false;
  26286. /**
  26287. * @property {boolean} mp3 - Can this device play mp3 files?
  26288. * @default
  26289. */
  26290. this.mp3 = false;
  26291. /**
  26292. * @property {boolean} wav - Can this device play wav files?
  26293. * @default
  26294. */
  26295. this.wav = false;
  26296. /**
  26297. * Can this device play m4a files?
  26298. * @property {boolean} m4a - True if this device can play m4a files.
  26299. * @default
  26300. */
  26301. this.m4a = false;
  26302. /**
  26303. * @property {boolean} webm - Can this device play webm files?
  26304. * @default
  26305. */
  26306. this.webm = false;
  26307. // Device
  26308. /**
  26309. * @property {boolean} iPhone - Is running on iPhone?
  26310. * @default
  26311. */
  26312. this.iPhone = false;
  26313. /**
  26314. * @property {boolean} iPhone4 - Is running on iPhone4?
  26315. * @default
  26316. */
  26317. this.iPhone4 = false;
  26318. /**
  26319. * @property {boolean} iPad - Is running on iPad?
  26320. * @default
  26321. */
  26322. this.iPad = false;
  26323. /**
  26324. * @property {number} pixelRatio - PixelRatio of the host device?
  26325. * @default
  26326. */
  26327. this.pixelRatio = 0;
  26328. /**
  26329. * @property {boolean} littleEndian - Is the device big or little endian? (only detected if the browser supports TypedArrays)
  26330. * @default
  26331. */
  26332. this.littleEndian = false;
  26333. /**
  26334. * @property {boolean} fullscreen - Does the browser support the Full Screen API?
  26335. * @default
  26336. */
  26337. this.fullscreen = false;
  26338. /**
  26339. * @property {string} requestFullscreen - If the browser supports the Full Screen API this holds the call you need to use to activate it.
  26340. * @default
  26341. */
  26342. this.requestFullscreen = '';
  26343. /**
  26344. * @property {string} cancelFullscreen - If the browser supports the Full Screen API this holds the call you need to use to cancel it.
  26345. * @default
  26346. */
  26347. this.cancelFullscreen = '';
  26348. /**
  26349. * @property {boolean} fullscreenKeyboard - Does the browser support access to the Keyboard during Full Screen mode?
  26350. * @default
  26351. */
  26352. this.fullscreenKeyboard = false;
  26353. // Run the checks
  26354. this._checkAudio();
  26355. this._checkBrowser();
  26356. this._checkCSS3D();
  26357. this._checkDevice();
  26358. this._checkFeatures();
  26359. this._checkOS();
  26360. };
  26361. Phaser.Device.prototype = {
  26362. /**
  26363. * Check which OS is game running on.
  26364. * @method Phaser.Device#_checkOS
  26365. * @private
  26366. */
  26367. _checkOS: function () {
  26368. var ua = navigator.userAgent;
  26369. if (/Android/.test(ua))
  26370. {
  26371. this.android = true;
  26372. }
  26373. else if (/CrOS/.test(ua))
  26374. {
  26375. this.chromeOS = true;
  26376. }
  26377. else if (/iP[ao]d|iPhone/i.test(ua))
  26378. {
  26379. this.iOS = true;
  26380. }
  26381. else if (/Linux/.test(ua))
  26382. {
  26383. this.linux = true;
  26384. }
  26385. else if (/Mac OS/.test(ua))
  26386. {
  26387. this.macOS = true;
  26388. }
  26389. else if (/Windows/.test(ua))
  26390. {
  26391. this.windows = true;
  26392. if (/Windows Phone/i.test(ua))
  26393. {
  26394. this.windowsPhone = true;
  26395. }
  26396. }
  26397. if (this.windows || this.macOS || (this.linux && this.silk === false))
  26398. {
  26399. this.desktop = true;
  26400. }
  26401. // Windows Phone / Table reset
  26402. if (this.windowsPhone || ((/Windows NT/i.test(ua)) && (/Touch/i.test(ua))))
  26403. {
  26404. this.desktop = false;
  26405. }
  26406. },
  26407. /**
  26408. * Check HTML5 features of the host environment.
  26409. * @method Phaser.Device#_checkFeatures
  26410. * @private
  26411. */
  26412. _checkFeatures: function () {
  26413. this.canvas = !!window['CanvasRenderingContext2D'] || this.cocoonJS;
  26414. try {
  26415. this.localStorage = !!localStorage.getItem;
  26416. } catch (error) {
  26417. this.localStorage = false;
  26418. }
  26419. this.file = !!window['File'] && !!window['FileReader'] && !!window['FileList'] && !!window['Blob'];
  26420. this.fileSystem = !!window['requestFileSystem'];
  26421. this.webGL = ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )();
  26422. if (this.webGL === null || this.webGL === false)
  26423. {
  26424. this.webGL = false;
  26425. }
  26426. else
  26427. {
  26428. this.webGL = true;
  26429. }
  26430. this.worker = !!window['Worker'];
  26431. if ('ontouchstart' in document.documentElement || (window.navigator.maxTouchPoints && window.navigator.maxTouchPoints > 1))
  26432. {
  26433. this.touch = true;
  26434. }
  26435. if (window.navigator.msPointerEnabled || window.navigator.pointerEnabled)
  26436. {
  26437. this.mspointer = true;
  26438. }
  26439. this.pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
  26440. this.quirksMode = (document.compatMode === 'CSS1Compat') ? false : true;
  26441. this.getUserMedia = !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
  26442. },
  26443. /**
  26444. * Checks for support of the Full Screen API.
  26445. *
  26446. * @method Phaser.Device#checkFullScreenSupport
  26447. */
  26448. checkFullScreenSupport: function () {
  26449. var fs = [
  26450. 'requestFullscreen',
  26451. 'requestFullScreen',
  26452. 'webkitRequestFullscreen',
  26453. 'webkitRequestFullScreen',
  26454. 'msRequestFullscreen',
  26455. 'msRequestFullScreen',
  26456. 'mozRequestFullScreen',
  26457. 'mozRequestFullscreen'
  26458. ];
  26459. for (var i = 0; i < fs.length; i++)
  26460. {
  26461. if (this.game.canvas[fs[i]])
  26462. {
  26463. this.fullscreen = true;
  26464. this.requestFullscreen = fs[i];
  26465. }
  26466. }
  26467. var cfs = [
  26468. 'cancelFullScreen',
  26469. 'exitFullscreen',
  26470. 'webkitCancelFullScreen',
  26471. 'webkitExitFullscreen',
  26472. 'msCancelFullScreen',
  26473. 'msExitFullscreen',
  26474. 'mozCancelFullScreen',
  26475. 'mozExitFullscreen'
  26476. ];
  26477. if (this.fullscreen)
  26478. {
  26479. for (var i = 0; i < cfs.length; i++)
  26480. {
  26481. if (this.game.canvas[cfs[i]])
  26482. {
  26483. this.cancelFullscreen = cfs[i];
  26484. }
  26485. }
  26486. }
  26487. // Keyboard Input?
  26488. if (window['Element'] && Element['ALLOW_KEYBOARD_INPUT'])
  26489. {
  26490. this.fullscreenKeyboard = true;
  26491. }
  26492. },
  26493. /**
  26494. * Check what browser is game running in.
  26495. * @method Phaser.Device#_checkBrowser
  26496. * @private
  26497. */
  26498. _checkBrowser: function () {
  26499. var ua = navigator.userAgent;
  26500. if (/Arora/.test(ua))
  26501. {
  26502. this.arora = true;
  26503. }
  26504. else if (/Chrome/.test(ua))
  26505. {
  26506. this.chrome = true;
  26507. }
  26508. else if (/Epiphany/.test(ua))
  26509. {
  26510. this.epiphany = true;
  26511. }
  26512. else if (/Firefox/.test(ua))
  26513. {
  26514. this.firefox = true;
  26515. }
  26516. else if (/Mobile Safari/.test(ua))
  26517. {
  26518. this.mobileSafari = true;
  26519. }
  26520. else if (/MSIE (\d+\.\d+);/.test(ua))
  26521. {
  26522. this.ie = true;
  26523. this.ieVersion = parseInt(RegExp.$1, 10);
  26524. }
  26525. else if (/Midori/.test(ua))
  26526. {
  26527. this.midori = true;
  26528. }
  26529. else if (/Opera/.test(ua))
  26530. {
  26531. this.opera = true;
  26532. }
  26533. else if (/Safari/.test(ua))
  26534. {
  26535. this.safari = true;
  26536. }
  26537. else if (/Silk/.test(ua))
  26538. {
  26539. this.silk = true;
  26540. }
  26541. else if (/Trident\/(\d+\.\d+)(.*)rv:(\d+\.\d+)/.test(ua))
  26542. {
  26543. this.ie = true;
  26544. this.trident = true;
  26545. this.tridentVersion = parseInt(RegExp.$1, 10);
  26546. this.ieVersion = parseInt(RegExp.$3, 10);
  26547. }
  26548. // WebApp mode in iOS
  26549. if (navigator['standalone'])
  26550. {
  26551. this.webApp = true;
  26552. }
  26553. if (navigator['isCocoonJS'])
  26554. {
  26555. this.cocoonJS = true;
  26556. }
  26557. if (typeof window.ejecta !== "undefined")
  26558. {
  26559. this.ejecta = true;
  26560. }
  26561. },
  26562. /**
  26563. * Check audio support.
  26564. * @method Phaser.Device#_checkAudio
  26565. * @private
  26566. */
  26567. _checkAudio: function () {
  26568. this.audioData = !!(window['Audio']);
  26569. this.webAudio = !!(window['webkitAudioContext'] || window['AudioContext']);
  26570. var audioElement = document.createElement('audio');
  26571. var result = false;
  26572. try {
  26573. if (result = !!audioElement.canPlayType) {
  26574. if (audioElement.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
  26575. this.ogg = true;
  26576. }
  26577. if (audioElement.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, '')) {
  26578. this.opus = true;
  26579. }
  26580. if (audioElement.canPlayType('audio/mpeg;').replace(/^no$/, '')) {
  26581. this.mp3 = true;
  26582. }
  26583. // Mimetypes accepted:
  26584. // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
  26585. // bit.ly/iphoneoscodecs
  26586. if (audioElement.canPlayType('audio/wav; codecs="1"').replace(/^no$/, '')) {
  26587. this.wav = true;
  26588. }
  26589. if (audioElement.canPlayType('audio/x-m4a;') || audioElement.canPlayType('audio/aac;').replace(/^no$/, '')) {
  26590. this.m4a = true;
  26591. }
  26592. if (audioElement.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, '')) {
  26593. this.webm = true;
  26594. }
  26595. }
  26596. } catch (e) {
  26597. }
  26598. },
  26599. /**
  26600. * Check PixelRatio of devices.
  26601. * @method Phaser.Device#_checkDevice
  26602. * @private
  26603. */
  26604. _checkDevice: function () {
  26605. this.pixelRatio = window['devicePixelRatio'] || 1;
  26606. this.iPhone = navigator.userAgent.toLowerCase().indexOf('iphone') != -1;
  26607. this.iPhone4 = (this.pixelRatio == 2 && this.iPhone);
  26608. this.iPad = navigator.userAgent.toLowerCase().indexOf('ipad') != -1;
  26609. if (typeof Int8Array !== 'undefined')
  26610. {
  26611. this.littleEndian = new Int8Array(new Int16Array([1]).buffer)[0] > 0;
  26612. this.typedArray = true;
  26613. }
  26614. else
  26615. {
  26616. this.littleEndian = false;
  26617. this.typedArray = false;
  26618. }
  26619. navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
  26620. if (navigator.vibrate)
  26621. {
  26622. this.vibration = true;
  26623. }
  26624. },
  26625. /**
  26626. * Check whether the host environment support 3D CSS.
  26627. * @method Phaser.Device#_checkCSS3D
  26628. * @private
  26629. */
  26630. _checkCSS3D: function () {
  26631. var el = document.createElement('p');
  26632. var has3d;
  26633. var transforms = {
  26634. 'webkitTransform': '-webkit-transform',
  26635. 'OTransform': '-o-transform',
  26636. 'msTransform': '-ms-transform',
  26637. 'MozTransform': '-moz-transform',
  26638. 'transform': 'transform'
  26639. };
  26640. // Add it to the body to get the computed style.
  26641. document.body.insertBefore(el, null);
  26642. for (var t in transforms)
  26643. {
  26644. if (el.style[t] !== undefined)
  26645. {
  26646. el.style[t] = "translate3d(1px,1px,1px)";
  26647. has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
  26648. }
  26649. }
  26650. document.body.removeChild(el);
  26651. this.css3D = (has3d !== undefined && has3d.length > 0 && has3d !== "none");
  26652. },
  26653. /**
  26654. * Check whether the host environment can play audio.
  26655. * @method Phaser.Device#canPlayAudio
  26656. * @param {string} type - One of 'mp3, 'ogg', 'm4a', 'wav', 'webm'.
  26657. * @return {boolean} True if the given file type is supported by the browser, otherwise false.
  26658. */
  26659. canPlayAudio: function (type) {
  26660. if (type == 'mp3' && this.mp3)
  26661. {
  26662. return true;
  26663. }
  26664. else if (type == 'ogg' && (this.ogg || this.opus))
  26665. {
  26666. return true;
  26667. }
  26668. else if (type == 'm4a' && this.m4a)
  26669. {
  26670. return true;
  26671. }
  26672. else if (type == 'wav' && this.wav)
  26673. {
  26674. return true;
  26675. }
  26676. else if (type == 'webm' && this.webm)
  26677. {
  26678. return true;
  26679. }
  26680. return false;
  26681. },
  26682. /**
  26683. * Check whether the console is open.
  26684. * Note that this only works in Firefox with Firebug and earlier versions of Chrome.
  26685. * It used to work in Chrome, but then they removed the ability: http://src.chromium.org/viewvc/blink?view=revision&revision=151136
  26686. *
  26687. * @method Phaser.Device#isConsoleOpen
  26688. * @return {boolean} True if the browser dev console is open.
  26689. */
  26690. isConsoleOpen: function () {
  26691. if (window.console && window.console['firebug'])
  26692. {
  26693. return true;
  26694. }
  26695. if (window.console)
  26696. {
  26697. console.profile();
  26698. console.profileEnd();
  26699. if (console.clear)
  26700. {
  26701. console.clear();
  26702. }
  26703. if (console['profiles'])
  26704. {
  26705. return console['profiles'].length > 0;
  26706. }
  26707. }
  26708. return false;
  26709. }
  26710. };
  26711. Phaser.Device.prototype.constructor = Phaser.Device;
  26712. /**
  26713. * @author Richard Davey <rich@photonstorm.com>
  26714. * @copyright 2014 Photon Storm Ltd.
  26715. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  26716. */
  26717. /**
  26718. * Abstracts away the use of RAF or setTimeOut for the core game update loop.
  26719. *
  26720. * @class Phaser.RequestAnimationFrame
  26721. * @constructor
  26722. * @param {Phaser.Game} game - A reference to the currently running game.
  26723. * @param {boolean} [forceSetTimeOut=false] - Tell Phaser to use setTimeOut even if raf is available.
  26724. */
  26725. Phaser.RequestAnimationFrame = function(game, forceSetTimeOut) {
  26726. if (typeof forceSetTimeOut === 'undefined') { forceSetTimeOut = false; }
  26727. /**
  26728. * @property {Phaser.Game} game - The currently running game.
  26729. */
  26730. this.game = game;
  26731. /**
  26732. * @property {boolean} isRunning - true if RequestAnimationFrame is running, otherwise false.
  26733. * @default
  26734. */
  26735. this.isRunning = false;
  26736. /**
  26737. * @property {boolean} forceSetTimeOut - Tell Phaser to use setTimeOut even if raf is available.
  26738. */
  26739. this.forceSetTimeOut = forceSetTimeOut;
  26740. var vendors = [
  26741. 'ms',
  26742. 'moz',
  26743. 'webkit',
  26744. 'o'
  26745. ];
  26746. for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++)
  26747. {
  26748. window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
  26749. window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'];
  26750. }
  26751. /**
  26752. * @property {boolean} _isSetTimeOut - true if the browser is using setTimeout instead of raf.
  26753. * @private
  26754. */
  26755. this._isSetTimeOut = false;
  26756. /**
  26757. * @property {function} _onLoop - The function called by the update.
  26758. * @private
  26759. */
  26760. this._onLoop = null;
  26761. /**
  26762. * @property {number} _timeOutID - The callback ID used when calling cancel.
  26763. * @private
  26764. */
  26765. this._timeOutID = null;
  26766. };
  26767. Phaser.RequestAnimationFrame.prototype = {
  26768. /**
  26769. * Starts the requestAnimationFrame running or setTimeout if unavailable in browser
  26770. * @method Phaser.RequestAnimationFrame#start
  26771. */
  26772. start: function () {
  26773. this.isRunning = true;
  26774. var _this = this;
  26775. if (!window.requestAnimationFrame || this.forceSetTimeOut)
  26776. {
  26777. this._isSetTimeOut = true;
  26778. this._onLoop = function () {
  26779. return _this.updateSetTimeout();
  26780. };
  26781. this._timeOutID = window.setTimeout(this._onLoop, 0);
  26782. }
  26783. else
  26784. {
  26785. this._isSetTimeOut = false;
  26786. this._onLoop = function (time) {
  26787. return _this.updateRAF(time);
  26788. };
  26789. this._timeOutID = window.requestAnimationFrame(this._onLoop);
  26790. }
  26791. },
  26792. /**
  26793. * The update method for the requestAnimationFrame
  26794. * @method Phaser.RequestAnimationFrame#updateRAF
  26795. */
  26796. updateRAF: function () {
  26797. this.game.update(Date.now());
  26798. this._timeOutID = window.requestAnimationFrame(this._onLoop);
  26799. },
  26800. /**
  26801. * The update method for the setTimeout.
  26802. * @method Phaser.RequestAnimationFrame#updateSetTimeout
  26803. */
  26804. updateSetTimeout: function () {
  26805. this.game.update(Date.now());
  26806. this._timeOutID = window.setTimeout(this._onLoop, this.game.time.timeToCall);
  26807. },
  26808. /**
  26809. * Stops the requestAnimationFrame from running.
  26810. * @method Phaser.RequestAnimationFrame#stop
  26811. */
  26812. stop: function () {
  26813. if (this._isSetTimeOut)
  26814. {
  26815. clearTimeout(this._timeOutID);
  26816. }
  26817. else
  26818. {
  26819. window.cancelAnimationFrame(this._timeOutID);
  26820. }
  26821. this.isRunning = false;
  26822. },
  26823. /**
  26824. * Is the browser using setTimeout?
  26825. * @method Phaser.RequestAnimationFrame#isSetTimeOut
  26826. * @return {boolean}
  26827. */
  26828. isSetTimeOut: function () {
  26829. return this._isSetTimeOut;
  26830. },
  26831. /**
  26832. * Is the browser using requestAnimationFrame?
  26833. * @method Phaser.RequestAnimationFrame#isRAF
  26834. * @return {boolean}
  26835. */
  26836. isRAF: function () {
  26837. return (this._isSetTimeOut === false);
  26838. }
  26839. };
  26840. Phaser.RequestAnimationFrame.prototype.constructor = Phaser.RequestAnimationFrame;
  26841. /**
  26842. * @author Richard Davey <rich@photonstorm.com>
  26843. * @copyright 2014 Photon Storm Ltd.
  26844. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
  26845. */
  26846. /**
  26847. * A collection of mathematical methods.
  26848. *
  26849. * @class Phaser.Math
  26850. */
  26851. Phaser.Math = {
  26852. /**
  26853. * = 2 &pi;
  26854. * @method Phaser.Math#PI2
  26855. */
  26856. PI2: Math.PI * 2,
  26857. /**
  26858. * Two number are fuzzyEqual if their difference is less than &epsilon;.
  26859. * @method Phaser.Math#fuzzyEqual
  26860. * @param {number} a
  26861. * @param {number} b
  26862. * @param {number} epsilon
  26863. * @return {boolean} True if |a-b|<&epsilon;
  26864. */
  26865. fuzzyEqual: function (a, b, epsilon) {
  26866. if (typeof epsilon === "undefined") { epsilon = 0.0001; }
  26867. return Math.abs(a - b) < epsilon;
  26868. },
  26869. /**
  26870. * a is fuzzyLessThan b if it is less than b + &epsilon;.
  26871. * @method Phaser.Math#fuzzyLessThan
  26872. * @param {number} a
  26873. * @param {number} b
  26874. * @param {number} epsilon
  26875. * @return {boolean} True if a<b+&epsilon;
  26876. */
  26877. fuzzyLessThan: function (a, b, epsilon) {
  26878. if (typeof epsilon === "undefined") { epsilon = 0.0001; }
  26879. return a < b + epsilon;
  26880. },
  26881. /**
  26882. * a is fuzzyGreaterThan b if it is more than b - &epsilon;.
  26883. * @method Phaser.Math#fuzzyGreaterThan
  26884. * @param {number} a
  26885. * @param {number} b
  26886. * @param {number} epsilon
  26887. * @return {boolean} True if a>b+&epsilon;
  26888. */
  26889. fuzzyGreaterThan: function (a, b, epsilon) {
  26890. if (typeof epsilon === "undefined") { epsilon = 0.0001; }
  26891. return a > b - epsilon;
  26892. },
  26893. /**
  26894. * @method Phaser.Math#fuzzyCeil
  26895. * @param {number} val
  26896. * @param {number} epsilon
  26897. * @return {boolean} ceiling(val-&epsilon;)
  26898. */
  26899. fuzzyCeil: function (val, epsilon) {
  26900. if (typeof epsilon === "undefined") { epsilon = 0.0001; }
  26901. return Math.ceil(val - epsilon);
  26902. },
  26903. /**
  26904. * @method Phaser.Math#fuzzyFloor
  26905. * @param {number} val
  26906. * @param {number} epsilon
  26907. * @return {boolean} floor(val-&epsilon;)
  26908. */
  26909. fuzzyFloor: function (val, epsilon) {
  26910. if (typeof epsilon === "undefined") { epsilon = 0.0001; }
  26911. return Math.floor(val + epsilon);
  26912. },
  26913. /**
  26914. * Averages all values passed to the function and returns the result. You can pass as many parameters as you like.
  26915. * @method Phaser.Math#average
  26916. * @return {number} The average of all given values.
  26917. */
  26918. average: function () {
  26919. var args = [];
  26920. for (var _i = 0; _i < (arguments.length - 0); _i++) {
  26921. args[_i] = arguments[_i + 0];
  26922. }
  26923. var avg = 0;
  26924. for (var i = 0; i < args.length; i++) {
  26925. avg += args[i];
  26926. }
  26927. return avg / args.length;
  26928. },
  26929. /**
  26930. * @method Phaser.Math#truncate
  26931. * @param {number} n
  26932. * @return {number}
  26933. */
  26934. truncate: function (n) {
  26935. return (n > 0) ? Math.floor(n) : Math.ceil(n);
  26936. },
  26937. /**
  26938. * @method Phaser.Math#shear
  26939. * @param {number} n
  26940. * @return {number} n mod 1
  26941. */
  26942. shear: function (n) {
  26943. return n % 1;
  26944. },
  26945. /**
  26946. * Snap a value to nearest grid slice, using rounding.
  26947. *
  26948. * Example: if you have an interval gap of 5 and a position of 12... you will snap to 10 whereas 14 will snap to 15.
  26949. *
  26950. * @method Phaser.Math#snapTo
  26951. * @param {number} input - The value to snap.
  26952. * @param {number} gap - The interval gap of the grid.
  26953. * @param {number} [start] - Optional starting offset for gap.
  26954. * @return {number}
  26955. */
  26956. snapTo: function (input, gap, start) {
  26957. if (typeof start === "undefined") { start = 0; }
  26958. if (gap === 0) {
  26959. return input;
  26960. }
  26961. input -= start;
  26962. input = gap * Math.round(input / gap);
  26963. return start + input;
  26964. },
  26965. /**
  26966. * Snap a value to nearest grid slice, using floor.
  26967. *
  26968. * Example: if you have an interval gap of 5 and a position of 12... you will snap to 10. As will 14 snap to 10... but 16 will snap to 15
  26969. *
  26970. * @method Phaser.Math#snapToFloor
  26971. * @param {number} input - The value to snap.
  26972. * @param {number} gap - The interval gap of the grid.
  26973. * @param {number} [start] - Optional starting offset for gap.
  26974. * @return {number}
  26975. */
  26976. snapToFloor: function (input, gap, start) {
  26977. if (typeof start === "undefined") { start = 0; }
  26978. if (gap === 0) {
  26979. return input;
  26980. }
  26981. input -= start;
  26982. input = gap * Math.floor(input / gap);
  26983. return start + input;
  26984. },
  26985. /**
  26986. * Snap a value to nearest grid slice, using ceil.
  26987. *
  26988. * Example: if you have an interval gap of 5 and a position of 12... you will snap to 15. As will 14 will snap to 15... but 16 will snap to 20.
  26989. *
  26990. * @method Phaser.Math#snapToCeil
  26991. * @param {number} input - The value to snap.
  26992. * @param {number} gap - The interval gap of the grid.
  26993. * @param {number} [start] - Optional starting offset for gap.
  26994. * @return {number}
  26995. */
  26996. snapToCeil: function (input, gap, start) {
  26997. if (typeof start === "undefined") { start = 0; }
  26998. if (gap === 0) {
  26999. return input;
  27000. }
  27001. input -= start;
  27002. input = gap * Math.ceil(input / gap);
  27003. return start + input;
  27004. },
  27005. /**
  27006. * Snaps a value to the nearest value in an array.
  27007. * @method Phaser.Math#snapToInArray
  27008. * @param {number} input
  27009. * @param {array} arr
  27010. * @param {boolean} sort - True if the array needs to be sorted.
  27011. * @return {number}
  27012. */
  27013. snapToInArray: function (input, arr, sort) {
  27014. if (typeof sort === "undefined") { sort = true; }
  27015. if (sort) {
  27016. arr.sort();
  27017. }
  27018. if (input < arr[0]) {
  27019. return arr[0];
  27020. }
  27021. var i = 1;
  27022. while (arr[i] < input) {
  27023. i++;
  27024. }
  27025. var low = arr[i - 1];
  27026. var high = (i < arr.length) ? arr[i] : Number.POSITIVE_INFINITY;
  27027. return ((high - input) <= (input - low)) ? high : low;
  27028. },
  27029. /**
  27030. * Round to some place comparative to a 'base', default is 10 for decimal place.
  27031. *
  27032. * 'place' is represented by the power applied to 'base' to get that place
  27033. * e.g.
  27034. * 2000/7 ~= 285.714285714285714285714 ~= (bin)100011101.1011011011011011
  27035. *
  27036. * roundTo(2000/7,3) === 0
  27037. * roundTo(2000/7,2) == 300
  27038. * roundTo(2000/7,1) == 290
  27039. * roundTo(2000/7,0) == 286
  27040. * roundTo(2000/7,-1) == 285.7
  27041. * roundTo(2000/7,-2) == 285.71
  27042. * roundTo(2000/7,-3) == 285.714
  27043. * roundTo(2000/7,-4) == 285.7143
  27044. * roundTo(2000/7,-5) == 285.71429
  27045. *
  27046. * roundTo(2000/7,3,2) == 288 -- 100100000
  27047. * roundTo(2000/7,2,2) == 284 -- 100011100
  27048. * roundTo(2000/7,1,2) == 286 -- 100011110
  27049. * roundTo(2000/7,0,2) == 286 -- 100011110
  27050. * roundTo(2000/7,-1,2) == 285.5 -- 100011101.1
  27051. * roundTo(2000/7,-2,2) == 285.75 -- 100011101.11
  27052. * roundTo(2000/7,-3,2) == 285.75 -- 100011101.11
  27053. * roundTo(2000/7,-4,2) == 285.6875 -- 100011101.1011
  27054. * roundTo(2000/7,-5,2) == 285.71875 -- 100011101.10111
  27055. *
  27056. * Note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed
  27057. * because we are rounding 100011.1011011011011011 which rounds up.
  27058. *
  27059. * @method Phaser.Math#roundTo
  27060. * @param {number} value - The value to round.
  27061. * @param {number} place - The place to round to.
  27062. * @param {number} base - The base to round in... default is 10 for decimal.
  27063. * @return {number}
  27064. */
  27065. roundTo: function (value, place, base) {
  27066. if (typeof place === "undefined") { place = 0; }
  27067. if (typeof base === "undefined") { base = 10; }
  27068. var p = Math.pow(base, -place);
  27069. return Math.round(value * p) / p;
  27070. },
  27071. /**
  27072. * @method Phaser.Math#floorTo
  27073. * @param {number} value - The value to round.
  27074. * @param {number} place - The place to round to.
  27075. * @param {number} base - The base to round in... default is 10 for decimal.
  27076. * @return {number}
  27077. */
  27078. floorTo: function (value, place, base) {
  27079. if (typeof place === "undefined") { place = 0; }
  27080. if (typeof base === "undefined") { base = 10; }
  27081. var p = Math.pow(base, -place);
  27082. return Math.floor(value * p) / p;
  27083. },
  27084. /**
  27085. * @method Phaser.Math#ceilTo
  27086. * @param {number} value - The value to round.
  27087. * @param {number} place - The place to round to.
  27088. * @param {number} base - The base to round in... default is 10 for decimal.
  27089. * @return {number}
  27090. */
  27091. ceilTo: function (value, place, base) {
  27092. if (typeof place === "undefined") { place = 0; }
  27093. if (typeof base === "undefined") { base = 10; }
  27094. var p = Math.pow(base, -place);
  27095. return Math.ceil(value * p) / p;
  27096. },
  27097. /**
  27098. * A one dimensional linear interpolation of a value.
  27099. * @method Phaser.Math#interpolateFloat
  27100. * @param {number} a
  27101. * @param {number} b
  27102. * @param {number} weight
  27103. * @return {number}
  27104. */
  27105. interpolateFloat: function (a, b, weight) {
  27106. return (b - a) * weight + a;
  27107. },
  27108. /**
  27109. * Find the angle of a segment from (x1, y1) -> (x2, y2).
  27110. * @method Phaser.Math#angleBetween
  27111. * @param {number} x1
  27112. * @param {number} y1
  27113. * @param {number} x2
  27114. * @param {number} y2
  27115. * @return {number}
  27116. */
  27117. angleBetween: function (x1, y1, x2, y2) {
  27118. return Math.atan2(x2 - x1, y2 - y1);
  27119. },
  27120. /**
  27121. * Find the angle of a segment from (point1.x, point1.y) -> (point2.x, point2.y).
  27122. * @method Phaser.Math#angleBetweenPoints
  27123. * @param {Phaser.Point} point1
  27124. * @param {Phaser.Point} point2
  27125. * @return {number}
  27126. */
  27127. angleBetweenPoints: function (point1, point2) {
  27128. return Math.atan2(point2.x - point1.x, point2.y - point1.y);
  27129. },
  27130. /**
  27131. * Reverses an angle.
  27132. * @method Phaser.Math#reverseAngle
  27133. * @param {number} angleRad - The angle to reverse, in radians.
  27134. * @return {number} Returns the reverse angle, in radians.
  27135. */
  27136. reverseAngle: function (angleRad) {
  27137. return this.normalizeAngle(angleRad + Math.PI, true);
  27138. },
  27139. /**
  27140. * Normalizes an angle to the [0,2pi) range.
  27141. * @method Phaser.Math#normalizeAngle
  27142. * @param {number} angleRad - The angle to normalize, in radians.
  27143. * @return {number} Returns the angle, fit within the [0,2pi] range, in radians.
  27144. */
  27145. normalizeAngle: function (angleRad) {
  27146. angleRad = angleRad % (2 * Math.PI);
  27147. return angleRad >= 0 ? angleRad : angleRad + 2 * Math.PI;
  27148. },
  27149. /**
  27150. * Normalizes a latitude to the [-90,90] range. Latitudes above 90 or below -90 are capped, not wrapped.
  27151. * @method Phaser.Math#normalizeLatitude
  27152. * @param {number} lat - The latitude to normalize, in degrees.
  27153. * @return {number} Returns the latitude, fit within the [-90,90] range.
  27154. */
  27155. normalizeLatitude: function (lat) {
  27156. return Math.max(-90, Math.min(90, lat));
  27157. },
  27158. /**
  27159. * Normalizes a longitude to the [-180,180] range. Longitudes above 180 or below -180 are wrapped.
  27160. * @method Phaser.Math#normalizeLongitude
  27161. * @param {number} lng - The longitude to normalize, in degrees.
  27162. * @return {number} Returns the longitude, fit within the [-180,180] range.
  27163. */
  27164. normalizeLongitude: function (lng) {
  27165. if (lng % 360 == 180)
  27166. {
  27167. return 180;
  27168. }
  27169. lng = lng % 360;
  27170. return lng < -180 ? lng + 360 : lng > 180 ? lng - 360 : lng;
  27171. },
  27172. /**
  27173. * Closest angle between two angles from a1 to a2 absolute value the return for exact angle
  27174. * @method Phaser.Math#nearestAngleBetween
  27175. * @param {number} a1
  27176. * @param {number} a2
  27177. * @param {boolean} radians - True if angle sizes are expressed in radians.
  27178. * @return {number}
  27179. */
  27180. nearestAngleBetween: function (a1, a2, radians) {
  27181. if (typeof radians === "undefined") { radians = true; }
  27182. var rd = (radians) ? Math.PI : 180;
  27183. a1 = this.normalizeAngle(a1, radians);
  27184. a2 = this.normalizeAngle(a2, radians);
  27185. if (a1 < -rd / 2 && a2 > rd / 2)
  27186. {
  27187. a1 += rd * 2;
  27188. }
  27189. if (a2 < -rd / 2 && a1 > rd / 2)
  27190. {
  27191. a2 += rd * 2;
  27192. }
  27193. return a2 - a1;
  27194. },
  27195. /**
  27196. * Interpolate across the shortest arc between two angles.
  27197. * @method Phaser.Math#interpolateAngles
  27198. * @param {number} a1 - Description.
  27199. * @param {number} a2 - Description.
  27200. * @param {number} weight - Description.
  27201. * @param {boolean} radians - True if angle sizes are expressed in radians.
  27202. * @param {Description} ease - Description.
  27203. * @return {number}
  27204. */
  27205. interpolateAngles: function (a1, a2, weight, radians, ease) {
  27206. if (typeof radians === "undefined") { radians = true; }
  27207. if (typeof ease === "undefined") { ease = null; }
  27208. a1 = this.normalizeAngle(a1, radians);
  27209. a2 = this.normalizeAngleToAnother(a2, a1, radians);
  27210. return (typeof ease === 'function') ? ease(weight, a1, a2 - a1, 1) : this.interpolateFloat(a1, a2, weight);
  27211. },
  27212. /**
  27213. * Generate a random bool result based on the chance value.
  27214. * <p>
  27215. * Returns true or false based on the chance value (default 50%). For example if you wanted a player to have a 30% chance
  27216. * of getting a bonus, call chanceRoll(30) - true means the chance passed, false means it failed.
  27217. * </p>
  27218. * @method Phaser.Math#chanceRoll
  27219. * @param {number} chance - The chance of receiving the value. A number between 0 and 100 (effectively 0% to 100%).
  27220. * @return {boolean} True if the roll passed, or false otherwise.
  27221. */
  27222. chanceRoll: function (chance) {
  27223. if (typeof chance === "undefined") { chance = 50; }
  27224. if (chance <= 0)
  27225. {
  27226. return false;
  27227. }
  27228. else if (chance >= 100)
  27229. {
  27230. return true;
  27231. }
  27232. else
  27233. {
  27234. if (Math.random() * 100 >= chance)
  27235. {
  27236. return false;
  27237. }
  27238. else
  27239. {
  27240. return true;
  27241. }
  27242. }
  27243. },
  27244. /**
  27245. * Returns an Array containing the numbers from min to max (inclusive).
  27246. *
  27247. * @method Phaser.Math#numberArray
  27248. * @param {number} min - The minimum value the array starts with.
  27249. * @param {number} max - The maximum value the array contains.
  27250. * @return {array} The array of number values.
  27251. */
  27252. numberArray: function (min, max) {
  27253. var result = [];
  27254. for (var i = min; i <= max; i++)
  27255. {
  27256. result.push(i);
  27257. }
  27258. return result;
  27259. },
  27260. /**
  27261. * Adds the given amount to the value, but never lets the value go over the specified maximum.
  27262. *
  27263. * @method Phaser.Math#maxAdd
  27264. * @param {number} value - The value to add the amount to.
  27265. * @param {number} amount - The amount to add to the value.
  27266. * @param {number} max- The maximum the value is allowed to be.
  27267. * @return {number}
  27268. */
  27269. maxAdd: function (value, amount, max) {
  27270. value += amount;
  27271. if (value > max)
  27272. {
  27273. value = max;
  27274. }
  27275. return value;
  27276. },
  27277. /**
  27278. * Subtracts the given amount from the value, but never lets the value go below the specified minimum.
  27279. *
  27280. * @method Phaser.Math#minSub
  27281. * @param {number} value - The base value.
  27282. * @param {number} amount - The amount to subtract from the base value.
  27283. * @param {number} min - The minimum the value is allowed to be.
  27284. * @return {number} The new value.
  27285. */
  27286. minSub: function (value, amount, min) {
  27287. value -= amount;
  27288. if (value < min)
  27289. {
  27290. value = min;
  27291. }
  27292. return value;
  27293. },
  27294. /**
  27295. * Ensures that the value always stays between min and max, by wrapping the value around.
  27296. * max should be larger than min, or the function will return 0.
  27297. *
  27298. * @method Phaser.Math#wrap
  27299. * @param {number} value - The value to wrap.
  27300. * @param {number} min - The minimum the value is allowed to be.
  27301. * @param {number} max - The maximum the value is allowed to be.
  27302. * @return {number} The wrapped value.
  27303. */
  27304. wrap: function (value, min, max) {
  27305. var range = max - min;
  27306. if (range <= 0)
  27307. {
  27308. return 0;
  27309. }
  27310. var result = (value - min) % range;
  27311. if (result < 0)
  27312. {
  27313. result += range;
  27314. }
  27315. return result + min;
  27316. },
  27317. /**
  27318. * Adds value to amount and ensures that the result always stays between 0 and max, by wrapping the value around.
  27319. * Values must be positive integers, and are passed through Math.abs.
  27320. *
  27321. * @method Phaser.Math#wrapValue
  27322. * @param {number} value - The value to add the amount to.
  27323. * @param {number} amount - The amount to add to the value.
  27324. * @param {number} max - The maximum the value is allowed to be.
  27325. * @return {number} The wrapped value.
  27326. */
  27327. wrapValue: function (value, amount, max) {
  27328. var diff;
  27329. value = Math.abs(value);
  27330. amount = Math.abs(amount);
  27331. max = Math.abs(max);
  27332. diff = (value + amount) % max;
  27333. return diff;
  27334. },
  27335. /**
  27336. * Randomly returns either a 1 or -1.
  27337. *
  27338. * @method Phaser.Math#randomSign
  27339. * @return {number} 1 or -1
  27340. */
  27341. randomSign: function () {
  27342. return (Math.random() > 0.5) ? 1 : -1;
  27343. },
  27344. /**
  27345. * Returns true if the number given is odd.
  27346. *
  27347. * @method Phaser.Math#isOdd
  27348. * @param {number} n - The number to check.
  27349. * @return {boolean} True if the given number is odd. False if the given number is even.
  27350. */
  27351. isOdd: function (n) {
  27352. return (n & 1);
  27353. },
  27354. /**
  27355. * Returns true if the number given is even.
  27356. *
  27357. * @method Phaser.Math#isEven
  27358. * @param {number} n - The number to check.
  27359. * @return {boolean} True if the given number is even. False if the given number is odd.
  27360. */
  27361. isEven: function (n) {
  27362. if (n & 1)
  27363. {
  27364. return false;
  27365. }
  27366. else
  27367. {
  27368. return true;
  27369. }
  27370. },
  27371. /**
  27372. * Updated version of Math.min that can be passed either an array of numbers or the numbers as parameters.
  27373. * See http://jsperf.com/math-s-min-max-vs-homemade/5
  27374. *
  27375. * @method Phaser.Math#min
  27376. * @return {number} The lowest value from those given.
  27377. */
  27378. min: function () {
  27379. if (arguments.length === 1 && typeof arguments[0] === 'object')
  27380. {
  27381. var data = arguments[0];
  27382. }
  27383. else
  27384. {
  27385. var data = arguments;
  27386. }
  27387. for (var i = 1, min = 0, len = data.length; i < len; i++)
  27388. {
  27389. if (data[i] < data[min])
  27390. {
  27391. min = i;
  27392. }
  27393. }
  27394. return data[min];
  27395. },
  27396. /**
  27397. * Updated version of Math.max that can be passed either an array of numbers or the numbers as parameters.
  27398. *
  27399. * @method Phaser.Math#max
  27400. * @return {number} The largest value from those given.
  27401. */
  27402. max: function () {
  27403. if (arguments.length === 1 && typeof arguments[0] === 'object')
  27404. {
  27405. var data = arguments[0];
  27406. }
  27407. else
  27408. {
  27409. var data = arguments;
  27410. }
  27411. for (var i = 1, max = 0, len = data.length; i < len; i++)
  27412. {
  27413. if (data[i] > data[max])
  27414. {
  27415. max = i;
  27416. }
  27417. }
  27418. return data[max];
  27419. },
  27420. /**
  27421. * Updated version of Math.min that can be passed a property and either an array of objects or the objects as parameters.
  27422. * It will find the lowest matching property value from the given objects.
  27423. *
  27424. * @method Phaser.Math#minProperty
  27425. * @return {number} The lowest value from those given.
  27426. */
  27427. minProperty: function (property) {
  27428. if (arguments.length === 2 && typeof arguments[1] === 'object')
  27429. {
  27430. var data = arguments[1];
  27431. }
  27432. else
  27433. {
  27434. var data = arguments.slice(1);
  27435. }
  27436. for (var i = 1, min = 0, len = data.length; i < len; i++)
  27437. {
  27438. if (data[i][property] < data[min][property])
  27439. {
  27440. min = i;
  27441. }
  27442. }
  27443. return data[min][property];
  27444. },
  27445. /**
  27446. * Updated version of Math.max that can be passed a property and either an array of objects or the objects as parameters.
  27447. * It will find the largest matching property value from the given objects.
  27448. *
  27449. * @method Phaser.Math#maxProperty
  27450. * @return {number} The largest value from those given.
  27451. */
  27452. maxProperty: function (property) {
  27453. if (arguments.length === 2 && typeof arguments[1] === 'object')
  27454. {
  27455. var data = arguments[1];
  27456. }
  27457. else
  27458. {
  27459. var data = arguments.slice(1);
  27460. }
  27461. for (var i = 1, max = 0, len = data.length; i < len; i++)
  27462. {
  27463. if (data[i][property] > data[max][property])
  27464. {
  27465. max = i;
  27466. }
  27467. }
  27468. return data[max][property];
  27469. },
  27470. /**
  27471. * Keeps an angle value between -180 and +180<br>
  27472. * Should be called whenever the angle is updated on the Sprite to stop it from going insane.
  27473. *
  27474. * @method Phaser.Math#wrapAngle
  27475. * @param {number} angle - The angle value to check
  27476. * @param {boolean} radians - True if angle sizes are expressed in radians.
  27477. * @return {number} The new angle value, returns the same as the input angle if it was within bounds.
  27478. */
  27479. wrapAngle: function (angle, radians) {
  27480. var radianFactor = (radians) ? Math.PI / 180 : 1;
  27481. return this.wrap(angle, -180 * radianFactor, 180 * radianFactor);
  27482. },
  27483. /**
  27484. * Keeps an angle value between the given min and max values.
  27485. *
  27486. * @method Phaser.Math#angleLimit
  27487. * @param {number} angle - The angle value to check. Must be between -180 and +180.
  27488. * @param {number} min - The minimum angle that is allowed (must be -180 or greater).
  27489. * @param {number} max - The maximum angle that is allowed (must be 180 or less).
  27490. * @return {number} The new angle value, returns the same as the input angle if it was within bounds
  27491. */
  27492. angleLimit: function (angle, min, max) {
  27493. var result = angle;
  27494. if (angle > max)
  27495. {
  27496. result = max;
  27497. }
  27498. else if (angle < min)
  27499. {
  27500. result = min;
  27501. }
  27502. return result;
  27503. },
  27504. /**
  27505. * A Linear Interpolation Method, mostly used by Phaser.Tween.
  27506. * @method Phaser.Math#linearInterpolation
  27507. * @param {number} v
  27508. * @param {number} k
  27509. * @return {number}
  27510. */
  27511. linearInterpolation: function (v, k) {
  27512. var m = v.length - 1;
  27513. var f = m * k;
  27514. var i = Math.floor(f);
  27515. if (k < 0)
  27516. {
  27517. return this.linear(v[0], v[1], f);
  27518. }
  27519. if (k > 1)
  27520. {
  27521. return this.linear(v[m], v[m - 1], m - f);
  27522. }
  27523. return this.linear(v[i], v[i + 1 > m ? m : i + 1], f - i);
  27524. },
  27525. /**
  27526. * A Bezier Interpolation Method, mostly used by Phaser.Tween.
  27527. * @method Phaser.Math#bezierInterpolation
  27528. * @param {number} v
  27529. * @param {number} k
  27530. * @return {number}
  27531. */
  27532. bezierInterpolation: function (v, k) {
  27533. var b = 0;
  27534. var n = v.length - 1;
  27535. for (var i = 0; i <= n; i++)
  27536. {
  27537. b += Math.pow(1 - k, n - i) * Math.pow(k, i) * v[i] * this.bernstein(n, i);
  27538. }
  27539. return b;
  27540. },
  27541. /**
  27542. * A Catmull Rom Interpolation Method, mostly used by Phaser.Tween.
  27543. * @method Phaser.Math#catmullRomInterpolation
  27544. * @param {number} v
  27545. * @param {number} k
  27546. * @return {number}
  27547. */
  27548. catmullRomInterpolation: function (v, k) {
  27549. var m = v.length - 1;
  27550. var f = m * k;
  27551. var i = Math.floor(f);
  27552. if (v[0] === v[m])
  27553. {
  27554. if (k < 0)
  27555. {
  27556. i = Math.floor(f = m * (1 + k));
  27557. }
  27558. return this.catmullRom(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);
  27559. }
  27560. else
  27561. {
  27562. if (k < 0)
  27563. {
  27564. return v[0] - (this.catmullRom(v[0], v[0], v[1], v[1], -f) - v[0]);
  27565. }
  27566. if (k > 1)
  27567. {
  27568. return v[m] - (this.catmullRom(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);
  27569. }
  27570. return this.catmullRom(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);
  27571. }
  27572. },
  27573. /**
  27574. * Description.
  27575. * @method Phaser.Math#Linear
  27576. * @param {number} p0
  27577. * @param {number} p1
  27578. * @param {number} t
  27579. * @return {number}
  27580. */
  27581. linear: function (p0, p1, t) {
  27582. return (p1 - p0) * t + p0;
  27583. },
  27584. /**
  27585. * @method Phaser.Math#bernstein
  27586. * @param {number} n
  27587. * @param {number} i
  27588. * @return {number}
  27589. */
  27590. bernstein: function (n, i) {
  27591. return this.factorial(n) / this.factorial(i) / this.factorial(n - i);
  27592. },
  27593. /**
  27594. * Description.
  27595. * @method Phaser.Math#catmullRom
  27596. * @param {number} p0
  27597. * @param {number} p1
  27598. * @param {number} p2
  27599. * @param {number} p3
  27600. * @param {number} t
  27601. * @return {number}
  27602. */
  27603. catmullRom: function (p0, p1, p2, p3, t) {
  27604. var v0 = (p2 - p0) * 0.5, v1 = (p3 - p1) * 0.5, t2 = t * t, t3 = t * t2;
  27605. return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
  27606. },
  27607. /**
  27608. * @method Phaser.Math#difference
  27609. * @param {number} a
  27610. * @param {number} b
  27611. * @return {number}
  27612. */
  27613. difference: function (a, b) {
  27614. return Math.abs(a - b);
  27615. },
  27616. /**
  27617. * Fetch a random entry from the given array.
  27618. * Will return null if random selection is missing, or array has no entries.
  27619. *
  27620. * @method Phaser.Math#getRandom
  27621. * @param {array} objects - An array of objects.
  27622. * @param {number} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
  27623. * @param {number} length - Optional restriction on the number of values you want to randomly select from.
  27624. * @return {object} The random object that was selected.
  27625. */
  27626. getRandom: function (objects, startIndex, length) {
  27627. if (typeof startIndex === "undefined") { startIndex = 0; }
  27628. if (typeof length === "undefined") { length = 0; }
  27629. if (objects != null) {
  27630. var l = length;
  27631. if ((l === 0) || (l > objects.length - startIndex))
  27632. {
  27633. l = objects.length - startIndex;
  27634. }
  27635. if (l > 0)
  27636. {
  27637. return objects[startIndex + Math.floor(Math.random() * l)];
  27638. }
  27639. }
  27640. return null;
  27641. },
  27642. /**
  27643. * Removes a random object from the given array and returns it.
  27644. * Will return null if random selection is missing, or array has no entries.
  27645. *
  27646. * @method Phaser.Math#removeRandom
  27647. * @param {array} objects - An array of objects.
  27648. * @param {number} startIndex - Optional offset off the front of the array. Default value is 0, or the beginning of the array.
  27649. * @param {number} length - Optional restriction on the number of values you want to randomly select from.
  27650. * @return {object} The random object that was removed.
  27651. */
  27652. removeRandom: function (objects, startIndex, length) {
  27653. if (typeof startIndex === "undefined") { startIndex = 0; }
  27654. if (typeof length === "undefined") { length = 0; }
  27655. if (objects != null) {
  27656. var l = length;
  27657. if ((l === 0) || (l > objects.length - startIndex))
  27658. {
  27659. l = objects.length - startIndex;
  27660. }
  27661. if (l > 0)
  27662. {
  27663. var idx = startIndex + Math.floor(Math.random() * l);
  27664. var removed = objects.splice(idx, 1);
  27665. return removed[0];
  27666. }
  27667. }
  27668. return null;
  27669. },
  27670. /**
  27671. * Round down to the next whole number. E.g. floor(1.7) == 1, and floor(-2.7) == -2.
  27672. *
  27673. * @method Phaser.Math#floor
  27674. * @param {number} Value Any number.
  27675. * @return {number} The rounded value of that number.
  27676. */
  27677. floor: function (value) {
  27678. var n = value | 0;
  27679. return (value > 0) ? (n) : ((n != value) ? (n - 1) : (n));
  27680. },
  27681. /**
  27682. * Round up to the next whole number. E.g. ceil(1.3) == 2, and ceil(-2.3) == -3.
  27683. *
  27684. * @method Phaser.Math#ceil
  27685. * @param {number} value - Any number.
  27686. * @return {number} The rounded value of that number.
  27687. */
  27688. ceil: function (value) {
  27689. var n = value | 0;
  27690. return (value > 0) ? ((n != value) ? (n + 1) : (n)) : (n);
  27691. },
  27692. /**
  27693. * Generate a sine and cosine table simultaneously and extremely quickly. Based on research by Franky of scene.at
  27694. * <p>
  27695. * The parameters allow you to specify the length, amplitude and frequency of the wave. Once you have called this function
  27696. * you should get the results via getSinTable() and getCosTable(). This generator is fast enough to be used in real-time.
  27697. * </p>
  27698. * @method Phaser.Math#sinCosGenerator
  27699. * @param {number} length - The length of the wave
  27700. * @param {number} sinAmplitude - The amplitude to apply to the sine table (default 1.0) if you need