Merge branch 'master' into feature/support-infinite-tiled-maps

This commit is contained in:
Craig Whiteside 2018-12-20 16:51:42 +00:00 committed by GitHub
commit 48fc7dc388
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
748 changed files with 471747 additions and 279174 deletions

View file

@ -8,3 +8,12 @@ src/geom/polygon/Earcut.js
src/utils/array/StableSort.js
src/utils/object/Extend.js
src/structs/RTree.js
src/dom/_ScaleManager.js
src/dom/VisualBounds.js
plugins/spine/src/spine-canvas.js
plugins/spine/src/spine-webgl.js
webpack.*
webpack.config.js
webpack.dist.config.js
webpack.fb.config.js
webpack.fb.dist.config.js

View file

@ -16,7 +16,8 @@
"CANVAS_RENDERER": true,
"Phaser": true,
"process": true,
"ActiveXObject": true
"ActiveXObject": true,
"FBInstant": true
},
"rules": {
@ -71,7 +72,8 @@
"eol-last": [ "error" ],
"func-call-spacing": [ "error", "never" ],
"indent": [ "error", 4, { "SwitchCase": 1 } ],
"key-spacing": [ "error", { "beforeColon": false, "afterColon": true }],
"key-spacing": [ "error", { "beforeColon": false, "afterColon": true } ],
"keyword-spacing": [ "error", { "after": true } ],
"linebreak-style": [ "off" ],
"lines-around-comment": [ "error", { "beforeBlockComment": true, "afterBlockComment": false, "beforeLineComment": true, "afterLineComment": false, "allowBlockStart": true, "allowBlockEnd": false, "allowObjectStart": true, "allowArrayStart": true }],
"new-parens": "error",

View file

@ -1,9 +0,0 @@
This repo is for Phaser 3 related issues only. If you've found an issue with Phaser 2 please see the [Phaser CE (Community Edition)](https://github.com/photonstorm/phaser-ce) repo instead.
This should not be used for technical support. If you're struggling trying to use Phaser then post your question to the [forum](http://www.html5gamedevs.com/forum/33-phaser-3/), [Slack](https://phaser.io/community/slack) or [Discord](https://phaser.io/community/discord) channels. GitHub Issues are for bugs and feature requests only.
API errors must include example code showing what happens, and why you don't believe this is the expected behavior. Issues posted without code take _far_ longer to get resolved, _if ever_. Feel free to use a site such as jsBin or [CodePen](https://codepen.io/pen?template=YeEWom) to demo the problem. If we can run it, and see the error, we can usually fix it.
If your Issue contains _any_ form of hostility it will be instantly closed and you will be blocked from access to all our repos.
**Be nice. We do this for free.**

59
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,59 @@
---
name: "\U0001F41B Bug Report"
about: Report a bug found while using Phaser 3
---
<!--
Thank you for taking the time to contribute towards Phaser. Before submitting your issue, check the following:
1. This repo is for Phaser 3 only. Phaser 2.x issues should be raised in the [Phaser CE](https://github.com/photonstorm/phaser-ce) repo.
2. This repo should not be used for technical support. If you're struggling to use Phaser then post your question to the [forum](http://www.html5gamedevs.com/forum/33-phaser-3/), [Slack](https://phaser.io/community/slack) or [Discord](https://phaser.io/community/discord) channels. GitHub Issues are for bugs and feature requests only.
3. Make sure your issue isn't a duplicate, or has already been fixed.
4. If your issue contains _any_ form of hostility it will be closed and you will be blocked from access to all our repos. Be nice. We do this for free.
5. If all the above is ok, fill out the template below.
-->
## Version
<!--
Enter the version of Phaser you're using. You can find this output to the Dev Tools console in your browser.
-->
* Phaser Version:
<!--
Place the operating system **below** this comment.
-->
* Operating system:
<!--
If the bug is browser specific, please enter the version **below** this comment:
-->
* Browser:
## Description
<!--
Write a detailed description of the bug **below** this comment. Include the expected behavior and what actually happens. If the issue is device specific, please say so.
-->
## Example Test Code
<!--
All issues must have source code demonstrating the problem. We automatically close issues after 30 days if no code is provided.
The code can be pasted directly below this comment, or you can link to codepen, jsbin, or similar. The code will ideally be runnable instantly. The more work involved in turning your code into a reproducible test case, the longer it will take the fix the issue.
-->
## Additional Information
<!--
Is there anything else you think would be useful for us to reproduce the error? Do you have a solution in mind?
If you have any screen shots or gifs demonstrating the issue (if it can't be seen when running your code), please include those too.
-->

View file

@ -0,0 +1,15 @@
---
name: "\U0001F389 Feature Request"
about: Share an idea about a feature you'd like to see in Phaser
---
**We're constantly trying to make Phaser 3 better**
So we'd love to hear about feature requests for the v3 API. Screenshots, example code or links to blog posts / other APIs are encouraged.
Please try and keep the requests sensible. We will only keep those we feel are within our abilities to add to Phaser, or that are a good fit for our API.
**[Optional] Do you want to help provide this feature?**
If you would like to get involved in helping build the feature, please let us know. We can then discuss implementation with you and the best way to approach it. Again, screenshots or mockups are really useful.

14
.github/no-response.yml vendored Normal file
View file

@ -0,0 +1,14 @@
# Configuration for no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 30
# Label requiring a response
# TODO: also close `needs-reproduction` issues (blocked by https://github.com/probot/no-response/issues/11)
responseRequiredLabel: 🤷‍♂️ More info needed
# Comment to post when closing an issue due to lack of response.
closeComment: >
Thank you for taking time to open this issue.
We havent gotten a response to our questions above. With the details currently given in the issue we dont have enough information to take action.
So were going to close this issue. We can re-open it if you find the time to provide the information we need.

View file

@ -1,10 +1,842 @@
# Change Log
## Version 3.11.0 - Leafa - in development
## Version 3.16.0 - Ishikawa - in development
### Facebook Instant Games Updates and Fixes
* Added the `Leaderboard.getConnectedScores` method, to get a list of scores from player connected entries.
* The `loadPlayerPhoto` function in the Instant Games plugin now listens for the updated Loader event correctly, causing the `photocomplete` event to fire properly.
* `Leaderboard.setScore` now emits the LeaderboardScore object with the `setscore` event, as the documentation said it did.
* `Leaderboard.getPlayerScore` now only populates the `playerScore` property if the entry isn't `null`.
* If the `setScore` or `getPlayerScore` calls fail, it will return `null` as the score instance, instead of causing a run-time error.
* You can now pass an object or a string to `setScore` and objects will be automatically stringified.
* The `preloadAds` method will now only create an AdInstance object if the interstitial `loadSync` promise resolves.
* The `preloadVideoAds` method will now only create an AdInstance object if the interstitial `loadSync` promise resolves.
* The `preloadAds` method will now emit the `adsnofill` event, if there are no ads in the inventory to load.
* The `preloadVideoAds` method will now emit the `adsnofill` event, if there are no ads in the inventory to load.
* The `showAd` method will now emit the `adsnotloaded` event, if there are no ads loaded matching the given Placement ID.
* The `showVideo` method will now emit the `adsnotloaded` event, if there are no ads loaded matching the given Placement ID.
* Showing an ad will emit the `adfinished` event when the ad is closed, previously this event was called `showad` but the new name better reflects what has happened.
* The Facebook Plugin is now available in the `Phaser.Scene` class template under the `facebook` property (thanks @bryanwood)
### Keyboard Input - New Features
The specificity of the Keyboard events has been changed to allow you more control over event handling. Previously, the Keyboard Plugin would emit the global `keydown_CODE` event first (where CODE was a keycode string, like `keydown_A`), then it would emit the global `keydown` event. In previous versions, `Key` objects, created via `this.input.keyboard.addKey()`, didn't emit events.
The `Key` class now extends EventEmitter and emits two new events directly: `down` and `up`. This means you can listen for an event from a Key you've created, i.e.: `yourKey.on('up', handler)`.
The order has also now changed. If it exists, the Key object will dispatch its `down` event first. Then the Keyboard Plugin will dispatch `keydown_CODE` and finally the least specific of them all, `keydown` will be dispatched.
You also now have the ability to cancel this at any stage either on a local or global level. All events handlers are sent an event object which you can call `event.stopImmediatePropagation()` on. This will immediately stop any further listeners from being invoked in the current Scene. Therefore, if you call `stopImmediatePropagation()` in the `Key.on` handler, then the Keyboard Plugin will not emit either the `keydown_CODE` or `keydown` global events. You can also call `stopImmediatePropagation()` during the `keydown_CODE` handler, to stop it reaching the global `keydown` handler. As `keydown` is last, calling it there has no effect.
There is also the `stopPropagation()` function. This works in the same way as `stopImmediatePropagation` but instead of being local, it works across all of the Scenes in your game. For example, if you had 3 active Scenes (A, B and C, with A at the top of the Scene list), all listening for the same key, calling `stopPropagation()` in Scene A would stop the event from reaching any handlers in Scenes B or C. Remember that events flow down the Scene list from top to bottom. So, the top-most rendering Scene in the Scene list has priority over any Scene below it.
All the above also works for `keyup` events.
New in 3.16 is the ability to receive a global `keydown` or `keyup` event from any key on the keyboard. Previously, it would only emit the event if it came from one of the keys listed in the KeyCodes file. Now, those global events will fire for any key, regardless of location.
#### Keyboard Captures
Key capturing is the way in which you stop a keyboard DOM event from activating anything else in the browser by calling `preventDefault` on it. For example, in tall web pages, pressing the SPACE BAR causes the page to scroll down. Obviously, if this is also the fire or jump button in your game, you don't want this to happen. So the key needs to be 'captured' to prevent it. Equally, you may wish to also capture the arrow keys, for similar reasons. Key capturing is done on a global level. If you set-up the capture of a key in one Scene, it will be captured globally across the whole game.
In 3.16 you now do this using the new `KeyboardPlugin.addCapture` method. This takes keycodes as its argument. You can either pass in a single key code (i.e. 32 for the Space Bar), an array of key codes, or a comma-delimited string - in which case the string is parsed and each code it can work out is captured.
To remove a capture you can use the `KeyboardPlugin.removeCapture` method, which takes the same style arguments as adding captures. To clear all captures call `KeyboardPlugin.clearCaptures`. Again, remember that these actions are global.
You can also temporarily enable and disable capturing using `KeyboardPlugin.enableGlobalCapture` and `KeyboardPlugin.disableGlobalCapture`. This means if you set-up a bunch of key captures, but then need to disable them all for a while (perhaps you swap focus to a DOM text field), you can call `disableGlobalCapture` to do this, and when finished in the DOM you can enable captures again with `enableGlobalCapture`, without having to clear and re-create them all.
Default captures can be defined in the Game Config in the `input.keyboard.captures` object. The captures are actually stored in the `KeyboardManager` class. The `KeyboardPlugin` is just a proxy to methods in the Keyboard Manager, but is how you should interface with it.
* `KeyboardPlugin.addCapture` is a new method that allows you to define a set of keycodes to have the default browser behaviors disabled on.
* `KeyboardPlugin.removeCapture` is a new method that removes specific previously set key captures.
* `KeyboardPlugin.clearCaptures` is a new method that removes all key captures.
* `KeyboardPlugin.getCaptures` is a new method that returns an array of all current key captures.
* `KeyboardPlugin.enableGlobalCapture` is a new method that enables any key captures that have been created.
* `KeyboardPlugin.disableGlobalCapture` is a new method that disables any key captures that have been created, without removing them from the captures list.
* `KeyboardPlugin.addKey` has a new boolean argument `enableCapture`, which is true by default, that will add a key capture for the Key being created.
* `KeyboardPlugin.addKeys` has a new boolean argument `enableCapture`, which is true by default, that will add a key capture for any Key created by the method.
#### Other Keyboard Updates and Fixes
* There is a new class called `KeyboardManager`. This class is created by the global Input Manager, if keyboard access has been enabled in the Game config. It's responsible for handling all browser keyboard events. Previously, the `KeyboardPlugin` did this. Which meant that every Scene that had its own Keyboard Plugin was binding more native keyboard events. This was causing problems with parallel Scenes when needing to capture keys. the `KeyboardPlugin` class still exists, and is still the main point of interface when you call `this.input.keyboard` in a Scene, but DOM event handling responsibility has been taken away from it. This means there's no only
one set of bindings ever created, which makes things a lot cleaner.
* There is a new Game and Scene Config setting `input.keyboard.capture` which is an array of KeyCodes that the Keyboard Plugin will capture all non-modified key events on. By default it is empty. You can populate it in the config, or use the new capture methods.
* The Keyboard Manager will now call `preventDefault` only on non-modified key presses, stopping the keyboard event from hitting the browser. Previously, capturing the R key, for example, would block a CTRL+R page reload, but it now ignores it because of the key modifier.
* `Key.emitOnRepeat` is a new boolean property that controls if the Key will continuously emit a `down` event while being held down (true), or emit the event just once, on first press, and then skip future events (false).
* `Key.setEmitOnRepeat` is a new chainable method for setting the `emitOnRepeat` property.
* The `KeyboardPlugin.addKeys` method has a new optional boolean `emitOnRepeat` which sets that property on all Key objects it creates as part of the call. It defaults to `false`.
* The `KeyboardPlugin.addKey` method has a new optional boolean `emitOnRepeat` which sets that property on the Key object it creates. It defaults to `false`.
* The `Key` class now extends EventEmitter and emits two events directly: `down` and `up`. This means you can listen for an event from a Key you've created, i.e.: `yourKey.on('up', handler)`.
* The following Key Codes have been added, which include some missing alphabet letters in Persian and Arabic: `SEMICOLON_FIREFOX`, `COLON`, `COMMA_FIREFOX_WINDOWS`, `COMMA_FIREFOX`, `BRACKET_RIGHT_FIREFOX` and `BRACKET_LEFT_FIREFOX` (thanks @wmateam)
* `Key.onDown` is a new method that handles the Key being pressed down, including down repeats.
* `Key.onUp` is a new method that handles the Key being released.
* `Key.destroy` is a new method that handles Key instance destruction. It is called automatically in `KeyboardPlugin.destroy`.
* The `Key.preventDefault` property has been removed. This is now handled by the global keyboard capture methods.
* `Key.metaKey` is a new boolean property which indicates if the Meta Key was held down when the Key was pressed. On a Mac the Meta Key is Command. On a Windows keyboard, it's the Windows key.
* `InputManager.keyboard` is a new property that instantiates the global Keyboard Manager, if enabled in the game config.
* The `KeyboardPlugin.addKey` method has a new boolean property `enableCapture` which automatically prevents default on the Key being created.
* The `KeyboardPlugin.addKeys` method has a new boolean property `enableCapture` which automatically prevents default on Keys being created.
* `Phaser.Input.Keyboard.ProcessKeyDown` has been removed as it's no longer required, `Key.onDown` handles it instead.
* `Phaser.Input.Keyboard.ProcessKeyUp` has been removed as it's no longer required, `Key.onUp` handles it instead.
* The Keyboard Manager has a property called `captures` which is an array of keycodes, as populated by the Game Config. Any key code in the array will have `preventDefault` called on it if pressed.
* `KeyboardPlugin.manager` is a new property that references the Keyboard Manager and is used internally.
* `KeyboardPlugin.target` has been removed as it's no longer used by the class.
* `KeyboardPlugin.queue` has been removed as it's no longer used by the class.
* `KeyboardPlugin.onKeyHandler` has been removed as it's no longer used by the class.
### Mouse and Touch Input - New Features, Updates and Fixes
* The Mouse Manager class has been updated to remove some commented out code and refine the `startListeners` method.
* When enabling a Game Object for input it will now use the `width` and `height` properties of the Game Object first, falling back to the frame size if not found. This stops a bug when enabling BitmapText objects for input and it using the font texture as the hit area size, rather than the text itself.
* `Pointer.smoothFactor` is a float-value that allows you to automatically apply smoothing to the Pointer position as it moves. This is ideal when you want something smoothly tracking a pointer in a game, or are need a smooth drawing motion for an art package. The default value is zero, meaning disabled. Set to a small number, such as 0.2, to enable.
* `Config.inputSmoothFactor` is a new property that allows you to set the smoothing factor for all Pointers the game creators. The default value is zero, which is disabled. Set in the game config as `input: { smoothFactor: value }`.
* `InputManager.transformPointer` has a new boolean argument `wasMove`, which controls if the pointer is being transformed after a move or up/down event.
* `Pointer.velocity` is a new Vector2 that contains the velocity of the Pointer, based on the current and previous positions. The velocity is smoothed out each frame, according to the `Pointer.motionFactor` property. This is done for more accurate gesture recognition. The velocity is updated based on Pointer movement, it doesn't require a button to be pressed first.
* `Pointer.angle` is a new property that contains the angle of the Pointer, in radians, based on the current and previous positions. The angle is smoothed out each frame, according to the `Pointer.motionFactor` property. This is done for more accurate gesture recognition. The angle is updated based on Pointer movement, it doesn't require a button to be pressed first.
* `Pointer.distance` is a new property that contains the distance of the Pointer, in radians, based on the current and previous positions. The distance is smoothed out each frame, according to the `Pointer.motionFactor` property. This is done for more accurate gesture recognition. The distance is updated based on Pointer movement, it doesn't require a button to be pressed first.
* `Pointer.motionFactor` is a new property that controls how much smoothing to apply to the Pointer positions each frame. This value is passed to the Smooth Step Interpolation that is used to calculate the velocity, angle and distance of the Pointer. It's applied every frame, until the midPoint reaches the current position of the Pointer. The default value is 0.2.
* The Input Plugin was emitting a `preUpdate` event, with the capital U, instead of `preupdate`. This has now been corrected. Fix #4185 (thanks @gadelan)
* `Pointer.updateMotion` is a new method that is called automatically, each step, by the Input Manager. It's responsible for calculating the Pointer velocity, angle and distance properties.
* `Pointer.time` is a new property that holds the time the Pointer was last updated by the Game step.
* `Pointer.getDistance` has been updated. If called while a button is being held down, it will return the distance between the Pointer's current position and it's down position. If called when a Pointer doesn't have a button down, it will return the historic distance between the up and down positions.
* `Pointer.getDistanceX` is a new method that will return the horizontal distance between the Pointer's previous and current coordinates. If called while a button is being held down, it will return the distance between the Pointer's current position and it's down position. If called when a Pointer doesn't have a button down, it will return the historic distance between the up and down positions.
* `Pointer.getDistanceY` is a new method that will return the horizontal distance between the Pointer's previous and current coordinates. If called while a button is being held down, it will return the distance between the Pointer's current position and it's down position. If called when a Pointer doesn't have a button down, it will return the historic distance between the up and down positions.
* `Pointer.getDuration` is a new method that will return the duration the Pointer was held down for. If the Pointer has a button pressed down at the time this method is called, it will return the duration since the Pointer's was pressed down. If no button is held down, it will return the last recorded duration, based on the time the Pointer button was released.
* `Pointer.getAngle` is a new method that will return the angle between the Pointer coordinates. If the Pointer has a button pressed down at the time this method is called, it will return the angle between the Pointer's `downX` and `downY` values and the current position. If no button is held down, it will return the last recorded angle, based on where the Pointer was when the button was released.
* In previous versions, the VisibilityHandler would create a `mousedown` listener for the game canvas and then call `window.focus` when detected (assuming the game config `autoFocus` property was `true`). Responsibility for this has now been handled to the Mouse Manager `onMouseDown` handler.
* In previous versions, the VisibilityHandler would create a `mouseout` listener for the game canvas and then set `game.isOver` when detected. Responsibility for this has now been handled to the Mouse Manager, which sets the new Input Manager `isOver` property directly.
* In previous versions, the VisibilityHandler would create a `mouseover` listener for the game canvas and then set `game.isOver` when detected. Responsibility for this has now been handled to the Mouse Manager, which sets the new Input Manager `isOver` property directly.
* The `Phaser.Game.isOver` property has been moved. You can now find it in the Input Manager and it's also accessible via the Input Plugin, which means you can do `this.input.isOver` from within a Scene. This makes more sense as it's input related and not a game level property.
* The Input Plugin has a new event you can listen to: `gameover`, which is triggered whenever the mouse or a pointer is moved over the Game canvas. Listen to it with `this.input.on('gameover')` from within a Scene.
* The Input Plugin has a new event you can listen to: `gameout`, which is triggered whenever the mouse or a pointer leaves the Game canvas. Listen to it with `this.input.on('gameout')` from within a Scene.
* The Game used to emit a `mouseover` event when the mouse entered the game canvas. This is no longer emitted by the Game itself and can instead be listened for using the new Input Plugin event `gameover`.
* The Game used to emit a `mouseout` event when the mouse left the game canvas. This is no longer emitted by the Game itself and can instead be listened for using the new Input Plugin event `gameout`.
* If the `window` object exists (which it will in normal browser environments) new `mouseup` and `touchend` event listeners are bound to it and trigger the normal `mouseup` or `touchend` events within the internal input system. This means if you will now get a `pointerup` event from the Input Plugin even if the pointer is released outside of the game canvas. Pointers will also no longer think they are still 'down' if released outside the canvas and then moved inside again in their new state.
* The window will now have focus called on it by the Touch Manager, as well as the Mouse Manager, is the `autoFocus` game config property is enabled.
* The Input Plugin has a new event you can listen to: `pointerdownoutside`, which is triggered whenever the mouse or a pointer is pressed down while outside of the Game canvas. Listen to it with `this.input.on('pointerdownoutside')` from within a Scene.
* The Input Plugin has a new event you can listen to: `pointerupoutside`, which is triggered whenever the mouse or a pointer is released while outside of the Game canvas. Listen to it with `this.input.on('pointerupoutside')` from within a Scene.
* `Pointer.downElement` is a new property that holds the target of the DOM Event that triggered when the Pointer was pressed down. If this is within the game, this will be the game canvas element.
* `Pointer.upElement` is a new property that holds the target of the DOM Event that triggered when the Pointer was released. If this is within the game, this will be the game canvas element.
### New Features
* You can now load external Scene files using the new `load.sceneFile` method. This allows you to dynamically load a Scene into the Scene Manager of your game, and swap to it at will. Please see the documentation and examples for further details.
* The data object being sent to the Dynamic Bitmap Text callback now has a new property `parent`, which is a reference to the Bitmap Text instance that owns the data object (thanks ornyth)
* The WebGL Renderer has a new method `clearPipeline`, which will clear down the current pipeline and reset the blend mode, ready for the context to be passed to a 3rd party library.
* The WebGL Renderer has a new method `rebindPipeline`, which will rebind the given pipeline instance, reset the blank texture and reset the blend mode. Which is useful for recovering from 3rd party libs that have modified the gl context.
* Game Objects have a new property called `state`. Use this to track the state of a Game Object during its lifetime. For example, it could move from a state of 'moving', to 'attacking', to 'dead'. Phaser itself will never set this property, although plugins are allowed to.
* Game Objects have a new method called `setState` which will set the state property in a chainable call.
* `BlendModes.ERASE` is a new blend mode that will erase the object being drawn. When used in conjunction with a Render Texture it allows for effects that let you erase parts of the texture, in either Canvas or WebGL. When used with a transparent game canvas, it allows you to erase parts of the canvas, showing the web page background through.
* `BlendModes.SOURCE_IN` is a new Canvas-only blend mode, that allows you to use the `source-in` composite operation when rendering Game Objects.
* `BlendModes.SOURCE_OUT` is a new Canvas-only blend mode, that allows you to use the `source-out` composite operation when rendering Game Objects.
* `BlendModes.SOURCE_ATOP` is a new Canvas-only blend mode, that allows you to use the `source-atop` composite operation when rendering Game Objects.
* `BlendModes.DESTINATION_OVER` is a new Canvas-only blend mode, that allows you to use the `destination-over` composite operation when rendering Game Objects.
* `BlendModes.DESTINATION_IN` is a new Canvas-only blend mode, that allows you to use the `destination-in` composite operation when rendering Game Objects.
* `BlendModes.DESTINATION_OUT` is a new Canvas-only blend mode, that allows you to use the `destination-out` composite operation when rendering Game Objects.
* `BlendModes.DESTINATION_ATOP` is a new Canvas-only blend mode, that allows you to use the `destination-atop` composite operation when rendering Game Objects.
* `BlendModes.LIGHTER` is a new Canvas-only blend mode, that allows you to use the `lighter` composite operation when rendering Game Objects.
* `BlendModes.COPY` is a new Canvas-only blend mode, that allows you to use the `copy` composite operation when rendering Game Objects.
* `BlendModes.XOR` is a new Canvas-only blend mode, that allows you to use the `xor` composite operation when rendering Game Objects.
* `RenderTexture.erase` is a new method that will take an object, or array of objects, and draw them to the Render Texture using an ERASE blend mode, resulting in them being removed from the Render Texture. This is really handy for making a bitmap masked texture in Canvas or WebGL (without using an actual mask), or for 'cutting away' part of a texture.
* There is a new boolean Game Config property called `customEnvironment`. If set to `true` it will skip the internal Feature checks when working out which type of renderer to create, allowing you to run Phaser under non-native web environments. If using this value, you _must_ set an explicit `renderType` of either CANVAS or WEBGL. It cannot be left as AUTO. Fix #4166 (thanks @jcyuan)
* `Animation.nextFrame` will advance an animation to the next frame in the sequence instantly, regardless of the animation time or state. You can call this on a Sprite: `sprite.anims.nextFrame()` (thanks rgk25)
* `Animation.previousFrame` will set an animation to the previous frame in the sequence instantly, regardless of the animation time or state. You can call this on a Sprite: `sprite.anims.previousFrame()` (thanks rgk25)
* `Geom.Intersects.PointToLine` has a new optional argument `lineThickness` (which defaults to 1). This allows you to determine if the point intersects a line of a given thickness, where the line-ends are circular (not square).
* `Geom.Line.GetNearestPoint` is a new static method that will return the nearest point on a line to the given point.
* `Geom.Line.GetShortestDistance` is a new static method that will return the shortest distance from a line to the given point.
* `Camera.getBounds` is a new method that will return a rectangle containing the bounds of the camera.
* `Camera.centerOnX` will move the camera horizontally to be centered on the given coordinate, without changing its vertical placement.
* `Camera.centerOnY` will move the camera vertically to be centered on the given coordinate, without changing its horizontally placement.
* `AnimationManager.exists` is a new method that will check to see if an Animation using the given key already exists or not and returns a boolean.
* `animationstart-key` is a new Animation key specific event emitted by a Game Object. For example, if you had an animation with a key of 'explode' you can now listen for `animationstart-explode`.
* `animationrestart-key` is a new Animation key specific event emitted by a Game Object. For example, if you had an animation with a key of 'explode' you can now listen for `animationrestart-explode`.
* `animationcomplete-key` is a new Animation key specific event emitted by a Game Object. For example, if you had an animation with a key of 'explode' you can now listen for `animationcomplete-explode`.
* `animationupdate-key` is a new Animation key specific event emitted by a Game Object. For example, if you had an animation with a key of 'explode' you can now listen for `animationupdate-explode`.
* The Animation class now extends the Event Emitter and dispatches events itself. This allows you to listen for events from a specific Animation, rather than via a Game Object. This is handy, for example, if you had an explosion animation that you wanted to trigger a sound effect when it started. You can now listen for the events from the Animation object directly.
* The Animation class now emits the `start` event when played (either forward, or in reverse) by any Game Object.
* The Animation class now emits the `restart` event when it restarts playing on any Game Object.
* The Animation class now emits the `complete` event when it finishes playing on any Game Object.
* The Animation Component has a new method called `chain` which allows you to line-up another animation to start playing as soon as the current one stops, no matter how it stops (either by reaching its natural end, or directly by having stop called on it). You can chain a new animation at any point, including before the current one starts playing, during it, or when it ends (via its `animationcomplete` callback). Chained animations are specific to a Game Object, meaning different Game Objects can have different chained animations without impacting the global animation they're playing.
* `CanvasTexture.drawFrame` is a new method that allows you to draw a texture frame to the CanvasTexture based on the texture key and frame given.
* `CanvasTexture.getIndex` is a new method that will take an x/y coordinate and return the Image Data index offset used to retrieve the pixel values.
* `CanvasTexture.getPixels` is a new method that will take a region as an x/y and width/height and return all of the pixels in that region from the CanvasTexture.
* `CanvasTexture.setPixel` is a new method that sets the given pixel in the CanvasTexture to the color and alpha values provided.
* `CanvasTexture.getData` is a new method that will extract an ImageData block from the CanvasTexture from the region given.
* `CanvasTexture.putData` is a new method that will put an ImageData block at the given coordinates in a CanvasTexture.
### Updates
* You can now modify `this.physics.world.debugGraphic.defaultStrokeWidth` to set the stroke width of any debug drawn body, previously it was always 1 (thanks @samme)
* `TextStyle.setFont` has a new optional argument `updateText` which will sets if the text should be automatically updated or not (thanks @DotTheGreat)
* `ProcessQueue.destroy` now sets the internal `toProcess` counter to zero.
* The `PathFollower.pathRotationVerticalAdjust` property has been removed. It was supposed to flipY a follower when it reversed path direction, but after some testing it appears it has never worked and it's easier to do this using events, so the property and associated config value are removed. The `verticalAdjust` argument from the `setRotateToPath` method has been removed as well.
* The config value `preserveDrawingBuffer` has been removed as it has never been used by the WebGL Renderer.
* `PluginManager.install` returns `null` if the plugin failed to install in all cases.
* `PluginFile` will now install the plugin into the _current_ Scene as long as the `start` or `mapping` arguments are provided.
* MATH_CONST no longer requires or sets the Random Data Generator, this is now done in the Game Config, allowing you to require the math constants without pulling in a whole copy of the RNG with it.
* The Dynamic Bitmap Text Canvas Renderer was creating a new data object every frame for the callback. It now uses the `callbackData` object instead, like the WebGL renderer does.
* `WebGLRenderer.setBlendMode` has a new optional argument `force`, which will force the given blend mode to be set, regardless of the current settings.
* The method `DisplayList.sortGameObjects` has been removed. It has thrown a runtime error since v3.3.0! which no-one even spotted, a good indication of how little the method is used. The display list is automatically sorted anyway, so if you need to sort a small section of it, just use the standard JavaScript Array sort method (thanks ornyth)
* The method `DisplayList.getTopGameObject` has been removed. It has thrown a runtime error since v3.3.0! which no-one even spotted, a good indication of how little the method is used (thanks ornyth)
* `WebGLRenderer.setFramebuffer` has a new optional boolean argument `updateScissor`, which will reset the scissor to match the framebuffer size, or clear it.
* `WebAudioSoundManager.onFocus` will not try to resume the Audio Context if it's still locked.
* `WebAudioSoundManager.onBlur` will not try to suspend the Audio Context if it's still locked.
* When using `ScenePlugin.add`, to add a new Scene to the Scene Manager, it didn't allow you to include the optional Scene data object. You can now pass this in the call (thanks @kainage)
* `Graphics.stroke` is a new alias for the `strokePath` method, to keep the calls consistent with the Canvas Rendering Context API.
* `Graphics.fill` is a new alias for the `fillPath` method, to keep the calls consistent with the Canvas Rendering Context API.
* `LoaderPlugin.sceneManager` is a new property that is a reference to the global Scene Manager, useful for Plugins.
* Whenever `Camera.roundPixels` was enabled it would use a bitwise operation to truncate the float (`x |= 0`) - this has been replaced across all files that used it, with a call to `Math.round` instead. This gives far better results when zooming cameras both in and out of a Scene, stopping thin gaps appearing between closely packed Game Objects.
* `AnimationManager.create` will now return a boolean `false` if the given key is invalid (i.e. undefined or falsey).
* `AnimationManager.create` will no longer raise a console warning if the animation key is already in use. Instead, it will return the animation belonging to that key. A brand new animation will only be created if the key isn't already in use. When this happens, the `add` event is emitted by the Animation Manager. If no event is emitted, the animation already existed.
* `ArcadePhysics.Body.destroy` will now only add itself to the World `pendingDestroy` list if the world property exists. This prevents `Cannot read property 'pendingDestroy' of undefined` errors if you try to delete a physics body in a callback and then immediately change Scene (which tells the physics work to also delete all bodies)
* The Animation Component `restart` method has had is sole `key` argument removed. Previously, you had to pass in the key of the animation you wished to reverse, but now you can just call the method directly, and as long as there is an animation playing, it will automatically start playing in reverse, without the nee for a key (the way it should have been originally)
* `Animation.play` and `playReverse` will now accept either a string-based key of the animation to play (like before), or you can pass in an Animation instance, and it will play that animation.
* `CanvasTexture.clear` now has 4 new optional arguments: `x, y, width, height` which allow you to define the region of the texture to be cleared. If not provided it will clear the whole texture, which is the same behavior as before.
* EarCut, the polygon triangulation library used by the Graphics and WebGL classes, has been upgraded from 2.1.1 to 2.1.4. 2.1.2 fixed a few race conditions where bad input would cause an error. 2.1.3 improved performance for bigger inputs (5-12%) and 2.1.4 fixed a race condition that could lead to a freeze on degenerate input.
* `TextureTintPipeline.batchQuad` and `batchTri` have two new optional arguments `texture` and `unit` which are used to re-set the batch texture should the method cause a batch flush.
* `TextureTintPipeline.requireTextureBatch` is a new internal method that helps speed-up the creation of texture batches. It is used in conjunction with `setTexture2D` and `pushBatch`.
* `TextureTintPipeline.flush` and `TextureTintPipeline.pushBatch` have been optimized to handle zero based texture units as priority. They've also been refactored to avoid creation of empty texture batches.
* The `WebGLRenderer.setTexture2D` method has a new optional argument `flush` which controls if the pipeline is flushed if the given texture is new, or not. This is used internally to skip flushing during an existing flush.
* The Tilemap Layer `width` and `height` properties are now based on the tilemap tile sizes multiplied by the layer dimensions. This corrects an issue with layer sizes being wrong if you called `setBaseTileSize` on a Map.
* The WebGLRenderer will now clear the framebuffer at the start of every render.
* `WebGLRenderer.setScissor` now has a new optional argument `drawingBufferHeight` which allows you to specify the drawing buffer height, rather than use the renderers default value.
* `WebGLRenderer.pushScissor` now has a new optional argument `drawingBufferHeight` which allows you to specify the drawing buffer height, rather than use the renderers default value.
* `WebGLRenderer.preRender` now calls `gl.clearColor` in order to restore the background clear color in case something, like a Render Texture, has changed it.
### Bug Fixes
* The Rectangle Shape object wouldn't render if it didn't have a stroke, or any other objects on the display list (thanks mliko)
* When using a font string instead of setting `fontFamily`, `fontSize` and `fontStyle` in either `Text.setStyle` or `setFont`, the style properties wouldn't get set. This isn't a problem while creating the text object, only if modifying it later (thanks @DotTheGreat)
* `Text.toJSON` wasn't saving the font style when using the "font" shorthand to create it. It now saves it correctly. Fix #4141 (thanks @divillysausages)
* Disabling camera bounds and then moving the camera to an area in a Tilemap that did not have any tile information would throw an `Uncaught Reference error` as it tried to access tiles that did not exist (thanks @Siyalatas)
* Fixed an issue where Sprite Sheets being extracted from a texture atlas would fail if the sheet was either just a single column or single row of sprites. Fix #4096 (thanks @Cirras)
* If you created an Arcade Physics Group without passing a configuration object, and passing an array of non-standard children, it would throw a classType runtime error. It now creates a default config object correctly (thanks @pierpo)
* The `Camera.cull` method has been restructured so it now calculates if a Game Object is correctly in view or not, before culling it. Although not used internally, if you need to cull objects for a camera, you can now safely use this method. Fix #4092 (thanks @Cirras)
* The Tiled Parser would ignore animated tile data if it was in the new Tiled 1.2 format. This is now accounted for, as well as 1.0 (thanks @nkholski)
* `Array.Matrix.ReverseRows` was actually reversing the columns, but now reverses the rows.
* `Array.Matrix.ReverseColumns` was actually reversing the rows, but now reverses the columns.
* UnityAtlas now sets the correct file type key if using a config file object.
* Starting with version 3.13 in the Canvas Renderer, it was possible for long-running scripts to start to get bogged-down in `fillRect` calls if the game had a background color set. The context is now saved properly to avoid this. Fix #4056 (thanks @Aveyder)
* Render Textures created larger than the size of the default canvas would be automatically clipped when drawn to in WebGL. They now reset the gl scissor and drawing height property in order to draw to their full size, regardless of the canvas size. Fix #4139 (thanks @chaoyang805 @iamchristopher)
* The `cameraFilter` property of a Game Object will now allow full bitmasks to be set (a value of -1), instead of just those > 0 (thanks @stuartkeith)
* The `PathFollower.startFollow` method now properly uses the `startAt` argument to the method, so you can start a follower off at any point along the path. Fix #3688 (thanks @DannyT @diteix)
* Static Circular Arcade Physics Bodies now render as circles in the debug display, instead of showing their rectangle bounds (thanks @maikthomas)
* Changing the mute flag on an `HTML5AudioSound` instance, via the `mute` setter, now works, as it does via the Sound Manager (thanks @Waclaw-I @neon-dev)
* Changing the volume on an `HTML5AudioSound` instance, via the `volume` setter, now works, as it does via the Sound Manager (thanks @Waclaw-I)
* The Dynamic Tilemap Layer WebGL renderer was drawing tiles at the incorrect position if the layer was scaled. Fix #4104 (thanks @the-realest-stu)
* `Tile.tileset` now returns the specific Tileset associated with the tile, rather than an array of them. Fix #4095 (thanks @quadrupleslap)
* `Tile.getCollisionGroup` wouldn't return the correct Group after the change to support multiple Tilesets. It now returns the group properly (thanks @jbpuryear)
* `Tile.getTileData` wouldn't return the correct data after the change to support multiple Tilesets. It now returns the tile data properly (thanks @jbpuryear)
* The `GetTileAt` and `RemoveTileAt` components would error with "Cannot read property 'index' of undefined" if the tile was undefined rather than null. It now handles both cases (thanks @WaSa42)
* Changing `TileSprite.width` or `TileSprite.height` will now flag the texture as dirty and call `updateDisplayOrigin`, allowing you to resize TileSprites dynamically in both Canvas and WebGL.
* `RandomDataGenerator.shuffle` has been fixed to use the proper modifier in the calculation, allowing for a more even distribution (thanks wayfinder)
* The Particle Emitter was not recycling dead particles correctly, so it was creating new objects every time it emitted (the old particles were then left to the browsers gc to clear up). This has now been recoded, so the emitter will properly keep track of dead particles and re-use them (thanks @Waclaw-I for the initial PR)
* `ParticleEmitter.indexSortCallback` has been removed as it's no longer required.
* `Particle.index` has been removed, as it's no longer required. Particles don't need to keep track of their index any more.
* The Particle Emitter no longer needs to call the StableSort.inplace during its preUpdate, saving cpu.
* `Particle.resetPosition` is a new method that is called when a particle dies, preparing it ready for firing again in the future.
* The Canvas `SetTransform` method would save the context state, but it wasn't restored at the end in the following Game Objects: Dynamic Bitmap Text, Graphics, Arc, Curve, Ellipse, Grid, IsoBox, IsoTriangle, Line, Polygon, Rectangle, Star and Triangle. These now all restore the context, meaning if you're using non-canvas sized cameras in Canvas mode, it will now render beyond just the first custom camera.
* `Utils.Array.MoveUp` wouldn't let you move an array element to the top-most index in the array. This also impacted `Container.moveUp`.
* The Texture Tint Pipeline had a logic error that would cause every 2001st quad to either be invisible, or pick-up the texture of the 2000th quad by mistake. The `batchQuad` and `batchTri` methods how handle re-assigning the batch texture if they cause a batch flush as part of their process.
* Rotating Sprites that used a Normal Map wouldn't rotate the normal map with it, causing the lighting effects to become irregular. The normal map vectors are now rotated correctly (thanks @sercant for the PR and @fazzamatazz and @ysraelJMM for the report)
* Changing `scaleX` or `scaleY` on a `MatterImage` or `MatterSprite` would cause the body scale to become distorted as the setters didn't use the correct factor when resetting the initial scale. Fix #4206 (thanks @YannCaron)
* `StaticBody.reset` in Arcade Physics would ignore the `x` and `y` values given to it. If given, they're now used to reset the parent Game Object before the body is updated. Fix #4224 (thanks @samme)
* Static Tilemap Layers wouldn't render correctly if the layer used a tileset with a different size to the base map data (set via `setBaseTileSize`). They now render correctly in WebGL and Canvas, regardless of the base tile size.
* When using `RenderTexture.fill`, the `alpha` argument would be ignored in Canvas mode. It's now used when filling the RenderTexture.
* Fixed an issue in `WebGLRenderer.setScissor` where it was possible to try and compare the scissor size to a non-current scissor, if called outside of the render loop (i.e. from `RenderTexture.fill`) (thanks @hackhat)
* `RenderTexture.fill` in WebGL would use `gl.clear` and a clear color to try and fill the Render Texture. This only worked for full-canvas sized RenderTextures that didn't have a camera zoom applied. It has now been swapped to use the `drawFillRect` method of the Texture Tint Pipeline, allowing it to work properly regardless of camera zoom or size.
* `Container.getFirst` was using an incorrect Array Utils function `GetFirstElement`, when it should have been using `GetFirst`. It now uses the correct function. Fix #4244 (thanks @miran248)
* `List.getFirst` was using an incorrect Array Utils function `GetFirstElement`, when it should have been using `GetFirst`. It now uses the correct function. Fix #4244 (thanks @miran248)
* Fixed an issue where changing the viewport or size of a Camera belonging to a RenderTexture, it wouldn't impact the rendering and objects will still render outside of the viewport range. It's now converted to a proper gl scissor rect by the renderer, meaning you can limit the area rendered to by adjusting the internal Render Texture cameras viewport. Fix #4243 (thanks @hackhat)
* `CanvasTexture.destroy` is a new method that specifically handles the destruction of the CanvasTexture and all of its associated typed arrays. This prevents a memory leak when creating and destroying lots of RenderTextures (which are CanvasTexture backed). Fix #4239 (thanks @sjb933)
* The Alpha, Flip and Origin components have been removed from the Mesh Game Object (and by extension, Quad as well) as they are not used in the renderer and should be manipulated via the Mesh properties. Fix #4188 (thanks @enriqueto)
### Examples and TypeScript
Thanks to the following for helping with the Phaser 3 Examples and TypeScript definitions, either by reporting errors, or even better, fixing them:
@guilhermehto @samvieten @darkwebdev @RoryO @snowbillr @slothyrulez @jcyuan
### Phaser Doc Jam
The Phaser Doc Jam was a community-backed effort to try and get the Phaser 3 API documentation to 100% coverage. The Doc Jam is now over and I offer my thanks to the following who helped with docs in this release:
16patsle - @gurungrahul2 - @icbat - @samme - @telinc1 - anandu pavanan - blackhawx - candelibas - Diego Romero - doronlinder - Elliott Wallace - eric - Georges Gabereau - Haobo Zhang - henriacle - jak6jak - Jake Jensen - James Van Roose - JamesSkemp - joelahoover - Joey - madclaws - marc136 - Mihail Ilinov - naum303 - NicolasRoehm - nuane - rejacobson - Robert Kowalski - rodri042 - rootasjey - sawamara - scottwestover - sir13tommy - stetso - therealsamf - Tigran - willblackmore - zenwaichi
Also, the following helped with the docs outside of the Doc Jam:
@bryanwood @jestarray @matosummer @tfelix @imilo
## Version 3.15.1 - Batou - 16th October 2018
* Re-enabled Input Manager resizing, which had been left disabled by mistake.
## Version 3.15.0 - Batou - 16th October 2018
Note: We are releasing this version ahead of schedule in order to make some very important iOS performance and input related fixes available. It does not contain the new Scale Manager or Spine support, both of which have been moved to 3.16 as they require a few more weeks of development.
### New Features
* You can now set the `maxLights` value in the Game Config, which controls the total number of lights the Light2D shader can render in a single pass. The default is 10. Be careful about pushing this too far. More lights = less performance. Close #4081 (thanks @FrancescoNegri)
* `Rectangle.SameDimensions` determines if the two objects (either Rectangles or Rectangle-like) have the same width and height values under strict equality.
* An ArcadePhysics Group can now pass `{ enable: false }`` in its config to disable all the member bodies (thanks @samme)
* `Body.setEnable` is a new chainable method that allows you to toggle the enable state of an Arcade Physics Body (thanks @samme)
* `KeyboardPlugin.resetKeys` is a new method that will reset the state of any Key object created by a Scene's Keyboard Plugin.
* `Pointer.wasCanceled` is a new boolean property that allows you to tell if a Pointer was cleared due to a `touchcancel` event. This flag is reset during the next `touchstart` event for the Pointer.
* `Pointer.touchcancel` is a new internal method specifically for handling touch cancel events. It has the same result as `touchend` without setting any of the up properties, to avoid triggering up event handlers. It will also set the `wasCanceled` property to `true`.
### Updates
* `WebGLRenderer.deleteTexture` will check to see if the texture it is being asked to delete is the currently bound texture or not. If it is, it'll set the blank texture to be bound after deletion. This should stop `RENDER WARNING: there is no texture bound to the unit 0` errors if you destroy a Game Object, such as Text or TileSprite, from an async or timed process (thanks jamespierce)
* The `RequestAnimationFrame.step` and `stepTimeout` functions have been updated so that the new Frame is requested from raf before the main game step is called. This allows you to now stop the raf callback from within the game update or render loop. Fix #3952 (thanks @tolimeh)
* If you pass zero as the width or height when creating a TileSprite it will now use the dimensions of the texture frame as the size of the TileSprite. Fix #4073 (thanks @jcyuan)
* `TileSprite.setFrame` has had both the `updateSize` and `updateOrigin` arguments removed as they didn't do anything for TileSprites and were misleading.
* `CameraManager.remove` has a new argument `runDestroy` which, if set, will automatically call `Camera.destroy` on the Cameras removed from the Camera Manager. You should nearly always allow this to happen (thanks jamespierce)
* Device.OS has been restructured to allow fake UAs from Chrome dev tools to register iOS devices.
* Texture batching during the batch flush has been implemented in the TextureTintPipeline which resolves the issues of very low frame rates, especially on iOS devices, when using non-batched textures such as those used by Text or TileSprites. Fix #4110 #4086 (thanks @ivanpopelyshev @sachinhosmani @maximtsai @alexeymolchan)
* The WebGLRenderer method `canvasToTexture` has a new optional argument `noRepeat` which will stop it from using `gl.REPEAT` entirely. This is now used by the Text object to avoid it potentially switching between a REPEAT and CLAMP texture, causing texture black-outs (thanks @ivanpopelyshev)
* `KeyboardPlugin.resetKeys` is now called automatically as part of the Keyboard Plugin `shutdown` method. This means, when the plugin shuts down, such as when stopping a Scene, it will reset the state of any key held in the plugin. It will also clear the queue of any pending events.
* The `Touch Manager` has been rewritten to use declared functions for all touch event handlers, rather than bound functions. This means they will now clear properly when the TouchManager is shut down.
* There is a new Input constant `TOUCH_CANCEL` which represents canceled touch events.
### Bug Fixes
* Fixed a bug in the canvas rendering of both the Static and Dynamic Tilemap Layers where the camera matrix was being multiplied twice with the layer, causing the scale and placement to be off (thanks galerijanamar)
* If you set `pixelArt` to true in your game config (or `antialias` to false) then TileSprites will now respect this when using the Canvas Renderer and disable smoothing on the internal fill canvas.
* TileSprites that were set to be interactive before they had rendered once wouldn't receive a valid input hit area, causing input to fail. They now define their size immediately, allowing them to be made interactive without having rendered. Fix #4085 (thanks @DotTheGreat)
* The Particle Emitter Manager has been given a NOOP method called `setBlendMode` to stop warnings from being thrown if you added an emitter to a Container in the Canvas renderer. Fix #4083 (thanks @maximtsai)
* The `game.context` property would be incorrectly set to `null` after the WebGLRenderer instance was created (thanks @samme)
* The Touch Manager, Input Manager and Pointer classes all now handle the `touchcancel` event, such as triggered on iOS when activating an out of browser UI gesture, or in Facebook Instant Games when displaying an overlay ad. This should prevent issues with touch input becoming locked on iOS specifically. Fix #3756 (thanks @sftsk @sachinhosmani @kooappsdevs)
## Version 3.14.0 - Tachikoma - 1st October 2018
### Tilemap New Features, Updates and Fixes
* Both Static and Dynamic Tilemap layers now support rendering multiple tilesets per layer in both Canvas and WebGL. To use multiple tilesets pass in an array of Tileset objects, or strings, to the `createStaticLayer` and `createDynamicLayer` methods respectively.
* `Tilemap.createStaticLayer` now supports passing either a Tileset reference, or a string, or an array of them as the 2nd argument. If strings, the string should be the Tileset name (usually defined in Tiled).
* `Tilemap.createDynamicLayer` now supports passing either a Tileset reference, or a string, or an array of them as the 2nd argument. If strings, the string should be the Tileset name (usually defined in Tiled).
* `Tilemap.createBlankDynamicLayer` now supports passing either a Tileset reference, or a string, or an array of them as the 2nd argument. If strings, the string should be the Tileset name (usually defined in Tiled).
* Static Tilemap Layers now support tile rotation and flipping. Previously this was a feature only for Dynamic Tilemap Layers, but now both have it. Close #4037 (thanks @thisredone)
* `Tilemap.getTileset` is a new method that will return a Tileset based on its name.
* `ParseTilesets` has been rewritten so it will convert the new data structures of Tiled 1.2 into the format expected by Phaser, allowing you to use either Tiled 1.2.x or Tiled 1.1 JSON exports. Fix #3998 (thanks @martin-pabst @halgorithm)
* `Tilemap.setBaseTileSize` now sets the size into the LayerData `baseTileWidth` and `baseTileHeight` properties accordingly. Fix #4057 (thanks @imilo)
* Calling `Tilemap.renderDebug` ignored the layer world position when drawing to the Graphics object. It will now translate to the layer position before drawing. Fix #4061 (thanks @Zax37)
* Calling `Tilemap.renderDebug` ignored the layer scale when drawing to the Graphics object. It will now scale the layer before drawing. Fix #4026 (thanks @JasonHK)
* The Static Tilemap Layer would stop drawing all tiles from that point on, if it encountered a tile which had invalid texture coordinates (such as a tile from another tileset). It now skips invalid tiles properly again. Fix #4002 (thanks @jdotrjs)
* If you used a RenderTexture as a tileset then Dynamic Tilemap Layers would render the tiles inversed on the y-axis in WebGL. Fix #4017 (thanks @s-s)
* If you used a scaled Dynamic Tilemap Layer and rotated or flipped tiles, the tiles that were rotated or flipped would be positioned incorrectly in WebGL. Fix #3778 (thanks @nkholski)
* `StaticTilemapLayer.tileset` is now an array of Tileset objects, where-as before it was a single reference.
* `StaticTilemapLayer.vertexBuffer` is now an array of WebGLBuffer objects, where-as before it was a single instance.
* `StaticTilemapLayer.bufferData` is now an array of ArrayBuffer objects, where-as before it was a single instance.
* `StaticTilemapLayer.vertexViewF32` is now an array of Float3Array objects, where-as before it was a single instance.
* `StaticTilemapLayer.vertexViewU32` is now an array of Uint32Array objects, where-as before it was a single instance.
* `StaticTilemapLayer.dirty` is now an array of booleans, where-as before it was a single boolean.
* `StaticTilemapLayer.vertextCount` is now an array of integers, where-as before it was a single integer.
* `StaticTilemapLayer.updateVBOData()` is a new private method that creates the internal VBO data arrays for the WebGL renderer.
* The `StaticTilemapLayer.upload()` method has a new parameter `tilesetIndex` which controls which tileset to prepare the VBO data for.
* The `StaticTilemapLayer.batchTile()` method has a new parameter `tilesetIndex` which controls which tileset to batch the tile for.
* `StaticTilemapLayer.setTilesets()` is a new private method that creates the internal tileset references array.
* `DynamicTilemapLayer.tileset` is now an array of Tileset objects, where-as before it was a single reference.
* `DynamicTilemapLayer.setTilesets()` is a new private method that creates the internal tileset references array.
### New Features
* `bodyDebugFillColor` is a new Matter Physics debug option that allows you to set a color used when drawing filled bodies to the debug Graphic.
* `debugWireframes` is a new Matter Physics debug option that allows you to control if the wireframes of the bodies are used when drawing to the debug Graphic. The default is `true`. If enabled bodies are not filled.
* `debugShowInternalEdges` is a new Matter Physics debug option that allows you to set if the internal edges of a body are rendered to the debug Graphic.
* `debugShowConvexHulls` is a new Matter Physics debug option that allows you to control if the convex hull of a body is drawn to the debug Graphic. The default is `false`.
* `debugConvexHullColor` is a new Matter Physics debug option that lets you set the color of the convex hull, if being drawn to the debug Graphic.
* `debugShowSleeping` is a new Matter Physics debug option that lets you draw sleeping bodies at 50% opacity.
* `Curves.Ellipse.angle` is a new getter / setter that handles the rotation of the curve in degrees instead of radians.
### Updates
* The Loader has been updated to handle the impact of you destroying the game instance while still processing files. It will no longer throw cache and texture related errors. Fix #4049 (thanks @pantoninho)
* `Polygon.setTo` can now take a string of space separated numbers when creating the polygon data, i.e.: `'40 0 40 20 100 20 100 80 40 80 40 100 0 50'`. This update also impacts the Polygon Shape object, which can now also take this format as well.
* The `poly-decomp` library, as used by Matter.js, has been updated to 0.3.0.
* `Matter.verts`, available via `this.matter.verts` from within a Scene, is a quick way of accessing the Matter Vertices functions.
* You can now specify the vertices for a Matter `fromVerts` body as a string.
* `TextureTintPipeline.batchTexture` has a new optional argument `skipFlip` which allows you to control the internal render texture flip Y check.
* The Device.OS check for `node` will now do a `typeof` first to avoid issues with rollup packaged builds needing to shim the variable out. Fix #4058 (thanks @hollowdoor)
* Arcade Physics Bodies will now sync the display origin of the parent Game Object to the body properties as part of the `updateBounds` call. This means if you change the origin of an AP enabled Game Object, after creation of the body, it will be reflected in the body position. This may or may not be a breaking change for your game. Previously it was expected that the origin should always be 0.5 and you adjust the body using `setOffset`, but this change makes a bit more sense logically. If you find that your bodies are offset after upgrading to this version then this is likely why. Close #4052 (thanks @SolarOmni)
* The `Texture.getFramesFromTextureSource` method has a new boolean argument `includeBase`, which defaults to `false` and allows you to set if the base frame should be returned into the array or not.
* There is a new Animation Event that is dispatched when an animation restarts. Listen for it via `Sprite.on('animationrestart')`.
* All of the Animation Events now pass the Game Object as the final argument, this includes `animationstart`, `animationrestart`, `animationrepeat`, `animationupdate` and `animationcomplete`.
* `Curves.Ellipse.rotation` is a getter / setter that holds the rotation of the curve. Previously it expected the value in degrees and when getting it returned the value in radians. It now expects the value in radians and returns radians to keep it logical.
* `Set.size` will now only set the new size if the value is smaller than the current size, truncating the Set in the process. Values larger than the current size are ignored.
* Arcade Physics `shutdown` will check to see if the world instance still exists and only try removing it if so. This prevents errors when stopping a world and then destroying it at a later date.
* `Text.setFont`, `Text.setFontFamily`, `Text.setFontStyle` and `Text.setStroke` will no longer re-measure the parent Text object if their values have not changed.
### Bug Fixes
* GameObjects added to and removed from Containers no longer listen for the `shutdown` event at all (thanks Vitali)
* Sprites now have `preDestroy` method, which is called automatically by `destroy`. The method destroys the Animation component, unregistering the `remove` event in the process and freeing-up resources. Fix #4051 (thanks @Aveyder)
* `UpdateList.shutdown` wasn't correctly iterating over the pending lists (thanks @felipeprov)
* Input detection was known to be broken when the game resolution was !== 1 and the Camera zoom level was !== 1. Fix #4010 (thanks @s-s)
* The `Shape.Line` object was missing a `lineWidth` property unless you called the `setLineWidth` method, causing the line to not render in Canvas only. Fix #4068 (thanks @netgfx)
* All parts of Matter Body now have the `gameObject` property set correctly. Previously only the first part of the Body did.
* When using `MatterGameObject` and `fromVerts` as the shape type it wouldn't pass the values to `Bodies.fromVertices` because of a previous conditional. It now passes them over correctly and the body is only set if the result is valid.
* The `Texture.getFramesFromTextureSource` method was returning an array of Frame names by mistake, instead of Frame references. It now returns the Frames themselves.
* When using `CanvasTexture.refresh` or `Graphics.generateTexture` it would throw WebGL warnings like 'bindTexture: Attempt to bind a deleted texture'. This was due to the Frames losing sync with the glTexture reference used by their TextureSource. Fix #4050 (thanks @kanthi0802)
* Fixed an error in the `batchSprite` methods in the Canvas and WebGL Renderers that would incorrectly set the frame dimensions on Sprites with the crop component. This was particularly noticeable on Sprites with trimmed animation frames (thanks @sergeod9)
* Fixed a bug where the gl scissor wasn't being reset during a renderer resize, causing it to appear as if the canvas didn't resize properly when `autoResize` was set to `true` in the game config. Fix #4066 (thanks @Quinten @hsan999)
* If a Game instance is destroyed without using the `removeCanvas` argument, it would throw exceptions in the `MouseManager` after the destroy process has run, as the event listeners were not unbound. They're not unbound, regardless of if the parent canvas is removed or not. Fix #4015 (thanks @garethwhittaker)
### Examples and TypeScript
A huge thanks to @presidenten for his work on the Phaser 3 Examples. You'll notice they now have a lovely screen shots for every example and the scripts generate them automatically :)
Also, thanks to the following for helping with the Phaser 3 Examples and TypeScript definitions, either by reporting errors, or even better, fixing them:
@madanus @truncs @samme
### Phaser Doc Jam
The [Phaser Doc Jam](http://docjam.phaser.io) is an on-going effort to ensure that the Phaser 3 API has 100% documentation coverage. Thanks to the monumental effort of myself and the following people we're now really close to that goal! My thanks to:
31826615 - @16patsle - @bobonthenet - @rgk - @samme - @shaneMLK - @wemyss - ajmetal - andiCR - Arian Fornaris - bsparks - Carl - cyantree - DannyT - Elliott Wallace - felixnemis - griga - Hardylr - henriacle - Hsaka - icbat - Kanthi - Kyle - Lee - Nathaniel Foldan - Peter Pedersen - rootasjey - Sam Frantz - SBCGames - snowbillr - Stephen Hamilton - STuFF - TadejZupancic - telinc1
If you'd like to help finish off the last parts of documentation then take a look at the [Doc Jam site](http://docjam.phaser.io).
## Version 3.13.0 - Yuuki - 20th September 2018
### Facebook Instant Games Plugin
Phaser 3.13 introduces the new Facebook Instant Games Plugin. The plugin provides a seamless bridge between Phaser and version 6.2 of the Facebook Instant Games SDK. Every single SDK function is available via the plugin and we will keep track of the official SDK to make sure they stay in sync.
The plugin offers the following features:
* Easy integration with the Phaser Loader so load events update the Facebook progress circle.
* Events for every plugin method, allowing the async calls of the SDK to be correctly inserted into the Phaser game flow. When SDK calls resolve they will surface naturally as a Phaser event and you'll know you can safely act upon them without potentially doing something mid-way through the game step.
* All Plugin methods check if the call is part of the supported APIs available in the SDK, without needing to launch an async request first.
* Instant access to platform, player and locale data.
* Easily load player photos directly into the Texture Manager, ready for use with a Game Object.
* Subscribe to game bots.
* The plugin has a built-in Data Manager which makes dealing with data stored on Facebook seamless. Just create whatever data properties you need and they are automatically synced.
* Support for FB stats, to retrieve, store and increment stats into cloud storage.
* Save Session data with built-in session length validation.
* Easy context switching, to swap between game instances and session data retrieval.
* Easily open a Facebook share, invite, request or game challenge window and populate the text and image content using any image stored in the Texture cache.
* Full Leaderboard support. Retrieve, scan and update leaderboard entries, as well as player matching.
* Support for in-app purchases, with product catalogs, the ability to handle purchases, get past purchases and consume previously unlocked purchases.
* Easily preload a set of interstitial ads, in both banner and video form, then display the ad at any point in your game, with in-built tracking of ads displayed and inventory available.
* Plus other features, such as logging to FB Analytics, creating short cuts, switching games, etc.
The plugin is fully documented and official tutorials and project templates will follow shortly.
### New Shape Game Objects
Phaser 3.13 has a new Game Object called `Shape`, which by itself isn't much use because it's a base class. However, extending that class are 11 different types of Shape (with more to come) and you can use it to create your own custom Shapes as well. Shapes are added to the display list in the exact same way as any other Game Object. For example:
```
this.add.rectangle(400, 300, 500, 120, 0x00ff00);
```
Here we're creating a new Rectangle shape. It's positioned at 400 x 300 in the Scene and has a size of 500 x 120 pixels. The final value is the fill color.
The thing to remember is that you can treat this Shape just like you'd treat any other Game Object. You can scale it, rotate it, alpha it, blend mode it, change its origin, give it a Camera scroll factor, put it inside a Container or Group, give it input abilities or even give it a physics body. It is, to all intents and purposes, a normal Game Object. The only difference is that when rendering it uses its own special bit of display code.
The shapes available are as follows:
* `GameObject.Arc` - The arc allows you to draw either a circle, or part of a circle. You can set the start and end angle, if the rotation is clockwise or not, and even set the number of iterations the arc will use during rendering.
* `GameObject.Curve` - The Curve Shape can take any Phaser Curve object, such as a Spline or Bezier Curve, and add it to the display list.
* `GameObject.Ellipse` - An ellipse shape, which is essentially a circle with a differing width and height. It can be filled or stroked (or both!) and as with the arc you can set the 'smoothness' of it, allowing you to decrease the number of points used when creating its polygon data.
* `GameObject.Grid` - The Grid Shape object allows you to generate them. You can set the width and height of the grid itself, as well as for the grid cells. The grid can either have a single color, or alternating cell colors and even have outline spacing between the cells, or not.
* `GameObject.Line` - Create a Line Shape drawn between any two points, with a color and thickness. In WebGL you can also specify a different thickness for the start and end of the line.
* `GameObject.Polygon` - A Polygon is effectively a list of points that is drawn between. The points can be provided in a number of different ways (as Vec2 objects, as an array, etc) and then you can either fill or stroke the resulting shape, or both.
* `GameObject.Rectangle` - Simple, but powerful and endlessly useful. Set a width and height and it'll display a Rectangle, with control over the size, fill color and stroke color.
* `GameObject.Star` - The Star shape does as its name suggests: it displays a star. You can control the number of points in the star as well as the inner and outer radius of it.
* `GameObject.Triangle` - A Triangular shape with full control over the points used to make it and its fill and stroke colors. Internally it uses the `batchFillTriangle` method in WebGL, making it actually faster to draw than a Quad! Use them happily for bullets or abstract space ships, or anything else you feel like.
* `GameObject.IsoTriangle` - This draws an isometric triangle, like a pyramid. You can control the colors of each face, if the pyramid is upside down or not and the width and height of it.
* `GameObject.IsoBox` - This draws an isometric box. You can set the colors for each face of the box, as well as the projection angle and also which of the 3 faces are drawn.
All of the Shape objects render in both Canvas and WebGL and are available via the Game Object Factory.
### Pointer and Input Event Updates
The specificity if the input events has been changed to allow you more control over event handling. Previously, the InputPlugin would emit the global `pointerdown` event first, and then the Game Object itself would emit the `pointerdown` event and finally the InputPlugin would emit the `gameobjectdown` event.
The order has now changed. The Game Object will dispatch its `pointerdown` event first. The InputPlugin will then dispatch `gameobjectdown` and finally the less specific of them all, `pointerdown` will be dispatched.
New in 3.13 is the ability to cancel this at any stage. All events are now sent an event object which you can call `event.stopPropagation()` on. This will immediately stop any further listeners from being invoked. If you call `stopPropagation()` after the first Game Object `pointerdown` event, then no more Game Object's will receive their callbacks and the InputPlugin will not dispatch either of its events.
This change has been introduced for `pointerdown`, `pointerup`, `pointermove`, `pointerover` and `pointerout`. No other data is included in the `event` object in this release.
* The Game Object `pointerdown` callback signature has changed. It used to send `pointer, x, y, camera` to the listener. It now sends `pointer, x, y, event` to the listener. If you still need the `camera` property you can get it from `pointer.camera`.
* The Game Object `gameobjectdown` callback signature has a new argument. It now sends `event` as the 3rd argument.
* The `pointerdown` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerdown` and `gameobjectdown`). This gives you the chance to cancel the event before the global listener receives it.
* The Game Object `pointerup` callback signature has a new argument. It now sends the `event` as the 4th argument.
* The Game Object `gameobjectup` callback signature has a new argument. It now sends `event` as the 3rd argument.
* The `pointerup` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerup` and `gameobjectup`). This gives you the chance to cancel the event before the global listener receives it.
* The Game Object `pointermove` callback signature has a new argument. It now sends the `event` as the 4th argument.
* The Game Object `gameobjectmove` callback signature has a new argument. It now sends `event` as the 3rd argument.
* The `pointermove` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointermove` and `gameobjectmove`). This gives you the chance to cancel the event before the global listener receives it.
* The Game Object `pointerover` callback signature has a new argument. It now sends the `event` as the 4th argument.
* The Game Object `gameobjectover` callback signature has a new argument. It now sends `event` as the 3rd argument.
* The `pointerover` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerover` and `gameobjectover`). This gives you the chance to cancel the event before the global listener receives it.
* The Game Object `pointerout` callback signature has a new argument. It now sends the `event` as the 2nd argument.
* The Game Object `gameobjectout` callback signature has a new argument. It now sends `event` as the 3rd argument.
* The `pointerout` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerout` and `gameobjectout`). This gives you the chance to cancel the event before the global listener receives it.
### Game Object List Updates
When Sprite's are created they are added to two lists within the Scene - the Display List and the Update List. Under 3.12 when a Scene was shut down it would emit a `shutdown` event, which Sprites listened out for. When they received it, they would destroy themselves.
After [profiling and testing](https://github.com/photonstorm/phaser/issues/4028) this process has changed slightly. Game Object's no longer listen for the Scene `shutdown` event. Instead, the Display List and Update List will iterate their children and call `destroy` on them in turn. If being destroyed by a Scene in this way, the child will skip several expensive operations in its destroy function. More importantly, in busy Scenes you no longer need thousands of event listeners registered. The result is that changing Scene is now up to 100% faster than before. You need not change your code to benefit from this, however, if you were relying on custom Game Objects listening for the Scene `shutdown` event natively, then this is no longer the case and you'll have to manually add that listener to your classes.
* The UpdateList will now clear out its internal `_list`, `_pendingRemoval` and `_pendingInsertion` lists on shutdown. Before, it would only clear `_list`.
* `GameObject.destroy` has a new optional boolean argument `fromScene`, which controls how the destroy process flows.
### Camera Render to Texture
In 3.12 a new Camera method called `setRenderToTexture` was introduced. However, it had known issues so was placed under the experimental flag and you were advised not to use it unless in testing.
Thanks to several fixes in this release the experimental flag has been dropped and it's now safe to try using this new feature in production.
The method sets the Camera to render to a texture instead of to the main canvas. The Camera will redirect all Game Objects it's asked to render to this texture. During the render sequence, the texture itself will then be rendered to the main canvas.
Doing this gives you the ability to modify the texture before this happens, allowing for special effects such as Camera specific shaders, or post-processing on the texture.
* `Camera.setRenderToTexture` is a new method that enables the Camera to render to a target texture instead of the main canvas, allowing for application of special effects at run-time.
* `Camera.clearRenderToTexture` is a new method that stops a Camera from rendering to a texture and frees-up all associated resources.
* `Camera.setPipeline` allows you to change the WebGL pipeline being used if the Camera is rendering to a texture, effectively swapping the active shader. Call with no arguments to clear the pipeline.
* `Camera.renderToTexture` is a boolean property that controls where the Camera renders. It can be toggled on the fly.
* `Camera.canvas` is a Canvas Element that the Camera will render to if running under the Canvas Renderer and rendering to a texture.
* `Camera.context` is a Rendering Context that the Camera will render to if running under the Canvas Renderer and rendering to a texture.
* `Camera.glTexture` is a WebGL Texture that the Camera will render to if running under the WebGL Renderer and rendering to a texture.
* `Camera.framebuffer` is a WebGL Frame Buffer that the Camera will render to if running under the WebGL Renderer and rendering to a texture.
* `Camera.pipeline` is the Pipeline that the Camera will render with if running under the WebGL Renderer and rendering to a texture with a pipeline set.
* If you set a Camera to render to a texture then it will emit 2 events during the render loop. First, it will emit the event `prerender`. This happens right before any Game Object's are drawn to the Camera texture. Then, it will emit the event `postrender`. This happens after all Game Object's have been drawn, but right before the Camera texture is rendered to the main game canvas. It's the final point at which you can manipulate the texture before it appears in-game.
### New Features
* The `Color` object has a new property `h` which represents the hue of the color. You can tween or adjust this property in real-time and it will automatically update the internal RGB values with it.
* The `Color` object has a new property `s` which represents the saturation of the color. You can tween or adjust this property in real-time and it will automatically update the internal RGB values with it.
* The `Color` object has a new property `v` which represents the lightness value of the color. You can tween or adjust this property in real-time and it will automatically update the internal RGB values with it.
* `Color.setFromHSV` is a new method that will set the color values based on the HSV values given.
* `Color.gray` is a new method that will set the color to be a shade of gray based on the amount given.
* `Color.random` is a new method that will set the color to be a random hue based on the min and max values given.
* `Color.randomGray` is a new method that will set the color to be a random grayscale based on the min and max values given.
* `Color.saturate` is a new method that will saturate the color based on the amount given. This is a chainable version of adjusting the saturation property directly.
* `Color.desaturate` is a new method that will desaturate the color based on the amount given. This is a chainable version of adjusting the saturation property directly.
* `Color.lighten` is a new method that will lighten the color based on the amount given. This is a chainable version of adjusting the value property directly.
* `Color.darken` is a new method that will darken the color based on the amount given. This is a chainable version of adjusting the value property directly.
* `Color.brighten` is a new method that will brighten the color based on the amount given.
* The `CanvasTexture` class has a new property `imageData` which contains the ImageData of the texture.
* The `CanvasTexture` class has a new property `data` which is a Uint8ClampedArray view into the `buffer`.
* The `CanvasTexture` class has a new property `pixels` which is a Uint32Array view into the `buffer`.
* The `CanvasTexture` class has a new property `buffer` which is an ArrayBuffer the same size as the context ImageData.
* The `CanvasTexture` class has a new method `update` which refreshes the ImageData and ArrayBuffer based on the texture contents.
* The `CanvasTexture` class has a new method `draw` which draws the given Image or Canvas element to the CanvasTexture, then updates the internal ImageData buffer and arrays.
* The `CanvasTexture` class has a new method `getPixel` which will get the color of a specific pixel from the Canvas Texture and store it in the returned Color object. It uses the ArrayBuffer to do this, which is extremely fast, allowing for quick iteration across the canvas data.
* The WebGLPipeline and WebGLRenderer have new a method `setFloat1v` which allows you to set a `uniform1fv` uniform value (thanks @Mattykins)
* The WebGLPipeline and WebGLRenderer have new a method `setFloat2v` which allows you to set a `uniform2fv` uniform value (thanks @Mattykins)
* The WebGLPipeline and WebGLRenderer have new a method `setFloat3v` which allows you to set a `uniform3fv` uniform value (thanks @Mattykins)
* The WebGLPipeline and WebGLRenderer have new a method `setFloat4v` which allows you to set a `uniform4fv` uniform value (thanks @Mattykins)
* `Text.setLineSpacing` is a new method that allows you to easily set the line spacing value of a Text object in a chainable call (thanks @RafelSanso)
### Updates
* The Graphics Canvas Renderer will now automatically call `beginPath` on the target context before processing the command stack. This has the effect of clearing off any sub-paths that may have persisted on the stack from previous Graphics objects or frames. This makes it more in-line with WebGL re: expectations when calling `Graphics.clear`.
* `initPipeline` now defaults to the Texture Tint Pipeline if nothing else is specified. This allowed me to remove explicit strings from 11 different Game Objects, saving some bytes in the process.
* The `RGBToHSV` function can now take an optional `out` argument, which is either a `HSVColorObject` or a `Color` object, and the results will be set into that object instead of creating a new one.
* The `HSVToRGB` function can now take an optional `out` argument, which is either a `HSVColorObject` or a `Color` object, and the results will be set into that object instead of creating a new one.
* `Color.setTo` has a new argument `updateHSV` which allows you to control if the internal HSV values are updated during the same call or not.
* The `Text._lineSpacing` property has been renamed to `lineSpacing` and made public, not private. You still set it in the same way, by passing a `lineSpacing` property to the Text configuration object, but internally it's now clearer.
* If a Scene is already active (i.e. running) and you call `start` on it (such as from another Scene) then it will shutdown the Scene first, before starting it again.
### Bug Fixes
* TileSprite.setTileScale would set the tile position by mistake, instead of the scale. Using the properties directly worked, but the method was incorrect (thanks @alexeymolchan)
* Calling `Text.setStyle` would make the Text vanish if you didn't provide a `resolution` property in the style configuration object. Calling `setStyle` now only changes the properties given in the object, leaving any previously changed properties as-is. Fix #4011 (thanks @okcompewter)
* In Matter.js if a body had its debug `render.visible` property set to `false` it wouldn't then render any other debug body beyond it. Now it will just skip bodies with hidden debug graphics (thanks @jf908)
* If you flagged a Tween as `paused` in its config, never started it, and then called `Tween.stop` it wouldn't ever be removed from the `_pending` array. It's now moved to the Tween Manager's destroy list, ready for removal on the next frame. Fix #4023 (thanks @goldfire)
* Game Objects would not remove themselves from the Scene's `shutdown` event handler when destroyed, leading to a build-up over time (thanks @goldfire)
* The WebGL Renderer will no longer try and just resize a canvas backed texture, instead it will properly delete it then re-create it. Fix #4016 (thanks @alexeymolchan)
* The Camera background for mini-Cameras (those positioned deep inside another Camera) would be offset incorrectly in WebGL, causing the background fills to be displaced (thanks @aaronfc)
* The WebGL Renderer now always enables the `SCISSOR_TEST`, this allows Game Objects that use the scissor (such as custom objects, or Bitmap Text) to render properly again.
* The Cameras `setScene` method, which is called automatically when a new Camera is created, will now call `updateSystem` which correctly increases the custom viewport counter. This fixes an issue with mini-cams inside of larger cameras not clipping their contents properly. If a Camera is moved to another Scene it also now correctly shrinks the total custom viewport counter.
* Due to the two fixes above another bug was fixed: The ability for you to swap between Cameras with and without `setRenderToTexture` enabled with custom shaders. Previously if you used this with a custom shader then only the first Camera using the shader would render, the rest would appear black. Now, all Cameras using the custom shader work correctly. As a result all of the 'experimental' Camera rendering properties from 3.12 have been moved to stable.
* If you destroyed a Game Object that had a custom cursor set during one of its input events the cursor didn't correctly reset. Fix #4033 (thanks @pantoninho)
* `RenderTexture.resize` wouldn't correctly resize the texture under WebGL. Fix #4034 (thanks @jbpuryear)
* Calling `setFrame` on a TileSprite wouldn't change the frame, it would just change the frame size. Fix #4039 (thanks @Jerenaux)
* `Zone.setRectangleDropZone` used the wrong `x` and `y` coordinates for the hit area, causing it to be offset from the zone itself after the changes made for issue #3865 in the 3.12 release.
### Examples, Documentation and TypeScript
My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs:
@johanlindfors @Arthur3DLHC @JamesSkemp
## Version 3.12.0 - Silica - 4th September 2018
### FlatTintPipeline Updates
In 3.11 I overhauled the TextureTintPipeline, the WebGL batch used to render all texture based Game Objects, such as Sprites. In this release I did the same to the FlatTintPipeline. This pipeline was used exclusively by the Graphics Game Object to draw filled and stroked primitives in WebGL. It was also used by classes such as the Camera in order to draw their colored backgrounds and flash / fade effects.
When I looked closely at the shaders being used by the texture and graphics pipelines I noticed they were virtually identical. Yet if you were to mix Graphics objects and Sprites in your game, it would cause a complete batch flush as it switched between the them as it rebound the shaders, adding to both the draw calls and gl ops per frame.
The more I looked through the graphics pipeline, the more I saw the same kind of things the texture one previously had: duplicate vars, in-line matrix operations and so on. So I worked through the process of refactoring it, boiling it down to just a handful of core methods and re-using methods the texture pipeline already had. The end result is that I've been able to remove the FlatTintPipeline entirely. This saves 42.3KB (unminifed) and removes 1000 lines of code from the build. Of course, lots of the methods were added to the texture pipeline, but that only increased from 730 sloc to 1087 sloc, a fraction of the amount before! And the benefits don't end there.
If you had any custom pipelines that extended the FlatTintPipeline please update them to extend the TextureTintPipeline instead. You'll likely need to remap a few methods, but most of them remain the same. Double-check the method signatures though.
The same pipeline can now draw both graphics and sprites, with the same shader and no texture swapping either. This means you can happily mix Graphics objects alongside Sprites and it won't cost any extra overhead at all. There are more benefits too, which are outlined in the list below.
* The TextureTintPipeline now has 100% jsdoc coverage.
* The removal of the FlatTintPipeline shaves 42.3KB and 1000 sloc from the bundle size.
* The Graphics fill and line styles are now cached in the pipeline, rather than being re-calculated for every primitive drawn.
* The new `batchTri` method will add a triangle to the vertex batch, either textured or filled.
* `drawFillRect` is a new method that will add an untransformed rectangle to the batch. These are used by things like Cameras to fill in background colors.
* `batchFillRect` has been moved to the TextureTintPipeline and has a new much more concise method signature.
* `batchFillTriangle` has been moved to the TextureTintPipeline and has a new much more concise method signature.
* `batchFillPath` has been moved to the TextureTintPipeline and has a new much more concise method signature.
* `batchLine` has been moved to the TextureTintPipeline.
* When drawing Graphics paths with a line width of 1 it will no longer spend any time drawing the line joins, speeding-up the rendering of 1px lines.
### WebGL Scissor Update
The process of managing scissors in the WebGLRenderer has been completely rewritten. Previously, the gl scissor was being constantly enabled and disabled for every Camera in your game, leading to pointless gl operations.
* Cameras have a new internal method `updateSystem` which is automatically called if you change any Camera viewport values. This in turn tells the Scene Manager if there are any cameras with custom viewports, in any Scene of your game. If there are not then the scissor is never even enabled or set, meaning zero gl ops! If your game uses full sized Cameras it now doesn't cost anything at all with regard to scissoring.
* If a new scissor is set it will now check to see if it's the same size and position as the current scissor, and if so, it'll skip setting it at all.
### Render Texture New Features and Updates
The Render Texture class has been rewritten from scratch and all Game Objects have been updated to support it. Previously it was very restricted in what you could do with it. It used to have a matrix stack for internal transforms, but this has been replaced with a Camera instead. This means you have the full power of a Camera system (scrolling, zooming, rotation) but it only impacts the contents of the Render Texture.
* The biggest update is the change in what the `draw` method can accept. Previously you had to pass in a texture and frame reference. This has changed, as has the method signature. It can now accept any of the following:
- Any renderable Game Object, such as a Sprite, Text, Graphics or TileSprite.
- Dynamic and Static Tilemap Layers.
- A Group. The contents of which will be iterated and drawn in turn.
- A Container. The contents of which will be iterated fully, and drawn in turn.
- A Scene. Pass in `Scene.children` to draw the whole display list.
- Another Render Texture.
- A Texture Frame instance.
- A string. This is used to look-up a texture from the Texture Manager.
* There is a new method `drawFrame` which allows you to pass in a string-based texture and frame key and have it drawn to the Render Texture.
* The new method `saveTexture` allows you to save the Render Texture into the Texture Manager using your own key. You can then use the Render Texture for any Game Object that accepts textures as a source, such as Sprites or even Tilemap Layers. You can add frame data to a Render Texture using the `RenderTexture.texture.add` method.
* The new `camera` property is an instance of a complete 2D Camera. You can use it to change the view into your Render Texture. Scroll, rotate, zoom, just like you would with a normal Camera, except it will only influence the objects being drawn to the Render Texture.
* All of the matrix-style methods have been removed: `save`, `translate`, `restore`, `scale`, `rotate`. You can now achieve the same thing by either transforming the object you want to draw to the Render Texture, or using the built-in Camera.
* You can now crop a Render Texture. Use the `setCrop` method to define the crop region.
See the fully complete documentation for more details and the extensive examples and tests created.
### Text Game Object New Features and Updates
The Text Game Object has been given an internal overhaul to make it more flexible. Some properties have been renamed or moved and new features added:
* Text can now be cropped in WebGL and Canvas! Use the `setCrop` method to crop the text.
* Text now keeps a reference to the renderer in the `renderer` property.
* The `canvasTexture` property has been removed.
* Text now has internal `texture` and `frame` properties. These replace the old `canvasTexture` but perform the same task, while allowing for texture cropping and much smaller renderer code.
* Previously, changing a Text object by setting its `text` property directly wouldn't change the text being rendered as using `setText` was the expected way to change what was being displayed. Internally the `text` property has been renamed to `_text` and flagged as private, and a new getter / setter for `text` has been added, which hands over to the `setText` method, meaning you can now use both ways of setting the text. Fix #3919 (thanks @hackhat @samid737)
### Tile Sprite Object New Features and Updates
The Tile Sprite Game Object has been given an internal overhaul to make it more flexible. Some properties have been renamed or moved and new features added:
* Tile Sprites can now be cropped in WebGL and Canvas! Use the `setCrop` method to crop the tile sprite.
* There is a new method `setTileScale` which will set the tile scale in a chainable call.
* There is a new internal `canvas` property. Tile Sprites work differently than before in Canvas mode: Previously they would use the `fillRect` command on the game canvas to draw themselves every frame, even if they hadn't changed. They now draw to an internal canvas only when their position or scale changes. This canvas is then drawn to the game canvas instead. It's faster, as it doesn't fillRect every frame and also allows you to draw them to other contexts, such as Render Textures.
* There are two new internal properties `_tilePosition` and `_tileScale` which are Vector 2s that hold the position and scale. Getters have been added, so use the same properties as before in your code.
* There are two new properties `displayTexture` and `displayFrame`. These replace the previous `texture` and `frame` properties and hold references to the source texture the Tile Sprite is using.
* The `canvasPattern` property has been renamed to `fillPattern`.
* The `oldFrame` property has been removed.
* The `canvasBuffer` property has been renamed to `fillCanvas`.
* The `canvasBufferCtx` property has been renamed to `fillContext`.
### Tilemap New Features and Updates
The Tilemap and Dynamic and Static Tilemap Layer classes now all support 4 different modes of render order for drawing the tiles. This allows you to control the z-order of the tiles during render. This feature was requested by @etienne (who provided the test maps too) - see the new examples in the Labs for better understand the impact this has.
The default is 'right-down', meaning it will order the tiles starting from the top-left, drawing to the right and then moving down to the next row.
The four draw orders are:
0 = right-down
1 = left-down
2 = right-up
3 = left-up
* Tilemap has a new property `renderOrder` which is a string based version of the render order, as used when new layers are created via the map. If the map is created from Tiled JSON data, it will use whatever render order has been specified in the map data.
* Tilemap has a new method `setRenderOrder`. This takes either an integer or a string-based version of the render order and stores it locally. It's then used during the creation of any layers from that point on.
* The DynamicTilemapLayer has a new method `setRenderOrder`. This takes either an integer or a string-based version of the render order and stores it locally. It's then used during rendering of the layer. You can change the value on the fly.
* The StaticTilemapLayer has a new method `setRenderOrder`. This takes either an integer or a string-based version of the render order and stores it locally. Under WebGL it will re-create the whole vertex buffer, using the new draw order. Under Canvas it uses it at run-time during rendering. You can change it on the fly.
* ParseJSONTiled now extracts the `renderorder` property from the Tiled JSON.
* MapData has a new `renderOrder` property, which is populated by the Tiled Parser.
### Matter.js Updates
The version of Matter.js used by Phaser has been updated from 0.13.1 to 0.14.2. To clarify why we don't include Matter via npm, it's because we use a customized version of Matter that includes extra features and optimizations not yet found in the official library.
Most of the updates were about documentation and module namespacing, however those relevant to Phaser are listed below. You can also view the full [Matter Change Log](https://github.com/liabru/matter-js/blob/master/CHANGELOG.md).
* fix Composite.bounds global issue, closes #627, closes #544 ([f7f77b4](https://github.com/liabru/matter-js/commit/f7f77b4)), closes [#627](https://github.com/liabru/matter-js/issues/627) [#544](https://github.com/liabru/matter-js/issues/544)
* updated pathseg library, closes #548, closes #602, closes #424 ([1e5758f](https://github.com/liabru/matter-js/commit/1e5758f)), closes [#548](https://github.com/liabru/matter-js/issues/548) [#602](https://github.com/liabru/matter-js/issues/602) [#424](https://github.com/liabru/matter-js/issues/424)
* fix Common.isElement on node, closes #535 ([ec38eeb](https://github.com/liabru/matter-js/commit/ec38eeb)), closes [#535](https://github.com/liabru/matter-js/issues/535)
* added Query.collides, closes #478 ([6593a72](https://github.com/liabru/matter-js/commit/6593a72)), closes [#478](https://github.com/liabru/matter-js/issues/478)
* fix `point` argument of Body.scale, closes #428 ([894c1ef](https://github.com/liabru/matter-js/commit/894c1ef)), closes [#428](https://github.com/liabru/matter-js/issues/428)
* fix Body.scale for compound bodies ([50a89d0](https://github.com/liabru/matter-js/commit/50a89d0))
* fix centroid for static compound bodies, closes #483 ([ece66e6](https://github.com/liabru/matter-js/commit/ece66e6)), closes [#483](https://github.com/liabru/matter-js/issues/483)
* fix Common.isElement, closes #501, closes #507, closes #459, closes #468, closes #517 ([18a0845](https://github.com/liabru/matter-js/commit/18a0845)), closes [#501](https://github.com/liabru/matter-js/issues/501) [#507](https://github.com/liabru/matter-js/issues/507) [#459](https://github.com/liabru/matter-js/issues/459) [#468](https://github.com/liabru/matter-js/issues/468) [#517](https://github.com/liabru/matter-js/issues/517)
* fix inertia change in Body.setMass, closes #378 ([f7d1877](https://github.com/liabru/matter-js/commit/f7d1877)), closes [#378](https://github.com/liabru/matter-js/issues/378)
* fix Vertices.chamfer radius argument, closes #467 ([3bceef4](https://github.com/liabru/matter-js/commit/3bceef4)), closes [#467](https://github.com/liabru/matter-js/issues/467)
### Camera 3D Plugin
Support for Camera 3D and Sprite 3D Game Objects have been removed from the core Phaser bundle and moved to an optional plugin.
You can find the source for Camera 3D in the new `plugins/camera3d` folder, along with a README file explaining how to now use the plugin in your games.
* When a Sprite3D object is added to a Camera via `Camera.add` it is now added to the Display and Update Lists. Fix #3945 (thanks @vvega)
### New Features
* `Camera.resolution` is a new read-only property that holds the current game config resolution that the camera is using. This is used internally for viewport calculations.
* `Text.resolution` and the method `Text.setResolution` allows you to control the resolution of a Static Text Game Object. By default it will be set to match the resolution set in the Game Config, but you can override it yourself via the TextStyle. It allows for much clearer text on High DPI devices, at the cost of larger internal Canvas textures for the Text - so please use with caution, as the more high res Text you have, the more memory it uses up. Fix #3528 (thanks @kirillbunin)
* `TransformMatrix.getCSSMatrix` will return a CSS transform matrix formatted string from the current matrix values.
* `CacheManager` now creates a new cache called `html` which is used to store all loaded HTML snippets.
* `FileType.HTML` is a new file type loader that will load an HTML snippet and store it in the new `html` cache. Access it via `load.html` (this method was previously used to load html to textures, please see `load.htmlTexture` for this feature now)
* `TransformMatrix.getX` is a new method that return the x component from the given x and y values based on the current matrix. This is used heavily in the pipelines.
* `TransformMatrix.getY` is a new method that return the y component from the given x and y values based on the current matrix. This is used heavily in the pipelines.
* `TransformMatrix.copyToArray` is a new method that will copy the matrix values to the given array. It's the counter-part of `copyFromArray`.
* `Graphics.setTexture` is a new WebGL only method that allows you to set a texture to be used when drawing the shapes on the Graphics object. You can also specify how the texture should be blended with the current fill or gradient colors. Note that the texture is not tiled, it is stretched to fit the shape being drawn.
* `Graphics.fillGradientStyle` is a new WebGL only method that allows you to set a gradient for the shapes being filled. You can control the colors at the 4 corners of a rectangle. The colors are then blended automatically in the shader. Use of this feature is limited. For example, you cannot gradient fill a whole path or an arc, as it's made up of lots of triangles. But for quick gradient backgrounds or buttons it's perfect.
* `Graphics.lineGradientStyle` is a new WebGL only method that allows you to set a gradient for the shapes being stroked. You can control the colors at the 4 corners of a rectangle. The colors are then blended automatically in the shader. Use of this feature is limited. For example, you cannot gradient stroke a whole path or an arc, as it's made up of lots of triangles. But for quick gradient lines it's perfect.
* `TextureManager.getBase64` is a new method that will take a texture frame key and return a base64 encoded version of the frame. You can also provide the image type and encoder options.
* Global Plugins now have a new optional `data` object, the contents of which are passed to the plugins `init` method. This allows users to pass data directly into a plugin when added in the config: `{ key: 'BankPlugin', plugin: BankPluginV3, start: true, data: { gold: 5000 } }` or when adding a plugin via the `install` method (thanks @samme)
* You can now play animations in reverse! Use the new `Sprite.anims.playReverse` method to play a pre-defined animation in reverse from its starting frame. Or call `Sprite.anims.reverse` to immediately reverse the flow of an already running animation. Animations running in reverse still count towards the repeat total and respect the yoyo flag (thanks @khaleb85 @Ben-Millions)
* The `ParticleEmitterManager` now has the Transform component. This means you can now set the position, rotation or scale of the Emitter Manager, and it will influence every Emitter it is rendering. The Managers transform is mixed with that of the Camera. This works in both Canvas and WebGL.
* `TextureManager.addRenderTexture` is a new method that will add a Render Texture into the Texture Manager, allowing you to use it as the texture for Game Objects just by using the texture key. Modifying the source Render Texture will immediately modify any Game Objects using it.
* TextureSource has a new boolean property `isRenderTexture` which is set automatically when it's created.
* The Canvas Renderer has a new method `setContext` which allows it to swap the context being drawn to by all draw operations. Call the method with no arguments to reset it to the default game canvas.
* If you set `window.FORCE_WEBGL` or `window.FORCE_CANVAS` in the window in which the Phaser game is loaded it will over-ride the renderer type setting in your game config, and force either WebGL or Canvas. This is handy for quickly testing the differences between renderers without having to do a new build each time.
* `TextureSource.source` is a new property that contains the original source of the Texture image. It is cleared when the source is destroyed.
* `TransformMatrix.copyToContext` is a new method that will copy the values from the Matrix to the given Canvas Rendering Context.
* `Phaser.Utils.String.UUID` will return an RFC4122 complaint UUID as a string. This is used internally to avoid cache key conflicts, but is exposed for your own use as well.
* There is a new `Crop` Component which is used by non-texture based Game Objects, such as Text and TileSprite. You either use `TextureCrop` or `Crop`, not both together on the same object.
* `TransformMatrix.setToContext` is a new method that will set the values from the Matrix to the given Canvas Rendering Context using setTransform rather than transform.
* `SetTransform` is a new Canvas Renderer function that consolidates the process of preparing a Game Object for rendering, without actually rendering it. This is used internally by the Graphics and Bitmap Text classes.
* The Texture Manager has a new method called `renameTexture` which will let you rename a texture, changing the key to the new one given. All existing Game Objects will still maintain their reference, even after a rename.
* When loading an SVG file you can now change the size of the SVG during the load process, before it is rendered to a texture. This is really helpful if you wish to increase SVGs that have small viewBoxes set, or want to try and reduce memory consumption from SVGs with extra large dimensions. You can either pass in a fixed width and height: `this.load.svg('morty', 'file.svg', { width: 300, height: 600 })` or you can provide a scale factor instead: `this.load.svg('morty', 'file.svg', { scale: 4 })` (thanks @ysraelJMM)
* `Polygon.Perimeter` will return the perimeter for the given Polygon (thanks @iamchristopher)
* `Polygon.GetPoints` will return an array of Point objects containing the coordinates of the points around the perimeter of the Polygon, based on the given quantity or stepRate values. This is available as a static function and as the `getPoints` method on a Polygon (thanks @iamchristopher)
### Updates
* The Camera class has been split into two: `BaseCamera` which contains all of the core Camera functions and properties, and would serve as a great base for you to extend for your own custom Cameras, and `Camera` which is the same class name as previously. `Camera` extends the Base Camera and adds in follower support and the Special Effects. You don't need to update your code, even if currently extending a Camera, as they work the same as before.
* `Camera.x` and `Camera.y` have been turned into getters / setters, mapped to the internal private values `_x` and `_y` respectively. This is so that setting the Camera viewport position directly will now update the new internal resolution calculation vars too.
* `Camera.setScene` will now set the Cameras `resolution` property at the same time and update the internal viewport vars.
* The `Cull Tiles` method used by the Dynamic Tilemap Layer has had a nice and significant optimization. It will now use the cull area dimensions to restrict the amount of tile iteration that takes place per layer, resulting in dramatic reductions in processing time on large layers, or multiple layers (thanks @tarsupin)
* `GameObject.willRender` now takes a Camera as its only argument and uses it within the check. This has allowed me to remove 23 duplicate checks spread across the various Game Objects, all of which did the same thing, saving both KB and CPU time as the flags were being checked twice in most cases.
* The file type loader `HTML` has been renamed to `HTMLTexture`. If you were using this then please change your calls from `load.html` to `load.htmlTexture`. The arguments remain the same.
* The `setBlendMode` method in the WebGL Renderer now returns a boolean. True if a new blend mode was set, otherwise false. Previously it returned a reference to the renderer instance.
* The method `batchVertices` in the TextureTintPipeline has been renamed to `batchQuad` which more accurately describes what it does.
* In ArcadePhysics `Body.setSize` you can now choose to not pass width and height values to the method. If you do this it will check to see if the parent Game Object has a texture frame, and if so, it will use the frame sizes for the Body dimensions (thanks @tarsupin)
* `PluginCache.destroyCorePlugins` will remove all core plugins from the cache. Be very careful calling this as Phaser cannot restart or create any new Scenes once this has been called.
* `PluginCache.destroyCustomPlugins` will remove all custom plugins from the cache.
* `PluginManager.destroy` will now clear all custom plugins from the Plugin Cache. This fixes an issue with not being able to destroy a Phaser game instance and restart it if it used a custom plugin (thanks jd.joshuadavison)
* `Game.destroy` has a new boolean argument `noReturn`. If set it will remove all Core plugins when the game instance is destroyed. You cannot restart Phaser on the same web page after doing this, so only set it if you know you're done and don't need to run Phaser again.
* The `MouseManager` will no longer process its native events if the manager reference has been removed (i.e. you move the pointer as the game is destroying itself)
* The `TouchManager` will no longer process its native events if the manager reference has been removed (i.e. you move the pointer as the game is destroying itself)
* `Particle.color` has been removed as it's now calculated during rendering to allow for Camera alpha support.
* The Game boot event flow has changed slightly. The Game will now listen for a `texturesready` event, which is dispatched by the Texture Manager when the default textures have finished processing. Upon receiving this, the Game will emit the `ready` event, which all the other systems listen for and respond to. The difference is that the Renderer uses the `texturesready` event to ensure that it is the first thing to be activated, before any other system.
* The WebGLRenderer has a new property `blankTexture` which is a reference to an empty 32x32 transparent WebGL Texture. This is used internally for things like rendering Graphics with no texture fills and where no other texture has been set.
* The WebGLRenderer has a new method `setBlankTexture` which forces it to set the blank texture as the current texture. This is used after drawing a Render Texture to ensure no other object tries to draw to itself.
* The StaticTilemapLayer has had the following properties and methods added to it: `skipCull`, `tilesDrawn`, `tilesTotal`, `cullPaddingX`, `cullPaddingY`, `cullCallback`, `setSkipCull` and `setCullPadding` as these are all used by the Canvas Static Layer renderer. Static Layers in 3.11 didn't render in Canvas because the cull values were missing, but now render correctly and can also be rendered to other targets, like a Render Texture.
* The Math.Snap methods `Snap.Floor`, `Snap.Ceil` and `Snap.To` have all gained a new optional boolean argument `divide`. If set the resulting snapped value will be divided by the gap amount before returning. This is handy if you're trying to quickly snap a value into a grid or array location.
* The `currentBlendMode` property has been removed from the Canvas Renderer and is no longer checked by any class. Blend modes are now set directly on the context to avoid state saving invalidation.
* The `currentAlpha` property has been removed from the Canvas Renderer and is no longer checked by any class. Alpha values are now set directly on the context to avoid state saving invalidation.
* `TextureCrop` and `Crop` have a new method `resetCropObject` which generates the crop data object required by Game Objects that support cropping. This allows us to remove duplicate code from a number of Game Objects and replace it with a single function call.
* The Canvas Renderer has a new `batchSprite` method that consolidates the process of drawing a texture-based Game Object to the canvas. It processes the alpha, blend mode and matrix calculations in a single function and now is used by nearly all Game Object canvas renderers.
* The `batchTexture` method in the Texture Tint Pipeline now supports cropped Game Objects and will adjust the drawn texture frame accordingly.
* The `Matrix Stack` Component has been removed. It's no longer used internally and was just wasting space.
* You can now specify the `lineHeight` of a Retro Font in the Retro Font Config object (thanks @FelixNemis)
* When a Static Tilemap Layer is generated in WebGL it will use the Cameras `roundPixels` value to clamp the tile coordinates.
* The `CanvasRenderer.DrawImage` function has been removed, as has the associated `drawImage` property from the Canvas Renderer as they're no longer used.
* The `CanvasRenderer.BlitImage` function has been removed, as has the associated `blitImage` property from the Canvas Renderer as they're no longer used.
* You can now access the Game instance directly from a Scene using `this.game` as long as it exists in the Scene's Injection Map, which it does by default. Be very careful what you do here: there's next to nothing you should actually use this for.
* `Camera.ignore` can now take nested-arrays of Game Objects and also supports both Groups and Containers.
* The `changedata` event dispatched by the Data Manager now includes the previous value as the 4th argument to the callback, so the event signature is now: `parent, key, value, previousValue` (thanks @iamchristopher)
* The call to `gl.clearColor` is now skipped when `clearBeforeRender` is set to `false` (thanks @goldfire)
* The calls to `DistanceBetween` have been replaced with `DistanceSquared` in the `closest` and `furthest` functions within Arcade Physics (thanks @Mursaat)
* The RandomDataGenerator will now create a default random seed if you instantiate your own version of the class (instead of using `Phaser.Math.RND`) and don't provide a seed for it (thanks michaeld)
* The Tilemap `createFromObjects` method will now add custom properties to the Game Objects. It works by checking if the property exists or not, and if not, it sets it in the Game Objects Data Manager (thanks @scalemailted @samme)
* In Matter.js if you scaled a Body it would only scale correctly once, due to the way Matter handles scaling internally. We now automatically reset the Matter scale before applying the new value, which allows you to keep the Phaser and Matter object scales in sync. Fix #3785 #3951 (thanks @bergben)
* The default Container Blend Mode is now `SKIP_TEST`. This allows you to either set a blend mode for a Container, in which case all children use that blend mode. Or, you can set a blend mode on the children and the children will render using their own blend modes, as the Container doesn't have one set. The WebGL and Canvas Renderer functions have also been updated to support this change. Fix #3684 (thanks @TadejZupancic)
* Previously the Input Manager would create a Touch handler unless the Game Config had `input.touch` set to `false` (the default was true). If no such property is set, it no longer defaults to `true` and instead is set to whatever `Device.input.touch` returns. On non-touchscreen desktops this means it will now only create one single Pointer, rather than two.
* The Arcade Physics Body `_tempMatrix` property has been removed. It was only used if the Body's Game Object had a parent. The matrix has been moved to the World instance instead, shared by all bodies.
* Arcade Physics World has gained two new private properties `_tempMatrix` and `_tempMatrix2`. These are used by all bodies in the simulation that need a temporal matrix for calculations, rather than having their own instances.
* The Input Manager has gained a new private property `_tempMatrix2`. This is used internally in the hitTest checks to avoid constant matrix creation.
* The Transform Matrix has a new method `applyInverse` which will take an x/y position and inverse translate it through the current matrix.
* Using `keyboard.addKeys("W, A, S, D")` would fail because of the spacing between the characters. `addKeys` will now trim the input allowing you to space characters out if you prefer (thanks @dhruvyad)
* Calling `setTimeScale` on the Sprite's Animation component will now set the time scale value and keep it set until you change it again. Previously it would be reset to 1 when a new animation was loaded into the component, but this no longer happens - once the time scale is set it remains in effect, regardless of which animations are played on the Sprite.
### Game Config Resolution Specific Bug Fixes
Setting the `resolution` property in the Game Config to a value other than 1 would cause various errors in the API. The following have been fixed:
* The game canvas would be sized incorrectly, unless you had enabled auto resizing. It now scales the canvas to the size given, maintaining the resolution. Fix #3468 (thanks @Legomite)
* Cameras with background colors set would display the filled color area at the wrong size. Camera fills now respect the resolution.
* The Camera Fade Effect would display the fade fill rectangle at the wrong size. Camera fades now respect the resolution.
* The Camera Flash Effect would display the fade fill rectangle at the wrong size. Camera flashes now respect the resolution.
* The Camera Shake Effect would shake the Camera using the wrong width values. Camera Shakes now respect the resolution.
* Input calculations would not factor in the Game Resolution correctly. If a Camera viewport was not at 0x0 or not the full size, or the Camera was rotated or zoomed, the input areas would be wrong if `resolution` was > 1. These are now factored in correctly and changing the resolution no longer breaks input. Fix #3606 (thanks @Secretmapper @thanh-taro)
### Bug Fixes
* The `setCrop` method stored its crop object on the prototype chain by mistake, causing all Images or Sprites that were cropped to display the same frame. The crop data has been moved to the Game Object instance, where it should be, fixing this issue (thanks NoxBrutalis)
* If an AudioFile failed to load and throw an incomplete error, it would cause the console.log to crash JavaScript when trying to log the error. It now only logs the message if it exists. Fix #3830 (thanks @kelostrada)
* Particles using a blend mode wouldn't render correctly after the updates in 3.11. If the blend mode changes during the processing of an emitter manager it'll now correctly rebind the texture, stopping the particles from vanishing. Fix #3851 (thanks @maxailloud)
* Adding an array of children to a Group would cause it to mistakenly think you were passing a config object. Fix #3854 (thanks @pedro-w)
* Graphics paths in WebGL would not render the line join between the final and the first path if the path was closed, leaving a noticeable gap if you used particularly thick strokes. If the path is closed it will now render the final line join properly.
* If a Mesh caused a batch flush it would fail to render as its texture was lost. It's now rebound correctly after the flush.
* `ArcadePhysics.closest` and `ArcadePhysics.furthest` used the wrong tree reference, causing them to throw errors (thanks @samme)
* `BlitterCanvasRenderer` would fail to render a Bob in Canvas mode if it was flipped (thanks @SBCGames)
* `RenderTexture.draw` would fail to draw the frame in Canvas mode (thanks @SBCGames)
* `ParticleEmitter` would fail to draw a textured particle in Canvas mode (thanks @SBCGames)
* `RenderTexture.preDestroy` will now release the canvas back to the CanvasPool if running in canvas mode (thanks @SBCGames)
* The `alpha` value is now always set for Render Textures in canvas mode, regardless of the previous alpha value in the renderer (thanks @SBCGames)
* Zone now calls `updateDisplayOrigin` in its constructor, causing the `displayOriginX` and `displayOriginY` values to now be correct if you create a Zone and then don't resize it. Fix #3865 (thanks @rexrainbow)
* The `CameraManager` was accidentally adding extra destroy event calls when a Scene was restarted, causing an `Uncaught TypeError: Cannot read property 'events' of null` when trying to destroy a game instance having swapped from a Scene to another, and back again. Fix #3878 (thanks @mbunby)
* RenderTextures in WebGL will now set the viewport size, stopping the console warning in Firefox. Fix #3823 (thanks @SBCGames)
* Particles now take the Cameras alpha value into consideration when calculating their final alpha values in WebGL. They previously ignored it. If you now alpha a Camera out all particles will change accordingly.
* The `CullTiles` updates from 3.11 didn't factor in the position of the Tilemap Layer to its bounds calculations, causing Static layers displayed out of the Camera viewport to never render in Canvas mode. The method has also been optimized further, with less divisions and less checks if culling is disabled.
* The Particle Emitter when running in Canvas wouldn't allow more than 1 emitter to use a blend mode (as seen in the Electric examples). The blend mode is properly set for each emitter now.
* The Blend Mode is now set directly in all Canvas Renderers without comparing it to what's stored in the Canvas Renderer. This fixes problems where the blend mode would be lost between two different Game Objects because they restored the context, but didn't update the renderer flag. Game Objects in Canvas can now mix and match blend modes across the display list.
* Matter.js has received a tiny update that prevents `collisionEnd` from triggering many times when it should only trigger once (thanks @mikewesthad)
* Graphics objects couldn't be set to be ignored by Cameras. Now every renderable Game Object can be ignored by a Camera, either directly or via a Container. The exception are Groups because they don't render and are non-exclusive parents.
* The Tilemap Culling function now uses the Tilemap tile dimensions for its bounds calculations, instead of the layer tile sizes, as they two don't have to match and it's the underlying grid size that takes precedence when calculating visible tiles. Fix #3893 (thanks @Zax37)
* The Arcade Physics `Body.speed` property is now set whenever you set the velocity via `setVelocity` or `setVelocityX` or `setVelocityY` which stops the body velocity being reset to zero if `useDamping` is enabled. Fix #3888 (thanks @samme)
* The `getPixelAlpha` method in the Texture Manager wasn't using the correct frame name. This is now passed in correctly. Fix #3937 (thanks @goldfire)
* The `getPixelAlpha` and `getPixel` methods in the Texture Manager would allow x/y coordinates from outside the cut area of a frame. It now tests to ensure they're within the frame. Fix #3937 (thanks @goldfire)
* A Game Object couldn't have a blend mode of `SKIP_TEST` set by using the getter or the `setBlendMode` method.
* In Arcade Physics the `World.disable` call was passing the wrong argument, so never disabling the actual body (thanks @samme)
* There was a visual bug with Rounded Rectangles in Canvas mode, due to the addition of the `overshoot` argument in the Graphics arc call. This has been fixed, so arcs will now render correctly and consistently in WebGL and Canvas and Rounded Rectangles are back to normal again too. Fix #3912 (thanks @valse)
* The `InputManager.inputCandidate` method, which determines if a Game Object can be interacted with by a given Pointer and Camera combination, now takes the full camera status into consideration. This means if a Camera is set to ignore a Game Object you can now no longer interact with it, or if the Camera is ignoring a Container with an interactive Game Object inside it, you cannot interact with the Container children anymore. Previously they would interact regardless of the Camera state. Fix #3984 (thanks @NemoStein @samid737)
* `Transform.getWorldTransformMatrix` has been recoded to iterate the transform parents correctly, applying the matrix multiplications as it goes. This (along with some changes in the Input Manager) fix the issue with Game Objects inside of Containers failing hit tests between certain angles. Fix #3920 (thanks @chaping @hackhat)
* Calling Arcade Physics `collide` during an `update` method wouldn't inject the results back into the Body parent, causing the bodies to carry on moving. Using Colliders worked, but manually checking did not. Now, both methods work. Fix #3777 (thanks @samme)
* The `setTintFill` method would ignore the `alpha` value of the Game Object in the shader. The alpha value is now blended with the tint fill, allowing you to properly alpha out tint-filled Game Objects. Fix #3992 (thanks @trl-bsd)
* Arcade Physics World `collideSpriteVsTilemapLayer` now syncs the collision results back to the body, allowing you to call `collide` from within an update loop once again. Fix #3999 (thanks @nkholski @mikewesthad)
* Arcade Physics Body `deltaX` and `deltaY` methods will now return the previous steps delta values, rather than zero. Fix #3987 (thanks @HaoboZ)
### Examples, Documentation and TypeScript
My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs:
@SBCGames @rgk @rook2pawn @robbintt @bguyl @halilcakarr @PhaserEditor2D @Edwin222 @tfelix @Yudikubota @hexus @guzmonne @ampled @thanh-taro @dcbriccetti @Dreaded-Gnu @padme-amidala @rootasjey @ampled @thejonanshow @polarstoat @jdjoshuadavison @alexeymolchan @samme @PBird @spontoreau @hypertrifle @kid-wumeng
Thanks to @khaleb85 for fixing the super-annoying lag on the API Docs pages when it hung the browser while indexing the search field.
## Version 3.11.0 - Leafa - 13th July 2018
### Camera - New Features, Updates and Fixes
* All of the 2D Camera classes are now 100% covered by JSDocs!
* All of the 3D Camera classes are now deprecated and will be removed in the next version. They will be moved to a stand-alone plugin.
* `Camera.alpha` (and its related method `Camera.setAlpha`) allows you to set an alpha level for the entire camera. This impacts everything it is rendering, even if those objects also have their own alpha values too. You can tween the property to make the camera contents fade in / out, or otherwise set it as needed in your game.
* `Camera.deadzone` (and its related method `Camera.setDeadzone`) allows you to specify the deadzone for a camera. The deadzone is a rectangular region used when a camera is following a target. If the target is within the deadzone then the camera will not scroll. As soon as the target leaves the deadzone, the camera will begin tracking it (applying lerp if needed.) It allows you to set a region of the camera in which a player can move freely before tracking begins. The deadzone is re-centered on the camera mid point every frame, meaning you can also use the rectangle for other in-game checks as needed.
* `Camera.pan` is a new Camera Effect that allows you to control automatic camera pans between points in your game world. You can specify a duration and ease type for the pan, and it'll emit events just like all other camera effects, so you can hook into the start, update and completion of the pan. See the examples and docs for more details.
@ -12,6 +844,8 @@
* `Camera.midPoint` is a new Vec2 property that is updated every frame. Use it to obtain exactly where in the world the center of the camera is currently looking.
* `Camera.displayWidth` is a new property that returns the display width of the camera, factoring in the current zoom level.
* `Camera.displayHeight` is a new property that returns the display height of the camera, factoring in the current zoom level.
* `Camera.worldView` is a new property, an instance of a Rectangle, that contains the dimensions of the area of the world currently visible by the camera. You can use it for intersection or culling tests that don't need to factor in camera rotation.
* `Camera.dirty` is a new boolean property. A dirty Camera has had either its viewport size, bounds, scroll, rotation or zoom levels changed since the last frame. The flag is reset in the `postCameraRender` method, but until that point can be checked and used.
* `Camera.centerOn` is a new method that will move the camera so its viewport is centered on the given coordinates. A handy way of jumping to different points around a map without needing to calculate the scroll offsets.
* The Camera bounds didn't factor in the camera zoom properly, meaning you would often not be able to reach the corners of a camera bound world at a zoom level other than 1. The bounds are now calculated each frame to ensure they match the zoom level and it will no longer allow you to scroll off the edge of the bounds. Fix #3547 (thanks @nkholski)
* `Camera.centerToBounds` didn't take the bounds offset into account, so bounds at non-zero positions wouldn't center properly. All bounds now center correctly. Fix #3706 (thanks @cyantree)
@ -42,6 +876,80 @@ There is a third game config property called `pixelArt`. If set to `true` it's t
* If in your game config you have enabled either pixel art mode or roundPixels, then all Cameras will have their `roundPixels` values set to `true` by default. You can toggle this by changing the `CameraManager.roundPixels` property, or change it on a camera-by-camera basis, as needed.
* `Camera.roundPixels` is now used across all rendering code for both Canvas and WebGL. Previously, it would check the renderer config value, but now all renderer code uses the camera value to decide if it should floor the drawing position or not.
### Texture Tint Pipeline - New Features, Updates and Fixes
The Texture Tint Pipeline has been rewritten to tidy up hundreds of lines of duplicate code and to move the responsibility of drawing to the Game Objects themselves. Previously, had you excluded say Tilemaps from your build of Phaser, the renderer would still include masses of code dealing with the drawing of them. This task has been moved to the Game Objects and the pipeline just provides a set of clean utility functions for batching, flushing and drawing.
The decision to make this change was not taken lightly. However, I felt that none of the pipelines actually lived up to their name. You could never actually pass objects through one pipeline to another as they didn't have entry and exit points and were instead just glorified singular batches. Although you could change the pipeline being used on a Game Object this action meant that every pipeline had to be responsible for every single type of Game Object, both now and in the future, and they were full of redundant stub functions as a result. The payload size was also considerable. It has now gone from 1,961 lines of code at 76 KB down to 729 lines of code and 27 KB. It's not the only file to benefit either. The `ForwardDiffuseLightPipeline` also reduced from 402 lines (15.7 KB) down to 159 lines and 6 KB. Sizes include comments and are un-minified. In a production bundle the difference will be even greater. This is work we will continue in the next release as we do the same updates to the FlatTintPipeline, responsible for rendering Graphics objects, and look at consolidating the shaders allowing you to use Graphics and Sprites mixed in the display list with no shader swapping cost.
* You can now set the WebGL batch size in the Game Config via the property `batchSize`. The default is 2000 before the batch will flush, which is a happy average between desktop and mobile. If targeting desktop specifically, you may wish to increase this value to reduce draw calls.
* There is a new method `batchVertices` which will add a vertices block to the current batch. This is now used internally by nearly all render functions.
* The shader has a new attribute: `tintEffect`. This is a single FLOAT.
* The vertex size has increased by 1 FLOAT to account for the extra shader attribute.
* All of the rendering functions now use the `TransformMatrix` class far more than before. This allows the matrix operations to be run-time compiled and cut down on masses of code.
* The `drawTexture` method has been removed. It has been replaced by `drawTextureFrame` which has a new and more concise signature. See the API docs for details.
* The `batchTileSprite` method has been removed. It is now handled in the TileSprite WebGL Render function.
* The `drawStaticTilemapLayer` method has been removed. It is now handled in the Static Tilemap Layer WebGL Render function.
* The `drawEmitterManager` method has been removed. It is now handled in the Particle Manager WebGL Render function.
* The `batchText` method has been removed. It is now handled in the Static Text WebGL Render function.
* The `batchDynamicTilemapLayer` method has been removed. It is now handled in the Dynamic Tilemap Layer WebGL Render function.
* The `batchMesh` method has been removed. It is now handled in the Mesh WebGL Render function.
* The `batchBitmapText` method has been removed. It is now handled in the BitmapText WebGL Render function.
* The `batchDynamicBitmapText` method has been removed. It is now handled in the DynamicBitmapText WebGL Render function.
* The `batchBlitter` method has been removed. It is now handled in the Blitter WebGL Render function.
Due to the changes in the Texture Tint Pipeline the `Textures.Frame` class has also been updated. The following changes concern the Frame UV data:
* Previously, the UV data spanned 8 properties: `x0`, `y0`, `x1`, `y1`, `x2`, `y2`, `x3` and `y3` and was stored in the `data.uvs` object. These have been replaced with directly accessible properties: `u0`, `v0`, `u1` and `v1`. These 4 properties are used directly in all renderer code now. Although it was clearer having 8 properties, 4 of them were just duplicates, so we've traded a little clarity for a smaller overall object and less dictionary look-ups.
* `Frame.uvs` (and the corresponding `Frame.data.uvs`) object has been removed.
### New Tint Effects
As well as tidying the Texture Tint Pipeline, I also updated the shader. It now has a new attribute 'tintEffect' which allows you to control how a tint is applied to a Game Object. The default way tinting worked was for the tint color values to be multiplied with the texture pixel values. This meant you were unable to do things like tint a Game Object white, because multiplying a color by white doesn't change it. The new tint mode allows you to literally replace the pixel color values.
* `setTintFill` is a new method available to all Game Objects that have the Tint component. It differs from `setTint` in that the colors literally replace the pixel values from the texture (while still respecting the alpha). This means you can now create effects such as flashing a sprite white if it gets hit, or red for damage, etc. You can still use different colors per corner of the Game Object, allowing you to create nice seamless gradient effects.
* `tintFill` is a new boolean property that allows you to toggle between the two different tint types: multiply or replace.
* `isTinted` is a new read-only boolean indicating if a Game Object is tinted or not. Handy for knowing if you need to clear a tint after an effect.
* `Mesh.tintFill` allows you to control the tint effect applied to the Mesh vertices when color blending.
The Tint component documentation has been overhauled to explain these differences in more detail, and you can find lots of new examples as well.
### New Texture Crop Component
There is a new Game Object Component called `TextureCrop`. It replaces the Texture Component (which still exists) and adds in the ability to crop the texture being used. This component is now being used by the `Sprite` and `Image` Game Objects.
* You can crop the frame being used via the new `setCrop` method. The crop is a rectangle that limits the area of the texture frame that is visible during rendering. Cropping a Game Object does not change its size, dimensions, physics body or hit area, it just changes what is shown when rendered. This is ideal for hiding part of a Sprite without using a mask, or for effects like displaying a progress or loading bar. Cropping works even when the Game Object is flipped, or is a trimmed frame from an atlas.
* You can toggle the crop on a Game Object by changing the `isCropped` boolean at any point.
* The crop is automatically re-applied when the texture or frame of a Game Object is changed. If you wish to disable this, turn off the crop before changing the frame.
### BitmapText New Features, Updates and Bug Fixes
* Multi-line BitmapText objects can now be aligned. The constructor has a new argument `align` which can accept either left-aligned (the default), center aligned, or right-aligned. Alignment works by calculating the longest line of text in the object and then offsetting the other lines to match it.
* `BitmapText.setCenterAlign` is a new chainable method to center-align the text.
* `BitmapText.setLeftAlign` is a new chainable method to left-align the text.
* `BitmapText.setRightAlign` is a new chainable method to right-align the text.
* `BitmapText.align` is a new property that holds the alignment of the text.
* `BitmapText.setFont` is a new method that allows you to change the font it is rendering with.
* Internally all of the BitmapText properties have been renamed with an underscore (i.e. `letterSpacing` is now `_letterSpacing`), so as to not change the API, getters and setters for them all have been added.
* Internally there is a new `dirty` flag that tracks if any part of the BitmapText has changed. This is used when getting the BitmapText's bounds object, as used in the renderer for line alignment, and in properties like `width` and `height`. The dirty flag ensures the bounds are only recalculated if something has changed, cutting down on un-necessary calculations.
* `GetBitmapTextSize`, which is used internally in the BitmapText Game Objects, will now produce different bounds from the previous version. Previously, the bounds were tight against the letters in the text. However, this meant the bounds were not properly aligned with the origin of the BitmapText, and consequently you'd get different bounds if the text consisted of different characters. The bounds are now calculated purely based on the glyph data and letter spacing values. This will give a far more consistent overall experience, but it does mean if you were using the bounds to position text previously, you'll need to revisit that code again. See issue #3799 for more details (and to discuss this further if you wish) (thanks @SBCGames)
* `GetBitmapTextSize` and its exposed method `BitmapText.getTextBounds` now factor in the display origin of the BitmapText into the `global` position returned.
* The `BitmapText` WebGL Renderer incorrectly calculated the font scale at very small sizes, causing characters to overlap when they shouldn't. Scale is now applied to the correct component parts in the render code.
* Under WebGL `BitmapText` would be cut off if you specified a resolution value > 1. Fix #3642 (thanks @kanthi0802)
* Under WebGL, `DynamicBitmapText` that had a crop set on it would fail to render if anything was above it on the display list. It now crops properly, no matter what is above or below it on the display list.
* The `DynamicBitmapText` class now extends the `BitmapText` class. This saves on lots of space in the bundle and consolidates functionality between the two. Please be aware of it if you have classes that extend either of them.
* If you were using the `displayCallback` in the `DynamicBitmapText` class it would generate a brand new object containing all the glyph data, every frame, for every glyph, and send it to the callback. This has been changed so it now uses a new cached local object: `callbackData`. This object is recycled for every glyph, stopping un-needed gc from building up.
### Dynamic Tilemap Layer New Features, Updates and Bug Fixes
* `DynamicTilemapLayer.tilesDrawn` is a read-only property that contains the number of tiles sent to the renderer in the previous frame.
* `DynamicTilemapLayer.tilesTotal` is a read-only property that contains the total number of tiles in the layer, updated every frame.
* `DynamicTilemapLayer.skipCull` and its associated chainable method `setSkipCull` allows you to control if the cameras should cull the layer tiles before rendering them or not. By default they will cull, to avoid over-rendering, but in some circumstances you may wish to disable this and can now do so by toggling this property.
* The `CullTiles` component, as used by the Dynamic Tilemap, has been recoded from scratch to take advantage of updates in the Camera system. It will now properly cull tiles, irrespective of the layer scale, or camera zoom. It also now supports the layers `skipCull` property, allowing you to override the culling. The Dungeon Generator labs demo now works again as a result of this fix, and has been updated with a debug mode and camera control UI. You can edit the example source to swap between 4 different dungeon layouts, from 2500 tiles up to 1 million tiles. There are limitations to the way the culling works though. If you rotate the camera you may find you see the cull edge. You can disable this using the new `skipCull` property. Fixing this also fixed #3818 (thanks @Mursaat)
* `DynamicTilemapLayer.cullPaddingX`, `cullPaddingY` and the associated chainable method `setCullPadding` allows you to control how many additional tiles are added into the cull rectangle when it is calculated. If you find that your camera size and zoom settings are causing tiles to get prematurely culled, resulting in clipping during scrolling, then set the `cullPadding` values to add extra layers of tiles to the calculations in both directions without needing to disable culling entirely.
* `DynamicTilemapLayer.cullCallback` allows you to change the function that is used to perform the tile culling. By default it will call `TilemapComponents.CullTiles` but you can override this to call any function you like. It is sent 3 arguments: the layer data, the camera and the array to store the tiles in. Using this feature you can now create whatever culling system you require, should the default one prove to not be suitable for your game. Fix #3811 (thanks @georgzoeller)
* Dynamic Tilemap Layers now properly support the Lights2D Pipeline. This means you can provide a normal map for the layer tileset and it'll illuminate with the Lights shader properly. See the new `light map` example in the labs for a demonstration. Note that there are limits on the number of tiles that can be rendered with lighting enabled. Fix #3544 (thanks @FrancescoNegri)
### New Features
* `Graphics.fillRoundedRect` will draw a stroked rounded rectangle to a Graphics object. The radius of the corners can be either a number, or an object, allowing you to specify different radius per corner (thanks @TadejZupancic)
@ -53,6 +961,14 @@ There is a third game config property called `pixelArt`. If set to `true` it's t
* `ScenePlugin.wake` (and the corresponding methods in Scene Systems and the Scene Manager) now has a new optional `data` argument, which is passed to the target Scene and emitted in its 'wake' event.
* `ScenePlugin.setActive` now has a new optional `data` argument, which is passed to the target Scene and emitted in its 'pause' or 'resume' events.
* `TileSprite.tileScaleX` and `tileScaleY` are two new properties that allow you to control the scale of the texture within the Tile Sprite. This impacts the way the repeating texture is scaled, and is independent to scaling the Tile Sprite itself. It works in both Canvas and WebGL mode.
* `TransformMatrix.copyFrom` is a new method that will copy the given matrix into the values of the current one.
* `TransformMatrix.multiplyWithOffset` is a new method that will multiply the given matrix with the current one, factoring in an additional offset to the results. This is used internally by the renderer code in various places.
* `Rectangle.Intersection` will take two Rectangle objects and return the area of intersection between them. If there is no intersection, an empty Rectangle is returned.
* `Pointer.prevPosition` is a new Vector2 that stores the previous position of the Pointer, prior to the most recent DOM event. You can use this when performing calculations between the old and current positions, such as for tracking the pointer speed.
* `Pointer.getInterpolatedPosition` is a new method that will return an array of smoothly interpolated values between the old and previous position of the Pointer. You can configure how many interpolation steps should take place (the default is 10) and provide an output array to store them in. This method is handy if you've got an object tracking a pointer and you want to ensure it has smooth movement (as the DOM will often process pointer events at a faster rate than the game loop can update).
* `TransformMatrix.copyFromArray` will populate a matrix from the given array of values. Where 0, 1, 2, 3, 4 and 5 map to a, b, c, d, e and f.
* `WebGLPipeline` has a new over-rideable method called `boot` which is called when the renderer and all core game systems have finished being set-up.
* `KeyboardPlugin.checkDown` is a new method that allows you to check if a Key is being pressed down or not in an update loop. The difference between this method and checking the `Key.isDown` property directly is that you can provide a duration to this method. For example, if you wanted a key press to fire a bullet, but you only wanted it to be able to fire every 100ms, then you can call this method with a `duration` of 100 and it will only return `true` every 100ms.
### Updates
@ -60,10 +976,19 @@ There is a third game config property called `pixelArt`. If set to `true` it's t
* The docs for the Loader `filecomplete` event said that you could listen for a specific file using its type and key, i.e.: `filecomplete-image-monster`, however, the code used an underscore instead of a hyphen. We feel the hyphen looks cleaner, so the Loader code has been updated, meaning you can now use the hyphen version of the event properly (thanks @NokFrt)
* If a Game Object is already being dragged, it cannot be dragged by another pointer (in multi-touch mode) until the original pointer has released it (thanks @rexrainbow)
* Calling `Tween.play` on a tween created via `TweenManager.create` wouldn't actually start playback until the tween was first added to the Tween Manager. Now, calling `play` will have it automatically add itself to the Tween Manager if it's not already in there. Fix #3763 (thanks @pantoninho)
* If the Blitter object has no Bob's to render it will now abort immediately, avoiding several context calls in Canvas mode.
* If the Blitter object has no Bobs to render it will now abort immediately, avoiding several context calls in Canvas mode.
* `Scene.run` will now pass the optional `data` object in all cases, no matter if it's waking, resuming or starting a Scene (thanks @rook2pawn)
* `ScenePlugin.start` and `ScenePlugin.restart` will now always queue the op with the Scene Manager, regardless of the state of the Scene, in order to avoid issues where plugins carry on running for a frame before closing down. Fix #3776 (thanks @jjalonso)
* The `batchTileSprite` method has been removed from the `TextureTintPipeline` class, because it is now handled internally by the Tile Sprite object itself.
* `Tileset.glTexture` is a new property that maps to the WebGL Texture for the Tileset image. It's used internally by the renderer to avoid expensive object look-ups and is set automatically in the `Tileset.setImage` method.
* `Frame.glTexture` is a new property that maps to the WebGL Texture for the Frames Texture Source image. It's used internally by the renderer to avoid expensive object look-ups and is set automatically in the `Frame` constructor.
* `TransformMatrix.e` and `TransformMatrix.f` are two new properties that are an alias for the `tx` and `ty` values.
* `Graphics.arc` has a new optional argument `overshoot`. This is a small value that is added onto the end of the `endAngle` and allows you to extend the arc further than the default 360 degrees. You may wish to do this if you're trying to draw an arc with an especially thick line stroke, to ensure there are no gaps. Fix #3798 (thanks @jjalonso)
* The TextureManager Sprite Sheet Parser will now throw a concise console warning if you specify invalid frame sizes that would result in no frames being generated (thanks @andygroff)
* The `Quad` Game Object now has a new `setFrame` method that allows you to change the frame being rendered by the Quad, including using frames that are part of a texture atlas. Fix #3161 (thanks @halgorithm)
* The `ScenePlugin` will now queue all of the following ops with the Scene Manager: `start`, `run`, `pause`, `resume`, `sleep`, `wake`, `switch` and `stop`. This means for all of these calls the Scene Manager will add the call into its queue and process it at the start of the next frame. This fixes #3812 and keeps things more predictable (thanks @Waclaw-I)
* `TransformMatrix.multiply` has a new optional argument `out` which is a matrix to store the multiplication results in. If not given it will act as before, multiplying the current matrix.
* `Zones` now have a NOOP `setAlpha` method, which allows them to be added into Containers (thanks @TadejZupancic)
* The `setPipeline` method now returns the instance of the Game Object on which it was called. It used to return the pipeline that was set, but this made it non-chainable which broke with the conventions set in all the other `set` methods. If you use `setPipeline` in your code anywhere to retrieve the pipeline reference, please use the `pipeline` property of the Game Object instead.
### Bug Fixes
@ -82,16 +1007,20 @@ There is a third game config property called `pixelArt`. If set to `true` it's t
* `ArrayUtils.AddAt` didn't calculate the array offset correctly if you passed an array in to be merged with an existing array. This also caused Container.addAt to fail if an array was passed to it. Fix #3788 (thanks @jjalonso)
* The `Pointer.camera` property would only be set if there was a viable Game Object in the camera view. Now it is set regardless, to always be the Camera the Pointer interacted with.
* Added the Mask component to Container. It worked without it, but this brings it in-line with the documentation and other Game Objects. Fix #3797 (thanks @zilbuz)
* The DataManager couldn't redefine previously removed properties. Fix #3803 (thanks @AleBles @oo7ph)
* The Canvas DrawImage function has been recoded entirely so it now correctly supports parent matrix and camera matrix calculations. This fixes an issue where children inside Containers would lose their rotation, and other issues, when in the Canvas Renderer. Fix #3728 (thanks @samid737)
* `clearMask(true)` would throw an exception if the Game Object didn't have a mask. Now it checks first before destroying the mask. Fix #3809 (thanks @NokFrt)
* In the WebGL `GeometryMask` the stencil has been changed from `INVERT` to `KEEP` in order to fix issues when masking Graphics objects and other complex objects. Fix #3807. This also fixes the issue where children in Containers would display incorrectly outside of a Geometry mask. Fix #3746 (thanks @zilbuz @oklar)
* `BitmapMask.destroy` will now remove the textures and framebuffers that it created from the WebGL Renderer as part of the destroy process. Fix #3771 (thanks @nunof07)
### Examples, Documentation and TypeScript
My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs:
@DannyT @squilibob @dvdbrink @t1gu1 @cyantree @DrevanTonder @mikewesthad
@DannyT @squilibob @dvdbrink @t1gu1 @cyantree @DrevanTonder @mikewesthad @tarsupin @shadowofsoul
Also, a special mention to @andygroff for his excellent work enhancing the search box on the examples site, and @hexus for his assistance completing the documentation for the Game Objects.
## Version 3.10.1 - Hayashi - 13th June 2018
### Bug Fixes

282
README.md
View file

@ -24,25 +24,29 @@ Grab the source and join the fun!
<div align="center"><img src="https://phaser.io/images/github/news.jpg"></div>
> 13th June 2018
> 16th October 2018
I'm pleased to announce that Phaser 3.10.0 is now available. This release represents just under a month's worth of work and is a huge version for us. It introduces a lot of significant new features into v3, including multi-touch support, custom cursors, pixel perfect detection, Scene isolated input events, new Input plugins, a brand new Gamepad system and plenty more. There are big changes in Arcade Physics too, with a new fixed timestep option, angular damping, speed improvements, support for time scaling across your whole physics simulation and, yes, even more. The Data Manager too has been given a real shot in the arm, and there are subtle but important changes to the Scene flow and Loader interactions.
Phaser 3.15 is now available. This is slightly ahead of schedule because we needed to get some important performance and iOS input related fixes released, without waiting for new features to be completed first.
There are, of course, plenty of bug fixes and updates too. I'd urge you to carefully read the Change Log, especially if upgrading from an earlier version in an existing project. Hundreds more areas have been covered with documentation too. An on-going battle which we're winning, albeit slowly.
This means that the new Scale Manager and Spine support have been moved to release 3.16 due towards the end of October. Please read the weekly Dev Logs for details about development.
3.10 is a huge release and represents tireless effort on my part to get it into this shape. My aim has always been to continue the mission of enhancing Phaser 3 as quickly as I can. It means releasing significant updates in relatively short periods of time. But it also means I'm jumping on bug reports as quickly as I can, keeping the issues list total nice and low (the vast majority of the items in there are feature requests now!) - a massive thank-you to all of you who support Phaser on Patreon and PayPal. It's your support that allows me to work on this full-time, to the benefit of everyone.
> 1st October 2018
I'm pleased to announce that Phaser 3.14 is now out. Hot on the heels of the massive 3.13 release, 3.14 brings some sought-after new features to the party, including support for the new Tiled Map Editor 1.2 file formats, as well as the long-requested feature allowing use of multiple tilesets per single tilemap layer.
There are also new features to make Matter JS debugging easier and body creation when using lists of vertices is now much cleaner too. It's never just features though. There are lots of important fixes and updates in 3.14, including a fix causing gl canvas resizing to fail, better handling of the game shutdown process and fixes for an issue with Graphics.generateTexture.
If you're building an active project on 3.13 then please upgrade to 3.14 and, as usual, report any issues you find on GitHub so we can look at them immediately. Also, in the 3.14 release we have completed over 1000 new areas of documentation. At the time of writing there are now just 1900 items in the API left to document, which may sound like a lot, but is a fraction of the tens of thousands already done! With our current progress we should have 100% documentation coverage within the next couple of months.
In case you missed the notice, Phaser 3.13 introduced the Facebook Instant Games Plugin. The plugin provides a seamless bridge between Phaser and version 6.2 of the Facebook Instant Games SDK. Every single SDK function is available via the plugin and we will keep track of the official SDK to make sure they stay in sync. My thanks to Facebook for helping make this possible.
Also new in 3.13 were the Shape Game Objects, which allows for quick addition of geometry onto the display list. Easily add rectangles, triangles, curves, stars and more into your game and treat them just like any other Game Object. Perfect for place-holder art, abstract style games or just really fast iterations game-jam style.
3.14 continues to represent the tireless effort on my part to get it fully production ready. I'm seeing lots more games being released with Phaser 3 and stacks of tutorials and plugins are starting to surface. My aim has always been to continue the mission of enhancing Phaser 3 as quickly as I can. It means releasing significant updates in relatively short periods of time. But it also means I'm jumping on bug reports as quickly as I can, keeping the issues list total nice and low (the vast majority of the items in there are feature requests now!) - a massive thank-you to all of you who support Phaser on Patreon and PayPal. It's your support that allows me to work on this full-time, to the benefit of everyone.
As always, please check out the [Change Log](#changelog) for comprehensive details about what recent versions contain.
**About Phaser 3**
After 1.5 years in the making, tens of thousands of lines of code, hundreds of examples and countless hours of relentless work: Phaser 3 is finally out. It has been a real labor of love and then some!
Please understand this is a bleeding-edge and brand new release. There are features we've had to leave out, areas of the documentation that need completing and so many cool new things we wanted to add. But we had to draw a line in the sand somewhere and 3.0.0 represents that.
For us this is just the start of a new chapter in Phaser's life. We will be jumping on bug reports as quickly as we can and releasing new versions rapidly. We've structured v3 in such a way that we can push out point releases as fast as needed.
We publish our [Developer Logs](https://phaser.io/phaser3/devlog) in the [Phaser World](https://phaser.io/community/newsletter) newsletter. Subscribe to stay in touch and get all the latest news from us and the wider Phaser community.
If you'd like to stay abreast of developments then I publish my [Developer Logs](https://phaser.io/phaser3/devlog) in the [Phaser World](https://phaser.io/community/newsletter) newsletter. Subscribe to stay in touch and get all the latest news from the core team and the wider community.
You can also follow Phaser on [Twitter](https://twitter.com/phaser_) and chat with fellow Phaser devs in our [Slack](https://phaser.io/community/slack) and [Discord](https://phaser.io/community/discord) channels.
@ -104,19 +108,20 @@ npm install phaser
[Phaser is on jsDelivr](https://www.jsdelivr.com/projects/phaser) which is a "super-fast CDN for developers". Include the following in your html:
```html
<script src="//cdn.jsdelivr.net/npm/phaser@3.10.1/dist/phaser.js"></script>
<script src="//cdn.jsdelivr.net/npm/phaser@3.15/dist/phaser.js"></script>
```
or the minified version:
```html
<script src="//cdn.jsdelivr.net/npm/phaser@3.10.1/dist/phaser.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/phaser@3.15/dist/phaser.min.js"></script>
```
### API Documentation
1. Go to https://photonstorm.github.io/phaser3-docs/index.html to read the docs online. Use the drop-down menus at the top to navigate the name spaces, classes and Game Objects lists. If you wish to run the docs locally you can ...
2. Checkout the [phaser3-docs](https://github.com/photonstorm/phaser3-docs) repository and then read the documentation by pointing your browser to the local `docs/` folder, and again selecting from the Classes or Namespaces links at the top of the page.
Go to https://photonstorm.github.io/phaser3-docs/index.html to read the docs online. Use the drop-down menus at the top to navigate the name spaces, classes and Game Objects lists.
Or, if you wish to run the docs locally you can checkout the [phaser3-docs](https://github.com/photonstorm/phaser3-docs) repository and then read the documentation by pointing your browser to the `docs/` folder.
The documentation for Phaser 3 is an on-going project. Please help us by searching the Phaser code for any instance of the string `[description]` and then replacing it with some documentation.
@ -130,7 +135,7 @@ As soon as we're happy with the accuracy of the TS defs we'll merge them into th
### Webpack
We use Webpack to build Phaser and we take advantage of its conditional build flag feature to handle renderer swapping. If you wish to use Webpack with Phaser then please use our [Phaser 3 Project Template](https://github.com/photonstorm/phaser3-project-template) as it's already set-up to handle the build conditions Phaser needs. Recent changes to our build steps mean you should now be able to us any other packager, like Parcel, without any config changes.
We use Webpack to build Phaser and we take advantage of its conditional build flag feature to handle renderer swapping. If you wish to use Webpack with Phaser then please use our [Phaser 3 Project Template](https://github.com/photonstorm/phaser3-project-template) as it's already set-up to handle the build conditions Phaser needs. Recent changes to our build steps mean you should now be able to use any other packager, like Parcel, without any config changes.
### License
@ -141,17 +146,60 @@ Phaser is released under the [MIT License](https://opensource.org/licenses/MIT).
<img src="https://phaser.io/images/github/learn.jpg" align="right">
Phaser 3 is so new the "paint is still wet", but tutorials and guides are starting to come out!
Tutorials and guides on Phaser 3 development are being published every week.
* [Getting Started with Phaser 3](https://phaser.io/tutorials/getting-started-phaser3) (useful if you are completely new to Phaser)
* [Making your first Phaser 3 Game](https://phaser.io/tutorials/making-your-first-phaser-3-game)
* [Phaser 3 Bootstrap and Platformer Example](https://phaser.io/news/2018/02/phaser-3-bootstrap-platformer)
* The [Complete Phaser 3 Game Development course](https://academy.zenva.com/product/html5-game-phaser-mini-degree/?a=13) contains over 15 hours of videos covering all kinds of important topics.
* Plus, there are [over 700 Phaser tutorials](http://phaser.io/learn) listed on the official website.
Also, please subscribe to the [Phaser World](https://phaser.io/community/newsletter) newsletter for details about new tutorials as they are published.
### Facebook Instant Games
Phaser 3.13 introduced the new [Facebook Instant Games](http://phaser.io/news/2018/10/facebook-instant-games-phaser-tutorial) Plugin. The plugin provides a seamless bridge between Phaser and version 6.2 of the Facebook Instant Games SDK. Every single SDK function is available via the plugin and we will keep track of the official SDK to make sure they stay in sync.
The plugin offers the following features:
* Easy integration with the Phaser Loader so load events update the Facebook progress circle.
* Events for every plugin method, allowing the async calls of the SDK to be correctly inserted into the Phaser game flow. When SDK calls resolve they will surface naturally as a Phaser event and you'll know you can safely act upon them without potentially doing something mid-way through the game step.
* All Plugin methods check if the call is part of the supported APIs available in the SDK, without needing to launch an async request first.
* Instant access to platform, player and locale data.
* Easily load player photos directly into the Texture Manager, ready for use with a Game Object.
* Subscribe to game bots.
* The plugin has a built-in Data Manager which makes dealing with data stored on Facebook seamless. Just create whatever data properties you need and they are automatically synced.
* Support for FB stats, to retrieve, store and increment stats into cloud storage.
* Save Session data with built-in session length validation.
* Easy context switching, to swap between game instances and session data retrieval.
* Easily open a Facebook share, invite, request or game challenge window and populate the text and image content using any image stored in the Texture cache.
* Full Leaderboard support. Retrieve, scan and update leaderboard entries, as well as player matching.
* Support for in-app purchases, with product catalogs, the ability to handle purchases, get past purchases and consume previously unlocked purchases.
* Easily preload a set of interstitial ads, in both banner and video form, then display the ad at any point in your game, with in-built tracking of ads displayed and inventory available.
* Plus other features, such as logging to FB Analytics, creating short cuts, switching games, etc.
We've 3 tutorials related to Facebook Instant Games and Phaser:
* [Getting Started with Facebook Instant Games](http://phaser.io/news/2018/10/facebook-instant-games-phaser-tutorial)
* [Facebook Instant Games Leaderboards Tutorial](http://phaser.io/news/2018/11/facebook-instant-games-leaderboards-tutorial)
* [Displaying Ads in your Instant Games](http://phaser.io/news/2018/12/facebook-instant-games-ads-tutorial)
A special build of Phaser with the Facebook Instant Games Plugin ready-enabled is [available on jsDelivr](https://www.jsdelivr.com/projects/phaser). Include the following in your html:
```html
<script src="//cdn.jsdelivr.net/npm/phaser@3.15/dist/phaser-facebook-instant-games.js"></script>
```
or the minified version:
```html
<script src="//cdn.jsdelivr.net/npm/phaser@3.15/dist/phaser-facebook-instant-games.min.js"></script>
```
The build files are in the git repository in the `dist` folder, and you can also include the plugin in custom builds.
### Source Code Examples
During our development of Phaser 3, we created hundreds of examples with the full source code and assets. Until these examples are fully integrated into the Phaser website, you can browse them on [Phaser 3 Labs](https://labs.phaser.io), or clone the [examples repo][examples]. We are constantly adding to and refining these examples.
During our development of Phaser 3, we created hundreds of examples with the full source code and assets ready available. Until these examples are fully integrated into the Phaser website, you can browse them on [Phaser 3 Labs](https://labs.phaser.io), or clone the [examples repo][examples]. We are constantly adding to and refining these examples.
### Create Your First Phaser 3 Example
@ -257,11 +305,13 @@ There are both plain and minified compiled versions of Phaser in the `dist` fold
### Custom Builds
Phaser 3 is built using Webpack and we take advantage of the Webpack definePlugin feature to allow for conditional building of the Canvas and WebGL renderers. As of Phaser 3.7 we have updated our webpack config to make our source far easier to consume in other package managers like Parcel and Electron. Please look our webpack config files to get an idea of the settings we use.
Phaser 3 is built using Webpack and we take advantage of the Webpack definePlugin feature to allow for conditional building of the Canvas and WebGL renderers and extra plugins. You can custom the build process to only include the features you require. Doing so can cut the main build file size down to just 70KB.
Read our [comprehensive guide](https://phaser.io/phaser3/devlog/127) on creating Custom Builds of Phaser 3 for full details.
### Building from Source
If you wish to build Phaser 3 from source, ensure you have the required packages by cloning the repository and then running `npm install`.
If you wish to build Phaser 3 from source, ensure you have the required packages by cloning the repository and then running `npm install` on your source directory.
You can then run `webpack` to create a development build in the `build` folder which includes source maps for local testing. You can also `npm run dist` to create a minified packaged build in the `dist` folder. For a list of all commands available use `npm run help`.
@ -270,170 +320,42 @@ You can then run `webpack` to create a development build in the `build` folder w
# Change Log
## Version 3.10.1 - Hayashi - 13th June 2018
## Version 3.15.1 - Batou - 16th October 2018
### Bug Fixes
* The InputManager would only create 1 Pointer, even if Touch input was enabled in the config, which meant you couldn't use touch events unless you first called `addPointer` or specified one in the config. Now, it Touch is enabled in the config, it'll always create 2 pointers by default.
## Version 3.10.0 - Hayashi - 13th June 2018
### Input System New Features + Updates
* All Input classes are now covered 100% by JSDocs.
* The Input Manager and Input Plugin have been updated to support multiple simultaneous Pointers. Before, only one active pointer (mouse or touch) was supported. Now, you can have as many active pointers as you need, allowing for complex multi-touch games. These are stored in the Input Manager `pointers` array.
* `addPointer` allows you to add one, or more, new pointers to the Input Manager. There is no hard-coded limit to the amount you can have, although realistically you should never need more than 10. This method is available on both the Input Manager and Plugin, allowing you to use `this.input.addPointer` from within your game code.
* InputManager `pointersTotal` contains the total number of active pointers, which can be set in the Game Config using the `input.activePointers` property. Phaser will create 2 pointers on start unless a different value is given in the config, or you can add them at run-time.
* `mousePointer` is a new property that is specifically allocated for mouse use only. This is perfect for desktop only games but should be ignored if you're creating a mouse + touch game (use activePointer instead).
* `activePointer` will now reflect the most recently active pointer on the game, which is considered as being the pointer to have interacted with the game canvas most recently.
* The InputManager and InputPlugin have three new methods: `addUpCallback`, `addDownCallback` and `addMoveCallback`. These methods allow you to add callbacks to be invoked whenever native DOM mouse or touch events are received. Callbacks passed to this method are invoked _immediately_ when the DOM event happens, within the scope of the DOM event handler. Therefore, they are considered as 'native' from the perspective of the browser. This means they can be used for tasks such as opening new browser windows, or anything which explicitly requires user input to activate. However, as a result of this, they come with their own risks, and as such should not be used for general game input, but instead be reserved for special circumstances. The callbacks can be set as `isOnce` so you can control if the callback is called once then removed, or every time the DOM event occurs.
* Pointer has two new properties `worldX` and `worldY` which contain the position of the Pointer, translated into the coordinate space of the most recent Camera it interacted with.
* When checking to see if a Pointer has interacted with any objects it will now iterate through the Camera list. Previously, it would only check against the top-most Camera in the list, but now if the top-most camera doesn't return anything, it will move to the next camera and so on. This also addresses #3631 (thanks @samid737)
* `InputManager.dirty` is a new internal property that reflects if any of the Pointers have updated this frame.
* `InputManager.update` now uses constants internally for the event type checking, rather than string-based like before.
* `InputManager.startPointer` is a new internal method, called automatically by the update loop, that handles touch start events.
* `InputManager.updatePointer` is a new internal method, called automatically by the update loop, that handles touch move events.
* `InputManager.stopPointer` is a new internal method, called automatically by the update loop, that handles touch end events.
* `InputManager.hitTest` has had its arguments changed. It no longer takes x/y properties as the first two arguments, but instead takes a Pointer object (from which the x/y coordinates are extracted).
* `TouchManager.handler` has been removed as it's no longer used internally.
* `TouchManager.onTouchStart`, `onTouchMove` and `onTouchEnd` are the new DOM Touch Event handlers. They pass the events on to the InputManagers `queueTouchStart`, `queueTouchMove` and `queueTouchEnd` methods respectively.
* `MouseManager.handler` has been removed as it's no longer used internally.
* `MouseManager.onMouseDown`, `onMouseMove` and `onMouseUp` are the new DOM Mouse Event handlers. They pass the events on to the InputManagers `queueMouseDown`, `queueMouseMove` and `queueMouseUp` methods respectively.
* Setting `enabled` to false on either the TouchManager, MouseManager or KeyboardManager will prevent it from handling any native DOM events until you set it back again.
* InputPlugin has the following new read-only properties: `mousePointer`, `pointer1`, `pointer2`, `pointer3`, `pointer4`, `pointer5`, `pointer6`, `pointer7`, `pointer8`, `pointer9` and `pointer10`. Most of these will be undefined unless you call `addPointer` first, or set the active pointers quantity in your Game Config.
* InputManager has a new method `transformPointer` which will set the transformed x and y properties of a Pointer in one call, rather than the 2 calls it took before. This is now used by all Pointer event handlers.
* InputPlugin has a new method `makePixelPerfect` which allows you to specify a texture-based Game Object as being pixel perfect when performing all input checks against it. You use it like this: `this.add.sprite(x, y, key).setInteractive(this.input.makePixelPerfect())`, or the easier: `setInteractive({ pixelPerfect: true })` - you can also pass or set an optional alpha tolerance level. See the method docs for full details and the new examples to see it in action. Note that as a pointer interacts with the Game Object it will constantly poll the texture, extracting a single pixel from the given coordinates and checking its color values. This is an expensive process, so should only be enabled on Game Objects that really need it.
### Input - Custom Cursors
* You can now set a custom cursor for your game via `this.input.setDefaultCursor()`. This will take any valid CSS cursor string, including URLs to cursor image files.
* You can now set a custom cursor for specific Game Objects. This will take any valid CSS cursor string, including URLs to cursor image files, and is used when-ever a pointer is over that Game Object. For example, to have a hand cursor appear when over a button Sprite, you can do: `button.input.cursor = 'pointer'`, or to have a help cursor appear: `button.input.cursor = 'help'`, or to have a custom image: `button.input.cursor = 'url(assets/cursors/sword.cur), pointer'`.
* You can also set a custom cursor in the new Input Configuration Object. To use the `pointer` (hand cursor) there is a new short-cut: `setInteractive({ useHandCursor: true })`. To use anything else: `setInteractive({ cursor: CSSString })` where `CSSString` is any valid CSS for setting a cursor.
* Please be aware of limitations when it comes to image based cursors between browsers. It's up to you to find a suitable format and size that fits the browsers you wish to support (note: virtually all modern browsers no longer support animated CSS cursors.)
### Input - Configuration Objects
* The `setInteractive` method can now take an Input Configuration object as its only argument. This allows you to set multiple input related properties in a single call, i.e.: `setInteractive({ draggable: true, pixelPerfect: true })`. The available properties are:
* `hitArea` - The object / shape to use as the Hit Area. If not given it will try to create a Rectangle based on the texture frame.
* `hitAreaCallback` - The callback that determines if the pointer is within the Hit Area shape or not.
* `draggable` - If `true` the Interactive Object will be set to be draggable and emit drag events.
* `dropZone` - If `true` the Interactive Object will be set to be a drop zone for draggable objects.
* `useHandCursor` - If `true` the Interactive Object will set the `pointer` hand cursor when a pointer is over it. This is a short-cut for setting `cursor: 'pointer'`.
* `cursor` - The CSS string to be used when the cursor is over this Interactive Object.
* `pixelPerfect` - If `true` the a pixel perfect function will be set for the hit area callback. Only works with texture based Game Objects.
* `alphaTolerance` - If `pixelPerfect` is set, this is the alpha tolerance threshold value used in the callback.
### Input - Keyboard Manager Updates
* The `KeyboardManager` class has been removed. It has been replaced with `KeyboardPlugin` which is now an Input level plugin, that registers itself with the new `InputPluginCache`. The Input Plugin class (which belongs to a Scene) will now automatically inject registered plugins into itself on boot. Every Scene has its own instance of the Input Plugin (if enabled in the scene plugins), which in turn has its own instance of the KeyboardPlugin. The `InputManager` no longer has any reference to the Keyboard class at all. The benefits of this are two-fold: First, it allows you to now entirely exclude all of the keyboard classes from a custom build, saving a lot of space if not required. Secondly, it means that the Scenes themselves are now responsible for keyboard events, where-as before they were entirely global. This means a Scene can be paused and stop processing keyboard events, and stop having its Key objects updated, while another Scene can still carry on doing this. It also prevents key related callbacks in sleeping Scenes from being fired (which resolves issue #3733, thanks @JoeMoov2)
* `KeyboardManager.handler` has been renamed to `onKeyHandler`.
* The `KeyboardManager.captures` property has been removed as it can be more effectively handled by polling the `keys` object instead.
* The Keyboard Manager will no longer process key down or up events if its `enabled` property is set to false, or if the Scene to which it belongs is not active.
* The Keyboard Manager will now call `event.preventDefault` on the native DOM event as long as the Key exists in the keys array and has its `preventDefault` property set to `true` (which is the default). This means you can now control specifically which key prevents default on the browser, where-as before every key added did so.
* KeyboardManager `addKeyCapture` and `removeKeyCapture` have been removed as you now control which keys prevent capture by using the `addKey` or `addKeys` methods (see entry above). The act of creating a Key is now enough to enable capture of it and can be toggled (at run-time) on a per-Key basis.
* `KeyboardManager.addKeys` can now take either an object, or key codes, or a comma-separated string as its input. This means you can now do: `keyboard.addKeys('W,S,A,D')` and get an object back with the properties WSAD mapped to the relevant Key objects.
* `KeyboardManager.addKey` can now take either a Key object, a string, such as `A` or `SPACE`, or a key code value.
* `KeyboardManager.removeKey` can now take either a Key object, a string, such as `A` or `SPACE`, or a key code value.
### Input - Gamepad Manager Updates
* The `GamepadManager` class has been removed. It has been replaced with `GamepadPlugin` which is now an Input level plugin, that registers itself with the new `InputPluginCache`. The Input Plugin class (which belongs to a Scene) will now automatically inject the registered plugins into itself on boot. Every Scene has its own instance of the Input Plugin (if enabled in the scene plugins), which in turn has its own instance of the GamepadPlugin. The `InputManager` no longer has any reference to the Gamepad class at all. The benefits of this are two-fold: First, it allows you to now entirely exclude all of the gamepad classes from a custom build, saving a lot of space if not required. Secondly, it means that the Scenes themselves are now responsible for gamepad events, where-as before they were entirely global. This means a Scene can be paused and stop processing gamepad events, and stop having its Gamepad objects updated, while another Scene can still carry on doing this. It also prevents gamepad related callbacks in sleeping Scenes from being fired.
* The Gamepad Plugin has been rewritten from scratch. It now offers a lot more features and far easier access to the Gamepads and their properties. You can now access the first 4 gamepads connected to the browser via the `pad1` to `pad4` properties, meaning you can do: `this.input.gamepad.pad1` for direct access to a pad once it's connected.
* The Gamepad class has also been rewritten from scratch. It will no longer create Buttons or Axes dynamically, instead doing so on instantiation.
* The Gamepad class now has a bunch of new properties for easy access to the various standard mapping buttons. These include `left`, `right`, `up`, `down` for directions, `A`, `Y`, `X` and `B` for buttons, `L1`, `L2`, `R1` and `R2` for shoulder buttons, and `leftStick` and `rightStick` for the axis sticks. You can still use `Gamepad.getButtonValue()` to get the value from a button and `Gamepad.getButtonTotal()` to get the total number of buttons available on the pad.
* `Gamepad.getAxisTotal` and `Gamepad.getAxisValue` will return the total number of axis, and an axis value, accordingly.
* `Gamepad.setAxisThreshold` will now let you set the threshold across all axis of a Gamepad in one call.
* The Gamepad `Button` objects will now emit 2 events, one from the button itself and another from the Gamepad. This means you can listen for button events in 3 ways: 1) By directly polling the button value in an update loop, 2) Listening for events on the Gamepad Plugin: `this.input.gamepad.on('down')`, or 3) By listening for events on the Gamepad itself: `gamepadReference.on('down')`.
### Arcade Physics New Features + Updates
* Arcade Physics now uses a fixed time-step for all internal calculations. There is a new `fps` config value and property (defaults to 60fps), which you can change at run-time using the `setFPS` method. The core update loop has been recoded so that it steps based entirely on the given frame rate, and not the wall-clock or game step delta. This fixed time step allows for a straightforward implementation of a deterministic game state. Meaning you can now set the fps rate to a high value such as 240, regardless of the browser update speed (it will simply perform more physics steps per game step). This is handy if you want to increase the accuracy of the simulation in certain cases.
* You can also optionally call the `step` function directly, to manually advance the simulation.
* There is a new property `timeScale` which will scale all time-step calculations at run-time, allowing you to speed-up or slow-down your simulation at will, without adjusting the frame rate.
* You can now disable the use of the RTree for dynamic bodies via the config property `useTree`. In certain situations, i.e. densely packed worlds, this may give better performance. Static bodies will always use an RTree.
* `collideSpriteVsGroup` has been rewritten. If you are using an RTree it now uses the results directly from the tree search, instead of iterating all children in the Group, which dramatically reduces the work it does. If you have disabled the RTree it performs a brute-force O(N2) Sprite vs. Group iteration sweep. We tested multiple axis sorting variants but the cost of the array allocation and/or sorting, with large amounts of bodies (10,000+), far outweighed the simple math involved in the separation logic.
* `Body.useDamping` is a new boolean property that allows you to use a damping effect for drag, rather than the default linear deceleration. This gives much better results if you need smooth deceleration across both axis, such as the way the ship slows down in the game Asteroids, without the tell-tale axis drift associated with linear drag.
* `GetOverlapX` and `GetOverlapY` now use the calculated delta values, not the deltaX/Y methods.
* `collideSpriteVsGroup` aborts early if the Sprite body has been disabled.
* `updateMotion` has a new argument `delta` which should typically be a fixed-time delta value.
* `intersects` has been restructured to prioritize rect vs. rect checks.
* Body `update` and `postUpdate` have been recoded to handle the new fixed time-step system in place. `update` now takes a new argument, delta, which is used internally for calculations.
* `Body.dirty` has been removed as a property as it's no longer used internally.
* `Body.deltaAbsX` and `deltaAbsY` now return the cached absolute delta value from the previous update, and no longer calculate it during the actual call.
* `World.enable` has been recoded to remove all the `hasOwnProperty` checks and streamline the internal flow.
* `World.disable` has been recoded to remove all the `hasOwnProperty` checks and streamline the internal flow.
* `World.add` is a new method that adds an existing body to the simulation and `enableBody` now passes its newly created bodies to this method.
* `World.disableGameObjectBody` has been removed as it duplicated what the `disable` method did.
* There is a new internal flow with regard to the creation and disabling of bodies. Calling `World.enable` will pass the objects to `enableBody`, which will create a new Body object, if required, and finally pass it to `add`. `World.disable` does the same, but removes the bodies from the simulation. It passes the bodies to `disableBody`, which in turn passes it to `remove`. Both of these work for single objects, an array of objects, Groups or even arrays of Groups.
* `World.computeAngularVelocity` is a new method that specifically calculates the angular velocity of a Body.
* `World.computeVelocity` has had its signature changed. Rather than taking a bunch of arguments all it now takes is a Body and a delta value. Internally it now calculates both the x and y velocity components together in the same single call, where-as before it was split into two calls and multiple assignments.
* `World.computeVelocity` no longer returns the new velocities, they are now set directly on the body within the method.
* `World.computeVelocity` has been recoded to use Fuzzy Greater Than and Less Than calls when applying drag to a previously accelerated body. Using a fuzzy epsilon allows us to mitigate the ping-pong issue, where a decelerating body would constantly flip between a small negative and positive velocity value and never come to an actual rest.
* `World.computeVelocity` now checks the `Body.useDamping` property to perform either linear deceleration or damping on the Body.
* `World.updateMotion` has changed to call the new `computeAngularVelocity` and `computeVelocity` methods.
* Bodies set to bounce would eventually run out of velocity and stop. This has been fixed as part of the refactoring of the time step and compute velocity updates. Fix #3593 (thanks @helmi77)
* If a Body collides with a Static Body it will now set the `blocked` properties accordingly (before it only set the `touching` properties.) This means you can now use checks like `Body.onFloor()` when traversing static bodies (thanks @fariazz)
### Data Manager New Features and Updates
* You can now access anything set in the DataManager using the new `values` property. For example, if you set a new value such as this: `data.set('gold', 50)` you can now access it via: `data.values.gold`, where it is treated as a normal property, allowing you to use it in conditional evaluations `if (data.values.level === 2)`, or modify it: `data.values.gold += 50`.
* Each time a value is updated it emits a `changedata` event, regardless if it is changed via the `set` method, or the new `values` approach.
* Each time a value is updated it emits a new event named after the value. For example, if the value was called `PlayerLives`, it will emit the event `changedata_PlayerLives`. This happens regardless if it is changed via the `set` method, or the new `values` approach.
* The `set` method can now take an object containing key value pairs as the first argument. This means you can now set a bunch of values all at once, i.e: `data.set({ name: 'Red Gem Stone', level: 2, owner: 'Link', gold: 50 })`.
* The `get` method can now take an array of keys, and will return an array of matching values. This is handy for array destructuring in ES6.
* The `remove` method can now take an array of keys, and will remove all matching values, emitting the `removedata` event for each.
* The order of events has been updated. When a value is first set, and doesn't already exist in the Data Manager, it will emit a `setdata` event. If a value is set that already exists, it instead emits a `changedata` and related `changedata_key` event. Setting a new value no longer emits both events.
* The `resetFunction` function has been removed from the `changedata` event arguments. Previously this was used to allow you to stop a value being updated by calling the reset function instead. However, it created brand new anonymous functions every single time a value was updated. As you can now access stored data via the `values` property you can use this for much easier conditional checks and sets.
* The `blockSet` property has been removed as it's no longer used internally.
### Loader and Scene Updates
* Internally, the Loader has changed slightly. Rather than have each file cause the new batch to load, an `update` method is polled every frame, which does the same job instead. This avoids load-time race conditions where pre-populated files would trigger loads part way during an existing load, fixing #3705 in the process (thanks @the-simian)
* The Scene Manager has been updated so that it will call Scene.Systems.step during the `init`, `preload` and `create` phase of your Scene. This means that any plugins, or custom code, written to use the Scene Systems `preupdate`, `update` or `postupdate` events will need to be aware that these are now fired from `init` onwards, not just once `create` has finished.
* As a result of these two changes, there is a new Systems property called `sceneUpdate`, which is a reference that maps to your `Scene.update` function. During `init`, `preload` and `create` this is always mapped to NOOP. Once `create` has finished it gets re-mapped to your Scene's update function. If your Scene doesn't have one, it remains mapped to NOOP. In practise, this means nothing has changed from before. `Scene.update` never ran until `create` was completed, and it still doesn't. However, because the internal Scene systems are now updating right from `init`, it means that things like the update list and physics systems are fully operational _during_ your Preloader. This allows you to create far more elaborate preloaders than ever before. Although, with great power comes great responsibility, as the onus is now on you to be careful which events you consume (especially input events) during your preloader.
* Another side-effect of these changes is that Scenes no longer need an 'update' function at all. Previously, if they were missing one, the Scene Manager would inject one into them automatically. It no longer does this.
Note: We are releasing this version ahead of schedule in order to make some very important iOS performance and input related fixes available. It does not contain the new Scale Manager or Spine support, both of which have been moved to 3.16 as they require a few more weeks of development.
### New Features
* `RenderTexture.resize` will allow you to resize the underlying Render Texture to the new dimensions given. Doing this also clears the Render Texture at the same time (thanks @saqsun).
* `Rectangle.RandomOutside` is a new function that takes two Rectangles, `outer` and `inner`, and returns a random point that falls within the outer rectangle but is always outside of the inner rectangle.
* The Update List has a new read-only property `length`, making it consistent with the Display List (thanks @samme)
* The 2D Camera class has two new read-only properties `centerX` and `centerY` which return the coordinates of the center of the viewport, relative to the canvas (thanks @samme)
* Camera has a new property `visible`. An invisible Camera will skip rendering and input tests of everything it can see. This allows you to create say a mini-cam and then toggle it on and off without needing to re-create it each time.
* Camera has a new method `setVisible` which toggles its visible property.
* `CameraManager.fromJSON` will now set the visible property is defined in the config.
* `ScenePlugin.run` is a new method that will run the given Scene and not change the state of the current Scene at all. If the scene is asleep, it will be woken. If it's paused, it will be resumed. If not running at all, it will be started.
* `TextureManager.getPixelAlpha` is a new method that will return the alpha value of a pixel from the given texture and frame. It will return `null` if the coordinates were out of bounds, otherwise a value between 0 and 255.
* `Game.isOver` is a new read-only boolean property that indicates if the mouse pointer is currently over the game canvas or not. It is set by the VisibilityHandler and is only reliable on desktop systems.
* A new event `Game.mouseout` is dispatched if the mouse leaves the game canvas. You can listen to it from `this.sys.game.events.on('mouseout')` from within a Scene.
* A new event `Game.mouseover` is dispatched if the mouse enters the game canvas, having previously been outside of it. You can listen to it from `this.sys.game.events.on('mouseover')` from within a Scene.
* You can now use PhysicsEditor (https://www.codeandweb.com/physicseditor) to create complex Matter.js bodies. Load them as normal JSON and then just pass it to the Matter Sprite as a shape property: `this.matter.add.sprite(x, y, texture, frame, { shape: shapes.banana })` (where `shapes.banana` is one of the exported PhysicsEditor shapes in the JSON you loaded). See the 'physics/matterjs/advanced shape creation.js' example for more details.
* You can now set the `maxLights` value in the Game Config, which controls the total number of lights the Light2D shader can render in a single pass. The default is 10. Be careful about pushing this too far. More lights = less performance. Close #4081 (thanks @FrancescoNegri)
* `Rectangle.SameDimensions` determines if the two objects (either Rectangles or Rectangle-like) have the same width and height values under strict equality.
* An ArcadePhysics Group can now pass `{ enable: false }`` in its config to disable all the member bodies (thanks @samme)
* `Body.setEnable` is a new chainable method that allows you to toggle the enable state of an Arcade Physics Body (thanks @samme)
* `KeyboardPlugin.resetKeys` is a new method that will reset the state of any Key object created by a Scene's Keyboard Plugin.
* `Pointer.wasCanceled` is a new boolean property that allows you to tell if a Pointer was cleared due to a `touchcancel` event. This flag is reset during the next `touchstart` event for the Pointer.
* `Pointer.touchcancel` is a new internal method specifically for handling touch cancel events. It has the same result as `touchend` without setting any of the up properties, to avoid triggering up event handlers. It will also set the `wasCanceled` property to `true`.
### Updates
* The `ForwardDiffuseLightPipeline`, used by the Lights system, now sets a flag if the Scene doesn't contain any lights. All of the Game Objects now check this flag and don't even bother adding themselves to the batch if there are no lights in the Scene, as they'd never render anyway. This also avoids the ghost-image problem if you swap Scenes to a new Scene with the Light Manager enabled, but no actual lights defined. Fix #3707 (thanks @samvieten).
* `CameraManager.getCameraBelowPointer` has been renamed to `getCamerasBelowPointer` and it now returns an array of all the cameras below the given pointer, not just the top-most one. The array is sorted so that the top-most camera is at the start of the array.
* In `TimeStep.step` the `rawDelta` and `delta` values are checked to make sure they are non-negative, which can happen in Chrome when the delta is reset and out of sync with the value passed to Request Animation Frame. Fix #3088 (thanks @Antriel)
* `Cameras.Controls.Fixed` has been removed. It's was deprecated a few versions ago. Please use `FixedKeyControl` instead.
* `Cameras.Controls.Smoothed` has been removed. It's was deprecated a few versions ago. Please use `SmoothedKeyControl` instead.
* `WebGLRenderer.deleteTexture` will check to see if the texture it is being asked to delete is the currently bound texture or not. If it is, it'll set the blank texture to be bound after deletion. This should stop `RENDER WARNING: there is no texture bound to the unit 0` errors if you destroy a Game Object, such as Text or TileSprite, from an async or timed process (thanks jamespierce)
* The `RequestAnimationFrame.step` and `stepTimeout` functions have been updated so that the new Frame is requested from raf before the main game step is called. This allows you to now stop the raf callback from within the game update or render loop. Fix #3952 (thanks @tolimeh)
* If you pass zero as the width or height when creating a TileSprite it will now use the dimensions of the texture frame as the size of the TileSprite. Fix #4073 (thanks @jcyuan)
* `TileSprite.setFrame` has had both the `updateSize` and `updateOrigin` arguments removed as they didn't do anything for TileSprites and were misleading.
* `CameraManager.remove` has a new argument `runDestroy` which, if set, will automatically call `Camera.destroy` on the Cameras removed from the Camera Manager. You should nearly always allow this to happen (thanks jamespierce)
* Device.OS has been restructured to allow fake UAs from Chrome dev tools to register iOS devices.
* Texture batching during the batch flush has been implemented in the TextureTintPipeline which resolves the issues of very low frame rates, especially on iOS devices, when using non-batched textures such as those used by Text or TileSprites. Fix #4110 #4086 (thanks @ivanpopelyshev @sachinhosmani @maximtsai @alexeymolchan)
* The WebGLRenderer method `canvasToTexture` has a new optional argument `noRepeat` which will stop it from using `gl.REPEAT` entirely. This is now used by the Text object to avoid it potentially switching between a REPEAT and CLAMP texture, causing texture black-outs (thanks @ivanpopelyshev)
* `KeyboardPlugin.resetKeys` is now called automatically as part of the Keyboard Plugin `shutdown` method. This means, when the plugin shuts down, such as when stopping a Scene, it will reset the state of any key held in the plugin. It will also clear the queue of any pending events.
* The `Touch Manager` has been rewritten to use declared functions for all touch event handlers, rather than bound functions. This means they will now clear properly when the TouchManager is shut down.
* There is a new Input constant `TOUCH_CANCEL` which represents canceled touch events.
### Bug Fixes
* The Canvas `RenderTexture.drawImage` method incorrectly set the values of the frame, causing them to appear wrongly scaled in the canvas renderer. Fix #3710 (thanks @saqsun).
* Fixed `Math.Matrix4.makeRotationAxis()` (thanks @hexus)
* Fixed an incorrect usage of `Math.abs()` in `Math.Quaternion.calculateW()` (thanks @qxzkjp).
* Particle Emitter Managers can now be added to Containers (thanks @TadejZupancic)
* Fixed a method signature issue with the Animation component's `remove()` handler when `Animation`s are removed from the `AnimationManager`. This prevented removed animations from stopping correctly.
* If you set Phaser to use a pre-existing Canvas element it is no longer re-added to the DOM (thanks @NQNStudios)
* The `TweenManager.getTweensOf` method has been fixed to remove a potential endless loop should multiple targets be passed in to it (thanks @cyantree)
* Interactive Objects inside of Containers would still fire their input events even if the Container (or any ancestor) was set to be invisible. Objects now check their ancestor tree during the input cull and now properly skip input events if not visible. Fix #3620 (thanks @NemoStein)
* Fixed Device.os incorrectly reporting Linux as OS on Android devices (thanks @AleBles)
### Examples, Documentation and TypeScript
Thanks to the work of @hexus we have now documented all of the Math namespace and made good progress on the Game Objects.
I personally have also documented the entire Input system, which was 328 classes, properties and methods to describe, as well as lots of other areas.
* Fixed a bug in the canvas rendering of both the Static and Dynamic Tilemap Layers where the camera matrix was being multiplied twice with the layer, causing the scale and placement to be off (thanks galerijanamar)
* If you set `pixelArt` to true in your game config (or `antialias` to false) then TileSprites will now respect this when using the Canvas Renderer and disable smoothing on the internal fill canvas.
* TileSprites that were set to be interactive before they had rendered once wouldn't receive a valid input hit area, causing input to fail. They now define their size immediately, allowing them to be made interactive without having rendered. Fix #4085 (thanks @DotTheGreat)
* The Particle Emitter Manager has been given a NOOP method called `setBlendMode` to stop warnings from being thrown if you added an emitter to a Container in the Canvas renderer. Fix #4083 (thanks @maximtsai)
* The `game.context` property would be incorrectly set to `null` after the WebGLRenderer instance was created (thanks @samme)
* The Touch Manager, Input Manager and Pointer classes all now handle the `touchcancel` event, such as triggered on iOS when activating an out of browser UI gesture, or in Facebook Instant Games when displaying an overlay ad. This should prevent issues with touch input becoming locked on iOS specifically. Fix #3756 (thanks @sftsk @sachinhosmani @kooappsdevs)
Please see the complete [Change Log](https://github.com/photonstorm/phaser/blob/master/CHANGELOG.md) for previous releases.
@ -466,8 +388,8 @@ All rights reserved.
"Above all, video games are meant to be just one thing: fun. Fun for everyone." - Satoru Iwata
[get-js]: https://github.com/photonstorm/phaser/releases/download/v3.10.1/phaser.js
[get-minjs]: https://github.com/photonstorm/phaser/releases/download/v3.10.1/phaser.min.js
[get-js]: https://github.com/photonstorm/phaser/releases/download/v3.15.1/phaser.js
[get-minjs]: https://github.com/photonstorm/phaser/releases/download/v3.15.1/phaser.min.js
[clone-http]: https://github.com/photonstorm/phaser.git
[clone-ssh]: git@github.com:photonstorm/phaser.git
[clone-ghwin]: github-windows://openRepo/https://github.com/photonstorm/phaser
@ -476,4 +398,4 @@ All rights reserved.
[issues]: https://github.com/photonstorm/phaser/issues
[examples]: https://github.com/photonstorm/phaser3-examples
[contribute]: https://github.com/photonstorm/phaser/blob/master/.github/CONTRIBUTING.md
[forum]: http://www.html5gamedevs.com/forum/33-phaser-3/
[forum]: https://phaser.discourse.group/

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

80427
dist/phaser-core.js vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

172932
dist/phaser-facebook-instant-games.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

197624
dist/phaser.js vendored

File diff suppressed because it is too large Load diff

2
dist/phaser.min.js vendored

File diff suppressed because one or more lines are too long

5615
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"name": "phaser",
"version": "3.11.0-beta1",
"release": "Leafa",
"version": "3.16.0",
"release": "Ishikawa",
"description": "A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers.",
"author": "Richard Davey <rich@photonstorm.com> (http://www.photonstorm.com)",
"logo": "https://raw.github.com/photonstorm/phaser/master/phaser-logo-small.png",
@ -15,10 +15,23 @@
"url": "https://photonstorm@github.com/photonstorm/phaser.git"
},
"scripts": {
"beta": "npm publish --tag beta",
"help": "node scripts/help.js",
"build": "webpack",
"watch": "webpack --watch",
"buildfb": "webpack --config webpack.fb.config.js",
"watchfb": "webpack --config webpack.fb.config.js --watch",
"dist": "webpack --config webpack.dist.config.js",
"distfb": "webpack --config webpack.fb.dist.config.js",
"distfull": "npm run dist && npm run distfb",
"plugin.cam3d": "webpack --config plugins/camera3d/webpack.config.js",
"plugin.spine": "webpack --config plugins/spine/webpack.config.js",
"plugin.spine.dist": "webpack --config plugins/spine/webpack.auto.dist.config.js",
"plugin.spine.watch": "webpack --config plugins/spine/webpack.auto.config.js --watch --display-modules",
"plugin.spine.canvas.dist": "webpack --config plugins/spine/webpack.canvas.dist.config.js",
"plugin.spine.canvas.watch": "webpack --config plugins/spine/webpack.canvas.config.js --watch --display-modules",
"plugin.spine.webgl.dist": "webpack --config plugins/spine/webpack.webgl.dist.config.js",
"plugin.spine.webgl.watch": "webpack --config plugins/spine/webpack.webgl.config.js --watch",
"lint": "eslint --config .eslintrc.json \"src/**/*.js\"",
"lintfix": "eslint --config .eslintrc.json \"src/**/*.js\" --fix",
"sloc": "node-sloc \"./src\" --include-extensions \"js\"",
@ -42,14 +55,16 @@
"eslint": "^4.19.1",
"eslint-plugin-es5": "^1.3.1",
"fs-extra": "^6.0.0",
"node-sloc": "^0.1.10",
"uglifyjs-webpack-plugin": "^1.2.5",
"node-sloc": "^0.1.11",
"uglifyjs-webpack-plugin": "^1.3.0",
"vivid-cli": "^1.1.2",
"webpack": "^4.6.0",
"webpack-cli": "^2.1.2",
"webpack": "^4.23.0",
"webpack-cli": "^3.1.1",
"webpack-shell-plugin": "^0.5.0"
},
"dependencies": {
"eventemitter3": "^3.1.0"
"eventemitter3": "^3.1.0",
"exports-loader": "^0.7.0",
"imports-loader": "^0.8.0"
}
}

18079
plugins/camera3d/dist/camera3d.js vendored Normal file

File diff suppressed because it is too large Load diff

1
plugins/camera3d/dist/camera3d.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,91 @@
Phaser 3 Camera 3D Plugin
=========================
In Phaser 3.12 Camera 3D support was moved to its own external plugin.
There are two ways to use this in your games:
## 1. External Plugin
You can copy the `dist/camera3d.min.js` file to your project folder and preload it into Phaser:
```
function preload ()
{
this.load.scenePlugin('Camera3DPlugin', 'plugins/camera3d.min.js', 'Camera3DPlugin', 'cameras3d');
}
```
Then you can use it like usual.
## 2. Bundled Plugin
If you prefer you can configure Phaser to include it when it builds its dist files.
To do this you need to edit the webpack config files and change the following:
```
"typeof PLUGIN_CAMERA3D": JSON.stringify(false)
```
to
```
"typeof PLUGIN_CAMERA3D": JSON.stringify(true)
```
Then rebuild Phaser via webpack. The plugin will now be included by default and can be called from your game code.
## Using the Plugin
Here is a basic example of using the plugin. You can find many more in the Phaser 3 Examples repo in the [cameras/3D Camera](https://github.com/photonstorm/phaser3-examples/tree/master/public/src/camera/3D%20camera) folder.
```
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update
}
};
var camera;
var transform;
var game = new Phaser.Game(config);
function preload ()
{
this.load.scenePlugin('Camera3DPlugin', 'plugins/camera3d.min.js', 'Camera3DPlugin', 'cameras3d');
this.load.image('particle', 'assets/sprites/mushroom2.png');
}
function create ()
{
camera = this.cameras3d.add(85).setZ(300).setPixelScale(128);
var sprites = camera.createRect({ x: 4, y: 4, z: 16 }, { x: 48, y: 48, z: 32 }, 'particle');
// Our rotation matrix
transform = new Phaser.Math.Matrix4().rotateX(-0.01).rotateY(-0.02).rotateZ(0.01);
}
function update ()
{
camera.transformChildren(transform);
}
```
## Building the External Plugin
If you wish to edit the plugin use the following files:
`src/Camera3DPlugin.js` is the entry point for the external plugin. Edit this file if you're loading the plugin at run-time. Once you have finished making your changes, run the command `npm run plugin.cam3d` from the command-line to build a new version of the external plugin with Webpack.
## Changing the Bundled Plugin
`src/index.js` is the entry point for the bundled plugin. In here you'll find the module exports that Phaser uses when including the plugin internally. The file `CameraManager.js` is the Scene System. All other files are shared between both the external and bundled versions of the plugin.

View file

@ -4,16 +4,16 @@
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../utils/Class');
var Matrix4 = require('../../math/Matrix4');
var RandomXYZ = require('../../math/RandomXYZ');
var RandomXYZW = require('../../math/RandomXYZW');
var RotateVec3 = require('../../math/RotateVec3');
var Set = require('../../structs/Set');
var Sprite3D = require('../../gameobjects/sprite3d/Sprite3D');
var Vector2 = require('../../math/Vector2');
var Vector3 = require('../../math/Vector3');
var Vector4 = require('../../math/Vector4');
var Class = require('../../../src/utils/Class');
var Matrix4 = require('../../../src/math/Matrix4');
var RandomXYZ = require('../../../src/math/RandomXYZ');
var RandomXYZW = require('../../../src/math/RandomXYZW');
var RotateVec3 = require('../../../src/math/RotateVec3');
var Set = require('../../../src/structs/Set');
var Sprite3D = require('./sprite3d/Sprite3D');
var Vector2 = require('../../../src/math/Vector2');
var Vector3 = require('../../../src/math/Vector3');
var Vector4 = require('../../../src/math/Vector4');
// Local cache vars
var tmpVec3 = new Vector3();
@ -300,6 +300,9 @@ var Camera = new Class({
{
this.children.set(sprite3D);
this.displayList.add(sprite3D.gameObject);
this.updateList.add(sprite3D.gameObject);
this.updateChildren();
return sprite3D;

View file

@ -0,0 +1,340 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var BuildGameObject = require('../../../src/gameobjects/BuildGameObject');
var BuildGameObjectAnimation = require('../../../src/gameobjects/BuildGameObjectAnimation');
var Class = require('../../../src/utils/Class');
var GetAdvancedValue = require('../../../src/utils/object/GetAdvancedValue');
var OrthographicCamera = require('./OrthographicCamera');
var PerspectiveCamera = require('./PerspectiveCamera');
var ScenePlugin = require('../../../src/plugins/ScenePlugin');
var Sprite3D = require('./sprite3d/Sprite3D');
/**
* @classdesc
* The Camera 3D Plugin adds a new Camera type to Phaser that allows for movement and rendering
* in 3D space. It displays a special type of Sprite called a Sprite3D that is a billboard sprite,
* with a z-axis allowing for perspective depth.
*
* This is an external plugin which you can include in your game by preloading it:
*
* ```javascript
* this.load.scenePlugin({
* key: 'Camera3DPlugin',
* url: 'plugins/camera3d.min.js',
* sceneKey: 'cameras3d'
* });
* ```
*
* Once loaded you can create a 3D Camera using the `camera3d` property of a Scene:
*
* `var camera = this.cameras3d.add(85).setZ(500).setPixelScale(128);`
*
* See the examples for more information.
*
* @class Camera3DPlugin
* @constructor
*
* @param {Phaser.Scene} scene - The Scene to which this plugin is being installed.
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
*/
var Camera3DPlugin = new Class({
Extends: ScenePlugin,
initialize:
function Camera3DPlugin (scene, pluginManager)
{
ScenePlugin.call(this, scene, pluginManager);
/**
* An Array of the Camera objects being managed by this Camera Manager.
*
* @name Camera3DPlugin#cameras
* @type {Phaser.Cameras.Sprite3D.Camera[]}
* @since 3.0.0
*/
this.cameras = [];
// Register the Sprite3D Game Object
pluginManager.registerGameObject('sprite3D', this.sprite3DFactory, this.sprite3DCreator);
},
/**
* Creates a new Sprite3D Game Object and adds it to the Scene.
*
* @method Phaser.GameObjects.GameObjectFactory#sprite3D
* @since 3.0.0
*
* @param {number} x - The horizontal position of this Game Object.
* @param {number} y - The vertical position of this Game Object.
* @param {number} z - The z position of this Game Object.
* @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
* @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
*
* @return {Phaser.GameObjects.Sprite3D} The Game Object that was created.
*/
sprite3DFactory: function (x, y, z, key, frame)
{
var sprite = new Sprite3D(this.scene, x, y, z, key, frame);
this.displayList.add(sprite.gameObject);
this.updateList.add(sprite.gameObject);
return sprite;
},
/**
* Creates a new Sprite3D Game Object and returns it.
*
* @method Phaser.GameObjects.GameObjectCreator#sprite3D
* @since 3.0.0
*
* @param {object} config - The configuration object this Game Object will use to create itself.
* @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object.
*
* @return {Phaser.GameObjects.Sprite3D} The Game Object that was created.
*/
sprite3DCreator: function (config, addToScene)
{
if (config === undefined) { config = {}; }
var key = GetAdvancedValue(config, 'key', null);
var frame = GetAdvancedValue(config, 'frame', null);
var sprite = new Sprite3D(this.scene, 0, 0, key, frame);
if (addToScene !== undefined)
{
config.add = addToScene;
}
BuildGameObject(this.scene, sprite, config);
// Sprite specific config options:
BuildGameObjectAnimation(sprite, config);
return sprite;
},
/**
* This method is called automatically, only once, when the Scene is first created.
* Do not invoke it directly.
*
* @method Phaser.Cameras.Scene3D.CameraManager#boot
* @private
* @since 3.5.1
*/
boot: function ()
{
this.systems.events.once('destroy', this.destroy, this);
},
/**
* This method is called automatically by the Scene when it is starting up.
* It is responsible for creating local systems, properties and listening for Scene events.
* Do not invoke it directly.
*
* @method Camera3DPlugin#start
* @private
* @since 3.5.0
*/
start: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.on('update', this.update, this);
eventEmitter.once('shutdown', this.shutdown, this);
},
/**
* [description]
*
* @method Camera3DPlugin#add
* @since 3.0.0
*
* @param {number} [fieldOfView=80] - [description]
* @param {number} [width] - [description]
* @param {number} [height] - [description]
*
* @return {Phaser.Cameras.Sprite3D.PerspectiveCamera} [description]
*/
add: function (fieldOfView, width, height)
{
return this.addPerspectiveCamera(fieldOfView, width, height);
},
/**
* [description]
*
* @method Camera3DPlugin#addOrthographicCamera
* @since 3.0.0
*
* @param {number} width - [description]
* @param {number} height - [description]
*
* @return {Phaser.Cameras.Sprite3D.OrthographicCamera} [description]
*/
addOrthographicCamera: function (width, height)
{
var config = this.scene.sys.game.config;
if (width === undefined) { width = config.width; }
if (height === undefined) { height = config.height; }
var camera = new OrthographicCamera(this.scene, width, height);
this.cameras.push(camera);
return camera;
},
/**
* [description]
*
* @method Camera3DPlugin#addPerspectiveCamera
* @since 3.0.0
*
* @param {number} [fieldOfView=80] - [description]
* @param {number} [width] - [description]
* @param {number} [height] - [description]
*
* @return {Phaser.Cameras.Sprite3D.PerspectiveCamera} [description]
*/
addPerspectiveCamera: function (fieldOfView, width, height)
{
var config = this.scene.sys.game.config;
if (fieldOfView === undefined) { fieldOfView = 80; }
if (width === undefined) { width = config.width; }
if (height === undefined) { height = config.height; }
var camera = new PerspectiveCamera(this.scene, fieldOfView, width, height);
this.cameras.push(camera);
return camera;
},
/**
* [description]
*
* @method Camera3DPlugin#getCamera
* @since 3.0.0
*
* @param {string} name - [description]
*
* @return {(Phaser.Cameras.Sprite3D.OrthographicCamera|Phaser.Cameras.Sprite3D.PerspectiveCamera)} [description]
*/
getCamera: function (name)
{
for (var i = 0; i < this.cameras.length; i++)
{
if (this.cameras[i].name === name)
{
return this.cameras[i];
}
}
return null;
},
/**
* [description]
*
* @method Camera3DPlugin#removeCamera
* @since 3.0.0
*
* @param {(Phaser.Cameras.Sprite3D.OrthographicCamera|Phaser.Cameras.Sprite3D.PerspectiveCamera)} camera - [description]
*/
removeCamera: function (camera)
{
var cameraIndex = this.cameras.indexOf(camera);
if (cameraIndex !== -1)
{
this.cameras.splice(cameraIndex, 1);
}
},
/**
* [description]
*
* @method Camera3DPlugin#removeAll
* @since 3.0.0
*
* @return {(Phaser.Cameras.Sprite3D.OrthographicCamera|Phaser.Cameras.Sprite3D.PerspectiveCamera)} [description]
*/
removeAll: function ()
{
while (this.cameras.length > 0)
{
var camera = this.cameras.pop();
camera.destroy();
}
return this.main;
},
/**
* [description]
*
* @method Camera3DPlugin#update
* @since 3.0.0
*
* @param {number} timestep - [description]
* @param {number} delta - [description]
*/
update: function (timestep, delta)
{
for (var i = 0, l = this.cameras.length; i < l; ++i)
{
this.cameras[i].update(timestep, delta);
}
},
/**
* The Scene that owns this plugin is shutting down.
* We need to kill and reset all internal properties as well as stop listening to Scene events.
*
* @method Camera3DPlugin#shutdown
* @private
* @since 3.0.0
*/
shutdown: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.off('update', this.update, this);
eventEmitter.off('shutdown', this.shutdown, this);
this.removeAll();
},
/**
* The Scene that owns this plugin is being destroyed.
* We need to shutdown and then kill off all external references.
*
* @method Camera3DPlugin#destroy
* @private
* @since 3.0.0
*/
destroy: function ()
{
this.shutdown();
this.pluginManager = null;
this.game = null;
this.scene = null;
this.systems = null;
}
});
module.exports = Camera3DPlugin;

View file

@ -4,10 +4,10 @@
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../utils/Class');
var Class = require('../../../src/utils/Class');
var OrthographicCamera = require('./OrthographicCamera');
var PerspectiveCamera = require('./PerspectiveCamera');
var PluginCache = require('../../plugins/PluginCache');
var PluginCache = require('../../../src/plugins/PluginCache');
/**
* @classdesc
@ -57,7 +57,6 @@ var CameraManager = new Class({
scene.sys.events.on('start', this.start, this);
},
/**
* This method is called automatically, only once, when the Scene is first created.
* Do not invoke it directly.

View file

@ -5,8 +5,8 @@
*/
var Camera = require('./Camera');
var Class = require('../../utils/Class');
var Vector3 = require('../../math/Vector3');
var Class = require('../../../src/utils/Class');
var Vector3 = require('../../../src/math/Vector3');
// Local cache vars
var tmpVec3 = new Vector3();

View file

@ -5,8 +5,8 @@
*/
var Camera = require('./Camera');
var Class = require('../../utils/Class');
var Vector3 = require('../../math/Vector3');
var Class = require('../../../src/utils/Class');
var Vector3 = require('../../../src/math/Vector3');
// Local cache vars
var tmpVec3 = new Vector3();

View file

@ -4,11 +4,11 @@
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../utils/Class');
var GameObject = require('../GameObject');
var Sprite = require('../sprite/Sprite');
var Vector2 = require('../../math/Vector2');
var Vector4 = require('../../math/Vector4');
var Class = require('../../../../src/utils/Class');
var GameObject = require('../../../../src/gameobjects/GameObject');
var Sprite = require('../../../../src/gameobjects/sprite/Sprite');
var Vector2 = require('../../../../src/math/Vector2');
var Vector4 = require('../../../../src/math/Vector4');
/**
* @classdesc

View file

@ -4,10 +4,10 @@
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var BuildGameObject = require('../BuildGameObject');
var BuildGameObjectAnimation = require('../BuildGameObjectAnimation');
var GameObjectCreator = require('../GameObjectCreator');
var GetAdvancedValue = require('../../utils/object/GetAdvancedValue');
var BuildGameObject = require('../../../../src/gameobjects/BuildGameObject');
var BuildGameObjectAnimation = require('../../../../src/gameobjects/BuildGameObjectAnimation');
var GameObjectCreator = require('../../../../src/gameobjects/GameObjectCreator');
var GetAdvancedValue = require('../../../../src/utils/object/GetAdvancedValue');
var Sprite3D = require('./Sprite3D');
/**

View file

@ -5,7 +5,7 @@
*/
var Sprite3D = require('./Sprite3D');
var GameObjectFactory = require('../GameObjectFactory');
var GameObjectFactory = require('../../../../src/gameobjects/GameObjectFactory');
/**
* Creates a new Sprite3D Game Object and adds it to the Scene.

View file

@ -0,0 +1,47 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
camera3d: './Camera3DPlugin.js',
'camera3d.min': './Camera3DPlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'Camera3DPlugin',
libraryTarget: 'var'
},
performance: { hints: false },
optimization: {
minimizer: [
new UglifyJSPlugin({
include: /\.min\.js$/,
parallel: true,
sourceMap: false,
uglifyOptions: {
compress: true,
ie8: false,
ecma: 5,
output: {comments: false},
warnings: false
},
warningsFilter: () => false
})
]
},
plugins: [
new CleanWebpackPlugin([ 'dist' ])
]
};

View file

@ -0,0 +1,84 @@
Phaser 3 Facebook Instant Games Plugin
======================================
Starting with version 3.13 Phaser now has a dedicated plugin that provides complete support for Facebook Instant Games.
If you are using the pre-built versions of Phaser then use the file `phaser-facebook-instant-games.js` which you'll find in the `dist` folder.
If you are creating your own builds using Webpack then make sure you enable the plugin using the Webpack DefinePlugin control:
```
"typeof PLUGIN_FBINSTANT": JSON.stringify(true)
```
Building Phaser via Webpack with this set to `true` will include the plugin in the build.
## Using the Plugin
You need to include the Facebook SDK in your html and wait for the `initializeAsync` Promise to resolve before you should create your game instance:
```
<!DOCTYPE html>
<html>
<head>
<title>Phaser 3 Facebook Instant Games</title>
<meta charset="utf-8">
<script src="https://connect.facebook.net/en_US/fbinstant.6.2.js"></script>
<script src="lib/phaser-facebook-instant-games.js"></script>
</head>
<body>
FBInstant.initializeAsync().then(function() {
var config = {
type: Phaser.AUTO,
width: window.innerWidth,
height: window.innerHeight,
scene: ...
};
new Phaser.Game(config);
});
</body>
</html>
```
Now, when your game starts, you'll know that the FBInstant API is enabled and ready for use. To access the plugin use `this.facebook` from within any Scene, i.e.:
```
this.add.text(0, 0).setText(this.facebook.playerName);
```
### Preloader
To hook your games preloader into the Facebook Instant Games loader you should use a Preloader Scene like below:
```
class Preloader extends Phaser.Scene {
constructor ()
{
super('Preloader');
}
preload ()
{
this.facebook.showLoadProgress(this);
this.facebook.once('startgame', this.startGame, this);
// Now load all of your assets
}
startGame ()
{
this.scene.start('MainMenu');
}
}
```
In the above Scene it has hooked the Facebook preloader with the Phaser Loader, so every file that loads (once you add some) will make the Facebook loader update. When the load is over it will call the `startGame` function that just changes the Scene to another one.
Please look at the plugin documentation and the Facebook SDK documentation for more details about what features are available.

View file

@ -0,0 +1,26 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* @typedef {object} AdInstance
*
* @property {any} instance - Represents an instance of an ad.
* @property {string} placementID - The Audience Network placement ID of this ad instance.
* @property {boolean} shown - Has this ad already been shown in-game?
* @property {boolean} video - Is this a video ad?
*/
var AdInstance = function (placementID, instance, video)
{
return {
instance: instance,
placementID: placementID,
shown: false,
video: video
};
};
module.exports = AdInstance;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,313 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var EventEmitter = require('eventemitter3');
var LeaderboardScore = require('./LeaderboardScore');
/**
* @classdesc
* This class represents one single Leaderboard that belongs to a Facebook Instant Game.
*
* You do not need to instantiate this class directly, it will be created when you use the
* `getLeaderboard()` method of the main plugin.
*
* @class Leaderboard
* @memberOf Phaser.FacebookInstantGamesPlugin
* @constructor
* @since 3.13.0
*
* @param {Phaser.FacebookInstantGamesPlugin} plugin - A reference to the Facebook Instant Games Plugin.
* @param {any} data - An Instant Game leaderboard instance.
*/
var Leaderboard = new Class({
Extends: EventEmitter,
initialize:
function Leaderboard (plugin, data)
{
EventEmitter.call(this);
/**
* A reference to the Facebook Instant Games Plugin.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#plugin
* @type {Phaser.FacebookInstantGamesPlugin}
* @since 3.13.0
*/
this.plugin = plugin;
/**
* An Instant Game leaderboard instance.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#ref
* @type {any}
* @since 3.13.0
*/
this.ref = data;
/**
* The name of the leaderboard.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#name
* @type {string}
* @since 3.13.0
*/
this.name = data.getName();
/**
* The ID of the context that the leaderboard is associated with, or null if the leaderboard is not tied to a particular context.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#contextID
* @type {string}
* @since 3.13.0
*/
this.contextID = data.getContextID();
/**
* The total number of player entries in the leaderboard.
* This value defaults to zero. Populate it via the `getEntryCount()` method.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#entryCount
* @type {integer}
* @since 3.13.0
*/
this.entryCount = 0;
/**
* The players score object.
* This value defaults to `null`. Populate it via the `getPlayerScore()` method.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#playerScore
* @type {LeaderboardScore}
* @since 3.13.0
*/
this.playerScore = null;
/**
* The scores in the Leaderboard from the currently requested range.
* This value defaults to an empty array. Populate it via the `getScores()` method.
* The contents of this array are reset each time `getScores()` is called.
*
* @name Phaser.FacebookInstantGamesPlugin.Leaderboard#scores
* @type {LeaderboardScore[]}
* @since 3.13.0
*/
this.scores = [];
this.getEntryCount();
},
/**
* Fetches the total number of player entries in the leaderboard.
*
* The data is requested in an async call, so the result isn't available immediately.
*
* When the call completes this Leaderboard will emit the `getentrycount` event along with the count and name of the Leaderboard.
*
* @method Phaser.FacebookInstantGamesPlugin.Leaderboard#getEntryCount
* @since 3.13.0
*
* @return {this} This Leaderboard instance.
*/
getEntryCount: function ()
{
var _this = this;
this.ref.getEntryCountAsync().then(function (count)
{
_this.entryCount = count;
_this.emit('getentrycount', count, _this.name);
}).catch(function (e)
{
console.warn(e);
});
return this;
},
/**
* Updates the player's score. If the player has an existing score, the old score will only be replaced if the new score is better than it.
* NOTE: If the leaderboard is associated with a specific context, the game must be in that context to set a score for the player.
*
* The data is requested in an async call, so the result isn't available immediately.
*
* When the call completes this Leaderboard will emit the `setscore` event along with the LeaderboardScore object and the name of the Leaderboard.
*
* If the save fails the event will send `null` as the score value.
*
* @method Phaser.FacebookInstantGamesPlugin.Leaderboard#setScore
* @since 3.13.0
*
* @param {integer} score - The new score for the player. Must be a 64-bit integer number.
* @param {(string|any)} [data] - Metadata to associate with the stored score. Must be less than 2KB in size. If an object is given it will be passed to `JSON.stringify`.
*
* @return {this} This Leaderboard instance.
*/
setScore: function (score, data)
{
if (data === undefined) { data = ''; }
if (typeof data === 'object')
{
data = JSON.stringify(data);
}
var _this = this;
this.ref.setScoreAsync(score, data).then(function (entry)
{
if (entry)
{
var score = LeaderboardScore(entry);
_this.playerScore = score;
_this.emit('setscore', score, _this.name);
}
else
{
_this.emit('setscore', null, _this.name);
}
}).catch(function (e)
{
console.warn(e);
});
return this;
},
/**
* Gets the players leaderboard entry and stores it in the `playerScore` property.
*
* The data is requested in an async call, so the result isn't available immediately.
*
* When the call completes this Leaderboard will emit the `getplayerscore` event along with the score and the name of the Leaderboard.
*
* If the player has not yet saved a score, the event will send `null` as the score value, and `playerScore` will be set to `null` as well.
*
* @method Phaser.FacebookInstantGamesPlugin.Leaderboard#getPlayerScore
* @since 3.13.0
*
* @return {this} This Leaderboard instance.
*/
getPlayerScore: function ()
{
var _this = this;
this.ref.getPlayerEntryAsync().then(function (entry)
{
if (entry)
{
var score = LeaderboardScore(entry);
_this.playerScore = score;
_this.emit('getplayerscore', score, _this.name);
}
else
{
_this.emit('getplayerscore', null, _this.name);
}
}).catch(function (e)
{
console.warn(e);
});
return this;
},
/**
* Retrieves a set of leaderboard entries, ordered by score ranking in the leaderboard.
*
* The data is requested in an async call, so the result isn't available immediately.
*
* When the call completes this Leaderboard will emit the `getscores` event along with an array of LeaderboardScore entries and the name of the Leaderboard.
*
* @method Phaser.FacebookInstantGamesPlugin.Leaderboard#getScores
* @since 3.13.0
*
* @param {integer} [count=10] - The number of entries to attempt to fetch from the leaderboard. Currently, up to a maximum of 100 entries may be fetched per query.
* @param {integer} [offset=0] - The offset from the top of the leaderboard that entries will be fetched from.
*
* @return {this} This Leaderboard instance.
*/
getScores: function (count, offset)
{
if (count === undefined) { count = 10; }
if (offset === undefined) { offset = 0; }
var _this = this;
this.ref.getEntriesAsync().then(function (entries)
{
_this.scores = [];
entries.forEach(function (entry)
{
_this.scores.push(LeaderboardScore(entry));
});
_this.emit('getscores', _this.scores, _this.name);
}).catch(function (e)
{
console.warn(e);
});
return this;
},
/**
* Retrieves a set of leaderboard entries, based on the current player's connected players (including the current player), ordered by local rank within the set of connected players.
*
* The data is requested in an async call, so the result isn't available immediately.
*
* When the call completes this Leaderboard will emit the `getconnectedscores` event along with an array of LeaderboardScore entries and the name of the Leaderboard.
*
* @method Phaser.FacebookInstantGamesPlugin.Leaderboard#getConnectedScores
* @since 3.16.0
*
* @param {integer} [count=10] - The number of entries to attempt to fetch from the leaderboard. Currently, up to a maximum of 100 entries may be fetched per query.
* @param {integer} [offset=0] - The offset from the top of the leaderboard that entries will be fetched from.
*
* @return {this} This Leaderboard instance.
*/
getConnectedScores: function (count, offset)
{
if (count === undefined) { count = 10; }
if (offset === undefined) { offset = 0; }
var _this = this;
this.ref.getConnectedPlayerEntriesAsync().then(function (entries)
{
_this.scores = [];
entries.forEach(function (entry)
{
_this.scores.push(LeaderboardScore(entry));
});
_this.emit('getconnectedscores', _this.scores, _this.name);
}).catch(function (e)
{
console.warn(e);
});
return this;
}
});
module.exports = Leaderboard;

View file

@ -0,0 +1,34 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* @typedef {object} LeaderboardScore
*
* @property {integer} score - An integer score value.
* @property {string} scoreFormatted - The score value, formatted with the score format associated with the leaderboard.
* @property {integer} timestamp - The Unix timestamp of when the leaderboard entry was last updated.
* @property {integer} rank - The entry's leaderboard ranking.
* @property {string} data - The developer-specified payload associated with the score, or null if one was not set.
* @property {string} playerName - The player's localized display name.
* @property {string} playerPhotoURL - A url to the player's public profile photo.
* @property {string} playerID - The game's unique identifier for the player.
*/
var LeaderboardScore = function (entry)
{
return {
score: entry.getScore(),
scoreFormatted: entry.getFormattedScore(),
timestamp: entry.getTimestamp(),
rank: entry.getRank(),
data: entry.getExtraData(),
playerName: entry.getPlayer().getName(),
playerPhotoURL: entry.getPlayer().getPhoto(),
playerID: entry.getPlayer().getID()
};
};
module.exports = LeaderboardScore;

View file

@ -0,0 +1,32 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var GetFastValue = require('../../../src/utils/object/GetFastValue');
/**
* @typedef {object} Product
*
* @property {string} [title] - The title of the product.
* @property {string} [productID] - The product's game-specified identifier.
* @property {string} [description] - The product description.
* @property {string} [imageURI] - A link to the product's associated image.
* @property {string} [price] - The price of the product.
* @property {string} [priceCurrencyCode] - The currency code for the product.
*/
var Product = function (data)
{
return {
title: GetFastValue(data, 'title', ''),
productID: GetFastValue(data, 'productID', ''),
description: GetFastValue(data, 'description', ''),
imageURI: GetFastValue(data, 'imageURI', ''),
price: GetFastValue(data, 'price', ''),
priceCurrencyCode: GetFastValue(data, 'priceCurrencyCode', '')
};
};
module.exports = Product;

View file

@ -0,0 +1,32 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var GetFastValue = require('../../../src/utils/object/GetFastValue');
/**
* @typedef {object} Purchase
*
* @property {string} [developerPayload] - A developer-specified string, provided during the purchase of the product.
* @property {string} [paymentID] - The identifier for the purchase transaction.
* @property {string} [productID] - The product's game-specified identifier.
* @property {string} [purchaseTime] - Unix timestamp of when the purchase occurred.
* @property {string} [purchaseToken] - A token representing the purchase that may be used to consume the purchase.
* @property {string} [signedRequest] - Server-signed encoding of the purchase request.
*/
var Purchase = function (data)
{
return {
developerPayload: GetFastValue(data, 'developerPayload', ''),
paymentID: GetFastValue(data, 'paymentID', ''),
productID: GetFastValue(data, 'productID', ''),
purchaseTime: GetFastValue(data, 'purchaseTime', ''),
purchaseToken: GetFastValue(data, 'purchaseToken', ''),
signedRequest: GetFastValue(data, 'signedRequest', '')
};
};
module.exports = Purchase;

View file

@ -0,0 +1,13 @@
var fs = require('fs-extra');
var source = './plugins/spine/dist/';
var dest = '../phaser3-examples/public/plugins/';
if (fs.existsSync(dest))
{
fs.copySync(source, dest, { overwrite: true });
}
else
{
console.log('Copy-to-Examples failed: Phaser 3 Examples not present at ../phaser3-examples');
}

19720
plugins/spine/dist/SpineWebGLPlugin.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,190 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var ScenePlugin = require('../../../src/plugins/ScenePlugin');
var SpineFile = require('./SpineFile');
var SpineGameObject = require('./gameobject/SpineGameObject');
var runtime;
/**
* @classdesc
* TODO
*
* @class SpinePlugin
* @extends Phaser.Plugins.ScenePlugin
* @constructor
* @since 3.16.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
*/
var SpinePlugin = new Class({
Extends: ScenePlugin,
initialize:
function SpinePlugin (scene, pluginManager, SpineRuntime)
{
console.log('BaseSpinePlugin created');
ScenePlugin.call(this, scene, pluginManager);
var game = pluginManager.game;
// Create a custom cache to store the spine data (.atlas files)
this.cache = game.cache.addCustom('spine');
this.json = game.cache.json;
this.textures = game.textures;
this.skeletonRenderer;
this.drawDebug = false;
// Register our file type
pluginManager.registerFileType('spine', this.spineFileCallback, scene);
// Register our game object
pluginManager.registerGameObject('spine', this.createSpineFactory(this));
runtime = SpineRuntime;
},
spineFileCallback: function (key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings)
{
var multifile;
if (Array.isArray(key))
{
for (var i = 0; i < key.length; i++)
{
multifile = new SpineFile(this, key[i]);
this.addFile(multifile.files);
}
}
else
{
multifile = new SpineFile(this, key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings);
this.addFile(multifile.files);
}
return this;
},
/**
* Creates a new Spine Game Object and adds it to the Scene.
*
* @method Phaser.GameObjects.GameObjectFactory#spineFactory
* @since 3.16.0
*
* @param {number} x - The horizontal position of this Game Object.
* @param {number} y - The vertical position of this Game Object.
* @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
* @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
*
* @return {Phaser.GameObjects.Spine} The Game Object that was created.
*/
createSpineFactory: function (plugin)
{
var callback = function (x, y, key, animationName, loop)
{
var spineGO = new SpineGameObject(this.scene, plugin, x, y, key, animationName, loop);
this.displayList.add(spineGO);
this.updateList.add(spineGO);
return spineGO;
};
return callback;
},
getRuntime: function ()
{
return runtime;
},
createSkeleton: function (key, skeletonJSON)
{
var atlas = this.getAtlas(key);
var atlasLoader = new runtime.AtlasAttachmentLoader(atlas);
var skeletonJson = new runtime.SkeletonJson(atlasLoader);
var data = (skeletonJSON) ? skeletonJSON : this.json.get(key);
var skeletonData = skeletonJson.readSkeletonData(data);
var skeleton = new runtime.Skeleton(skeletonData);
return { skeletonData: skeletonData, skeleton: skeleton };
},
getBounds: function (skeleton)
{
var offset = new runtime.Vector2();
var size = new runtime.Vector2();
skeleton.getBounds(offset, size, []);
return { offset: offset, size: size };
},
createAnimationState: function (skeleton)
{
var stateData = new runtime.AnimationStateData(skeleton.data);
var state = new runtime.AnimationState(stateData);
return { stateData: stateData, state: state };
},
/**
* The Scene that owns this plugin is shutting down.
* We need to kill and reset all internal properties as well as stop listening to Scene events.
*
* @method Camera3DPlugin#shutdown
* @private
* @since 3.0.0
*/
shutdown: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.off('update', this.update, this);
eventEmitter.off('shutdown', this.shutdown, this);
this.removeAll();
},
/**
* The Scene that owns this plugin is being destroyed.
* We need to shutdown and then kill off all external references.
*
* @method Camera3DPlugin#destroy
* @private
* @since 3.0.0
*/
destroy: function ()
{
this.shutdown();
this.pluginManager = null;
this.game = null;
this.scene = null;
this.systems = null;
}
});
module.exports = SpinePlugin;

View file

@ -0,0 +1,63 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var BaseSpinePlugin = require('./BaseSpinePlugin');
var SpineCanvas = require('SpineCanvas');
/**
* @classdesc
* Just the Canvas Runtime.
*
* @class SpinePlugin
* @extends Phaser.Plugins.ScenePlugin
* @constructor
* @since 3.16.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
*/
var SpineCanvasPlugin = new Class({
Extends: BaseSpinePlugin,
initialize:
function SpineCanvasPlugin (scene, pluginManager)
{
console.log('SpineCanvasPlugin created');
BaseSpinePlugin.call(this, scene, pluginManager, SpineCanvas);
},
boot: function ()
{
this.skeletonRenderer = new SpineCanvas.canvas.SkeletonRenderer(this.game.context);
},
getAtlas: function (key)
{
var atlasData = this.cache.get(key);
if (!atlasData)
{
console.warn('No atlas data for: ' + key);
return;
}
var textures = this.textures;
var atlas = new SpineCanvas.TextureAtlas(atlasData, function (path)
{
return new SpineCanvas.canvas.CanvasTexture(textures.get(path).getSourceImage());
});
return atlas;
}
});
module.exports = SpineCanvasPlugin;

View file

@ -0,0 +1,325 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var GetFastValue = require('../../../src/utils/object/GetFastValue');
var ImageFile = require('../../../src/loader/filetypes/ImageFile.js');
var IsPlainObject = require('../../../src/utils/object/IsPlainObject');
var JSONFile = require('../../../src/loader/filetypes/JSONFile.js');
var MultiFile = require('../../../src/loader/MultiFile.js');
var TextFile = require('../../../src/loader/filetypes/TextFile.js');
/**
* @typedef {object} Phaser.Loader.FileTypes.SpineFileConfig
*
* @property {string} key - The key of the file. Must be unique within both the Loader and the Texture Manager.
* @property {string} [textureURL] - The absolute or relative URL to load the texture image file from.
* @property {string} [textureExtension='png'] - The default file extension to use for the image texture if no url is provided.
* @property {XHRSettingsObject} [textureXhrSettings] - Extra XHR Settings specifically for the texture image file.
* @property {string} [normalMap] - The filename of an associated normal map. It uses the same path and url to load as the texture image.
* @property {string} [atlasURL] - The absolute or relative URL to load the atlas data file from.
* @property {string} [atlasExtension='txt'] - The default file extension to use for the atlas data if no url is provided.
* @property {XHRSettingsObject} [atlasXhrSettings] - Extra XHR Settings specifically for the atlas data file.
*/
/**
* @classdesc
* A Spine File suitable for loading by the Loader.
*
* These are created when you use the Phaser.Loader.LoaderPlugin#spine method and are not typically created directly.
*
* For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#spine.
*
* @class SpineFile
* @extends Phaser.Loader.MultiFile
* @memberof Phaser.Loader.FileTypes
* @constructor
*
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
* @param {(string|Phaser.Loader.FileTypes.UnityAtlasFileConfig)} key - The key to use for this file, or a file configuration object.
* @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `<key>.png`, i.e. if `key` was "alien" then the URL will be "alien.png".
* @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas data file from. If undefined or `null` it will be set to `<key>.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt".
* @param {XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings.
* @param {XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings.
*/
var SpineFile = new Class({
Extends: MultiFile,
initialize:
function SpineFile (loader, key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings)
{
var json;
var atlas;
if (IsPlainObject(key))
{
var config = key;
key = GetFastValue(config, 'key');
json = new JSONFile(loader, {
key: key,
url: GetFastValue(config, 'jsonURL'),
extension: GetFastValue(config, 'jsonExtension', 'json'),
xhrSettings: GetFastValue(config, 'jsonXhrSettings')
});
atlas = new TextFile(loader, {
key: key,
url: GetFastValue(config, 'atlasURL'),
extension: GetFastValue(config, 'atlasExtension', 'atlas'),
xhrSettings: GetFastValue(config, 'atlasXhrSettings')
});
}
else
{
json = new JSONFile(loader, key, jsonURL, jsonXhrSettings);
atlas = new TextFile(loader, key, atlasURL, atlasXhrSettings);
}
atlas.cache = loader.cacheManager.custom.spine;
MultiFile.call(this, loader, 'spine', key, [ json, atlas ]);
},
/**
* Called by each File when it finishes loading.
*
* @method Phaser.Loader.MultiFile#onFileComplete
* @since 3.7.0
*
* @param {Phaser.Loader.File} file - The File that has completed processing.
*/
onFileComplete: function (file)
{
var index = this.files.indexOf(file);
if (index !== -1)
{
this.pending--;
if (file.type === 'text')
{
// Inspect the data for the files to now load
var content = file.data.split('\n');
// Extract the textures
var textures = [];
for (var t = 0; t < content.length; t++)
{
var line = content[t];
if (line.trim() === '' && t < content.length - 1)
{
line = content[t + 1];
textures.push(line);
}
}
var config = this.config;
var loader = this.loader;
var currentBaseURL = loader.baseURL;
var currentPath = loader.path;
var currentPrefix = loader.prefix;
var baseURL = GetFastValue(config, 'baseURL', currentBaseURL);
var path = GetFastValue(config, 'path', currentPath);
var prefix = GetFastValue(config, 'prefix', currentPrefix);
var textureXhrSettings = GetFastValue(config, 'textureXhrSettings');
loader.setBaseURL(baseURL);
loader.setPath(path);
loader.setPrefix(prefix);
for (var i = 0; i < textures.length; i++)
{
var textureURL = textures[i];
var key = '_SP_' + textureURL;
var image = new ImageFile(loader, key, textureURL, textureXhrSettings);
this.addToMultiFile(image);
loader.addFile(image);
}
// Reset the loader settings
loader.setBaseURL(currentBaseURL);
loader.setPath(currentPath);
loader.setPrefix(currentPrefix);
}
}
},
/**
* Adds this file to its target cache upon successful loading and processing.
*
* @method Phaser.Loader.FileTypes.SpineFile#addToCache
* @since 3.16.0
*/
addToCache: function ()
{
if (this.isReadyToProcess())
{
var fileJSON = this.files[0];
fileJSON.addToCache();
var fileText = this.files[1];
fileText.addToCache();
for (var i = 2; i < this.files.length; i++)
{
var file = this.files[i];
var key = file.key.substr(4).trim();
this.loader.textureManager.addImage(key, file.data);
file.pendingDestroy();
}
this.complete = true;
}
}
});
/**
* Adds a Unity YAML based Texture Atlas, or array of atlases, to the current load queue.
*
* You can call this method from within your Scene's `preload`, along with any other files you wish to load:
*
* ```javascript
* function preload ()
* {
* this.load.unityAtlas('mainmenu', 'images/MainMenu.png', 'images/MainMenu.txt');
* }
* ```
*
* The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts,
* or if it's already running, when the next free load slot becomes available. This happens automatically if you
* are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued
* it means you cannot use the file immediately after calling this method, but must wait for the file to complete.
* The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the
* Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
* loaded.
*
* If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring
* its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details.
*
* Phaser expects the atlas data to be provided in a YAML formatted text file as exported from Unity.
*
* Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle.
*
* The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load.
* The key should be unique both in terms of files being loaded and files already present in the Texture Manager.
* Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file
* then remove it from the Texture Manager first, before loading a new one.
*
* Instead of passing arguments you can pass a configuration object, such as:
*
* ```javascript
* this.load.unityAtlas({
* key: 'mainmenu',
* textureURL: 'images/MainMenu.png',
* atlasURL: 'images/MainMenu.txt'
* });
* ```
*
* See the documentation for `Phaser.Loader.FileTypes.SpineFileConfig` for more details.
*
* Once the atlas has finished loading you can use frames from it as textures for a Game Object by referencing its key:
*
* ```javascript
* this.load.unityAtlas('mainmenu', 'images/MainMenu.png', 'images/MainMenu.json');
* // and later in your game ...
* this.add.image(x, y, 'mainmenu', 'background');
* ```
*
* To get a list of all available frames within an atlas please consult your Texture Atlas software.
*
* If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files
* key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and
* this is what you would use to retrieve the image from the Texture Manager.
*
* The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it.
*
* If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien"
* and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although
* this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL.
*
* Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image,
* then you can specify it by providing an array as the `url` where the second element is the normal map:
*
* ```javascript
* this.load.unityAtlas('mainmenu', [ 'images/MainMenu.png', 'images/MainMenu-n.png' ], 'images/MainMenu.txt');
* ```
*
* Or, if you are using a config object use the `normalMap` property:
*
* ```javascript
* this.load.unityAtlas({
* key: 'mainmenu',
* textureURL: 'images/MainMenu.png',
* normalMap: 'images/MainMenu-n.png',
* atlasURL: 'images/MainMenu.txt'
* });
* ```
*
* The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings.
* Normal maps are a WebGL only feature.
*
* Note: The ability to load this type of file will only be available if the Unity Atlas File type has been built into Phaser.
* It is available in the default build but can be excluded from custom builds.
*
* @method Phaser.Loader.LoaderPlugin#spine
* @fires Phaser.Loader.LoaderPlugin#addFileEvent
* @since 3.16.0
*
* @param {(string|Phaser.Loader.FileTypes.SpineFileConfig|Phaser.Loader.FileTypes.SpineFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
* @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `<key>.png`, i.e. if `key` was "alien" then the URL will be "alien.png".
* @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas data file from. If undefined or `null` it will be set to `<key>.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt".
* @param {XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings.
* @param {XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings.
*
* @return {Phaser.Loader.LoaderPlugin} The Loader instance.
FileTypesManager.register('spine', function (key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings)
{
var multifile;
// Supports an Object file definition in the key argument
// Or an array of objects in the key argument
// Or a single entry where all arguments have been defined
if (Array.isArray(key))
{
for (var i = 0; i < key.length; i++)
{
multifile = new SpineFile(this, key[i]);
this.addFile(multifile.files);
}
}
else
{
multifile = new SpineFile(this, key, jsonURL, atlasURL, jsonXhrSettings, atlasXhrSettings);
this.addFile(multifile.files);
}
return this;
});
*/
module.exports = SpineFile;

View file

@ -0,0 +1,111 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var BaseSpinePlugin = require('./BaseSpinePlugin');
var SpineCanvas = require('SpineCanvas');
var SpineWebGL = require('SpineWebGL');
var runtime;
/**
* @classdesc
* Both Canvas and WebGL Runtimes together in a single plugin.
*
* @class SpinePlugin
* @extends Phaser.Plugins.ScenePlugin
* @constructor
* @since 3.16.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
*/
var SpineCanvasPlugin = new Class({
Extends: BaseSpinePlugin,
initialize:
function SpineCanvasPlugin (scene, pluginManager)
{
console.log('SpinePlugin created');
BaseSpinePlugin.call(this, scene, pluginManager);
var game = pluginManager.game;
runtime = (game.config.renderType === 1) ? SpineCanvas : SpineWebGL;
},
boot: function ()
{
this.skeletonRenderer = (this.game.config.renderType === 1) ? SpineCanvas.canvas.SkeletonRenderer(this.game.context) : SpineWebGL;
},
getRuntime: function ()
{
return runtime;
},
createSkeleton: function (key)
{
var atlasData = this.cache.get(key);
if (!atlasData)
{
console.warn('No skeleton data for: ' + key);
return;
}
var textures = this.textures;
var useWebGL = this.game.config.renderType;
var atlas = new runtime.TextureAtlas(atlasData, function (path)
{
if (useWebGL)
{
// return new SpineCanvas.canvas.CanvasTexture(textures.get(path).getSourceImage());
}
else
{
return new SpineCanvas.canvas.CanvasTexture(textures.get(path).getSourceImage());
}
});
var atlasLoader = new runtime.AtlasAttachmentLoader(atlas);
var skeletonJson = new runtime.SkeletonJson(atlasLoader);
var skeletonData = skeletonJson.readSkeletonData(this.json.get(key));
var skeleton = new runtime.Skeleton(skeletonData);
return { skeletonData: skeletonData, skeleton: skeleton };
},
getBounds: function (skeleton)
{
var offset = new runtime.Vector2();
var size = new runtime.Vector2();
skeleton.getBounds(offset, size, []);
return { offset: offset, size: size };
},
createAnimationState: function (skeleton)
{
var stateData = new runtime.AnimationStateData(skeleton.data);
var state = new runtime.AnimationState(stateData);
return { stateData: stateData, state: state };
}
});
module.exports = SpineCanvasPlugin;

View file

@ -0,0 +1,90 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../src/utils/Class');
var BaseSpinePlugin = require('./BaseSpinePlugin');
var SpineWebGL = require('SpineWebGL');
var Matrix4 = require('../../../src/math/Matrix4');
/**
* @classdesc
* Just the WebGL Runtime.
*
* @class SpinePlugin
* @extends Phaser.Plugins.ScenePlugin
* @constructor
* @since 3.16.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
*/
var SpineWebGLPlugin = new Class({
Extends: BaseSpinePlugin,
initialize:
function SpineWebGLPlugin (scene, pluginManager)
{
console.log('SpineWebGLPlugin created');
BaseSpinePlugin.call(this, scene, pluginManager, SpineWebGL);
this.gl;
this.mvp;
this.shader;
this.batcher;
this.debugRenderer;
this.debugShader;
},
boot: function ()
{
var gl = this.game.renderer.gl;
this.gl = gl;
this.mvp = new Matrix4();
// Create a simple shader, mesh, model-view-projection matrix and SkeletonRenderer.
this.shader = SpineWebGL.webgl.Shader.newTwoColoredTextured(gl);
this.batcher = new SpineWebGL.webgl.PolygonBatcher(gl);
this.skeletonRenderer = new SpineWebGL.webgl.SkeletonRenderer(gl);
this.skeletonRenderer.premultipliedAlpha = true;
this.shapes = new SpineWebGL.webgl.ShapeRenderer(gl);
this.debugRenderer = new SpineWebGL.webgl.SkeletonDebugRenderer(gl);
this.debugShader = SpineWebGL.webgl.Shader.newColored(gl);
},
getAtlas: function (key)
{
var atlasData = this.cache.get(key);
if (!atlasData)
{
console.warn('No atlas data for: ' + key);
return;
}
var textures = this.textures;
var gl = this.game.renderer.gl;
var atlas = new SpineWebGL.TextureAtlas(atlasData, function (path)
{
return new SpineWebGL.webgl.GLTexture(gl, textures.get(path).getSourceImage());
});
return atlas;
}
});
module.exports = SpineWebGLPlugin;

View file

@ -0,0 +1,298 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../../src/utils/Class');
var ComponentsAlpha = require('../../../../src/gameobjects/components/Alpha');
var ComponentsBlendMode = require('../../../../src/gameobjects/components/BlendMode');
var ComponentsDepth = require('../../../../src/gameobjects/components/Depth');
var ComponentsFlip = require('../../../../src/gameobjects/components/Flip');
var ComponentsScrollFactor = require('../../../../src/gameobjects/components/ScrollFactor');
var ComponentsTransform = require('../../../../src/gameobjects/components/Transform');
var ComponentsVisible = require('../../../../src/gameobjects/components/Visible');
var GameObject = require('../../../../src/gameobjects/GameObject');
var SpineGameObjectRender = require('./SpineGameObjectRender');
/**
* @classdesc
* TODO
*
* @class SpineGameObject
* @constructor
* @since 3.16.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
*/
var SpineGameObject = new Class({
Extends: GameObject,
Mixins: [
ComponentsAlpha,
ComponentsBlendMode,
ComponentsDepth,
ComponentsFlip,
ComponentsScrollFactor,
ComponentsTransform,
ComponentsVisible,
SpineGameObjectRender
],
initialize:
function SpineGameObject (scene, plugin, x, y, key, animationName, loop)
{
GameObject.call(this, scene, 'Spine');
this.plugin = plugin;
this.runtime = plugin.getRuntime();
this.skeleton = null;
this.skeletonData = null;
this.state = null;
this.stateData = null;
this.drawDebug = false;
this.timeScale = 1;
this.setPosition(x, y);
if (key)
{
this.setSkeleton(key, animationName, loop);
}
},
setSkeletonFromJSON: function (atlasDataKey, skeletonJSON, animationName, loop)
{
return this.setSkeleton(atlasDataKey, skeletonJSON, animationName, loop);
},
setSkeleton: function (atlasDataKey, animationName, loop, skeletonJSON)
{
var data = this.plugin.createSkeleton(atlasDataKey, skeletonJSON);
this.skeletonData = data.skeletonData;
var skeleton = data.skeleton;
skeleton.flipY = (this.scene.sys.game.config.renderType === 1);
skeleton.setToSetupPose();
skeleton.updateWorldTransform();
skeleton.setSkinByName('default');
this.skeleton = skeleton;
// AnimationState
data = this.plugin.createAnimationState(skeleton);
if (this.state)
{
this.state.clearListeners();
this.state.clearListenerNotifications();
}
this.state = data.state;
this.stateData = data.stateData;
var _this = this;
this.state.addListener({
event: function (trackIndex, event)
{
// Event on a Track
_this.emit('spine.event', _this, trackIndex, event);
},
complete: function (trackIndex, loopCount)
{
// Animation on Track x completed, loop count
_this.emit('spine.complete', _this, trackIndex, loopCount);
},
start: function (trackIndex)
{
// Animation on Track x started
_this.emit('spine.start', _this, trackIndex);
},
end: function (trackIndex)
{
// Animation on Track x ended
_this.emit('spine.end', _this, trackIndex);
}
});
if (animationName)
{
this.setAnimation(0, animationName, loop);
}
return this;
},
// http://esotericsoftware.com/spine-runtimes-guide
getAnimationList: function ()
{
var output = [];
var skeletonData = this.skeletonData;
if (skeletonData)
{
for (var i = 0; i < skeletonData.animations.length; i++)
{
output.push(skeletonData.animations[i].name);
}
}
return output;
},
play: function (animationName, loop)
{
if (loop === undefined)
{
loop = false;
}
return this.setAnimation(0, animationName, loop);
},
setAnimation: function (trackIndex, animationName, loop)
{
this.state.setAnimation(trackIndex, animationName, loop);
return this;
},
addAnimation: function (trackIndex, animationName, loop, delay)
{
return this.state.addAnimation(trackIndex, animationName, loop, delay);
},
setEmptyAnimation: function (trackIndex, mixDuration)
{
this.state.setEmptyAnimation(trackIndex, mixDuration);
return this;
},
clearTrack: function (trackIndex)
{
this.state.clearTrack(trackIndex);
return this;
},
clearTracks: function ()
{
this.state.clearTracks();
return this;
},
setSkinByName: function (skinName)
{
this.skeleton.setSkinByName(skinName);
return this;
},
setSkin: function (newSkin)
{
var skeleton = this.skeleton;
skeleton.setSkin(newSkin);
skeleton.setSlotsToSetupPose();
this.state.apply(skeleton);
return this;
},
setMix: function (fromName, toName, duration)
{
this.stateData.setMix(fromName, toName, duration);
return this;
},
findBone: function (boneName)
{
return this.skeleton.findBone(boneName);
},
findBoneIndex: function (boneName)
{
return this.skeleton.findBoneIndex(boneName);
},
findSlot: function (slotName)
{
return this.skeleton.findSlot(slotName);
},
findSlotIndex: function (slotName)
{
return this.skeleton.findSlotIndex(slotName);
},
getBounds: function ()
{
return this.plugin.getBounds(this.skeleton);
},
preUpdate: function (time, delta)
{
var skeleton = this.skeleton;
skeleton.flipX = this.flipX;
skeleton.flipY = this.flipY;
this.state.update((delta / 1000) * this.timeScale);
this.state.apply(skeleton);
this.emit('spine.update', skeleton);
skeleton.updateWorldTransform();
},
/**
* Internal destroy handler, called as part of the destroy process.
*
* @method Phaser.GameObjects.RenderTexture#preDestroy
* @protected
* @since 3.16.0
*/
preDestroy: function ()
{
if (this.state)
{
this.state.clearListeners();
this.state.clearListenerNotifications();
}
this.plugin = null;
this.runtime = null;
this.skeleton = null;
this.skeletonData = null;
this.state = null;
this.stateData = null;
}
});
module.exports = SpineGameObject;

View file

@ -0,0 +1,57 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var SetTransform = require('../../../../src/renderer/canvas/utils/SetTransform');
/**
* Renders this Game Object with the Canvas Renderer to the given Camera.
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
* This method should not be called directly. It is a utility function of the Render module.
*
* @method Phaser.GameObjects.SpineGameObject#renderCanvas
* @since 3.16.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.SpineGameObject} src - The Game Object being rendered in this call.
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
*/
var SpineGameObjectCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
var context = renderer.currentContext;
var plugin = src.plugin;
var skeleton = src.skeleton;
var skeletonRenderer = plugin.skeletonRenderer;
if (!skeleton || !SetTransform(renderer, context, src, camera, parentMatrix))
{
return;
}
skeletonRenderer.ctx = context;
context.save();
skeletonRenderer.draw(skeleton);
if (plugin.drawDebug || src.drawDebug)
{
context.strokeStyle = '#00ff00';
context.beginPath();
context.moveTo(-1000, 0);
context.lineTo(1000, 0);
context.moveTo(0, -1000);
context.lineTo(0, 1000);
context.stroke();
}
context.restore();
};
module.exports = SpineGameObjectCanvasRenderer;

View file

@ -0,0 +1,33 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var SpineGameObject = require('./SpineGameObject');
var GameObjectFactory = require('../../../../src/gameobjects/GameObjectFactory');
/**
* Creates a new Spine Game Object Game Object and adds it to the Scene.
*
* Note: This method will only be available if the Spine Plugin has been built or loaded into Phaser.
*
* @method Phaser.GameObjects.GameObjectFactory#spine
* @since 3.16.0
*
* @param {number} x - The horizontal position of this Game Object.
* @param {number} y - The vertical position of this Game Object.
* @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
* @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
*
* @return {Phaser.GameObjects.SpineGameObject} The Game Object that was created.
*/
GameObjectFactory.register('spine', function (x, y, key, animation)
{
var spine = new SpineGameObject(this.scene, x, y, key, animation);
this.displayList.add(spine);
this.updateList.add(spine);
return spine;
});

View file

@ -0,0 +1,25 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var renderWebGL = require('../../../../src/utils/NOOP');
var renderCanvas = require('../../../../src/utils/NOOP');
if (typeof WEBGL_RENDERER)
{
renderWebGL = require('./SpineGameObjectWebGLRenderer');
}
if (typeof CANVAS_RENDERER)
{
renderCanvas = require('./SpineGameObjectCanvasRenderer');
}
module.exports = {
renderWebGL: renderWebGL,
renderCanvas: renderCanvas
};

View file

@ -0,0 +1,121 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
/**
* Renders this Game Object with the Canvas Renderer to the given Camera.
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
* This method should not be called directly. It is a utility function of the Render module.
*
* @method Phaser.GameObjects.SpineGameObject#renderCanvas
* @since 3.16.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.SpineGameObject} src - The Game Object being rendered in this call.
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
*/
var SpineGameObjectWebGLRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
{
var pipeline = renderer.currentPipeline;
var plugin = src.plugin;
var mvp = plugin.mvp;
var shader = plugin.shader;
var batcher = plugin.batcher;
var runtime = src.runtime;
var skeleton = src.skeleton;
var skeletonRenderer = plugin.skeletonRenderer;
if (!skeleton)
{
return;
}
renderer.clearPipeline();
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
// - 90 degrees to account for the difference in Spine vs. Phaser rotation
spriteMatrix.applyITRS(src.x, src.y, src.rotation - 1.5707963267948966, src.scaleX, src.scaleY);
camMatrix.copyFrom(camera.matrix);
if (parentMatrix)
{
// Multiply the camera by the parent matrix
camMatrix.multiplyWithOffset(parentMatrix, -camera.scrollX * src.scrollFactorX, -camera.scrollY * src.scrollFactorY);
// Undo the camera scroll
spriteMatrix.e = src.x;
spriteMatrix.f = src.y;
// Multiply by the Sprite matrix, store result in calcMatrix
camMatrix.multiply(spriteMatrix, calcMatrix);
}
else
{
spriteMatrix.e -= camera.scrollX * src.scrollFactorX;
spriteMatrix.f -= camera.scrollY * src.scrollFactorY;
// Multiply by the Sprite matrix, store result in calcMatrix
camMatrix.multiply(spriteMatrix, calcMatrix);
}
var width = renderer.width;
var height = renderer.height;
var data = calcMatrix.decomposeMatrix();
mvp.ortho(0, width, 0, height, 0, 1);
mvp.translateXYZ(data.translateX, height - data.translateY, 0);
mvp.rotateZ(CounterClockwise(data.rotation));
mvp.scaleXYZ(data.scaleX, data.scaleY, 1);
// For a Stage 1 release we'll handle it like this:
shader.bind();
shader.setUniformi(runtime.webgl.Shader.SAMPLER, 0);
shader.setUniform4x4f(runtime.webgl.Shader.MVP_MATRIX, mvp.val);
// For Stage 2, we'll move to using a custom pipeline, so Spine objects are batched
batcher.begin(shader);
skeletonRenderer.premultipliedAlpha = true;
skeletonRenderer.draw(batcher, skeleton);
batcher.end();
shader.unbind();
if (plugin.drawDebug || src.drawDebug)
{
var debugShader = plugin.debugShader;
var debugRenderer = plugin.debugRenderer;
var shapes = plugin.shapes;
debugShader.bind();
debugShader.setUniform4x4f(runtime.webgl.Shader.MVP_MATRIX, mvp.val);
shapes.begin(debugShader);
debugRenderer.draw(shapes, skeleton);
shapes.end();
debugShader.unbind();
}
renderer.rebindPipeline(pipeline);
};
module.exports = SpineGameObjectWebGLRenderer;

View file

@ -0,0 +1,27 @@
Spine Runtimes Software License v2.5
Copyright (c) 2013-2016, Esoteric Software
All rights reserved.
You are granted a perpetual, non-exclusive, non-sublicensable, and
non-transferable license to use, install, execute, and perform the Spine
Runtimes software and derivative works solely for personal or internal
use. Without the written permission of Esoteric Software (see Section 2 of
the Spine Software License Agreement), you may not (a) modify, translate,
adapt, or develop new applications using the Spine Runtimes or otherwise
create derivative works or improvements of the Spine Runtimes or (b) remove,
delete, alter, or obscure any trademarks or any copyright, trademark, patent,
or other intellectual property or proprietary rights notices on or in the
Software, including any copy thereof. Redistributions in binary or source
form must include this license and terms.
THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
'use strict';
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpinePlugin': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // string
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]', // string
umdNamedDefine: true
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
}
]
},
resolve: {
alias: {
'SpineCanvas': './runtimes/spine-canvas.js',
'SpineWebGL': './runtimes/spine-webgl.js'
},
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new CleanWebpackPlugin([ 'dist' ]),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/spine/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
],
devtool: 'source-map'
};

View file

@ -0,0 +1,94 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpinePlugin': './SpineWebGLPlugin.js',
'SpinePlugin.min': './SpineWebGLPlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // string
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]', // string
umdNamedDefine: true
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
}
]
},
resolve: {
alias: {
'SpineCanvas': './runtimes/spine-canvas.js',
'SpineWebGL': './runtimes/spine-webgl.js'
},
},
optimization: {
minimizer: [
new UglifyJSPlugin({
include: /\.min\.js$/,
parallel: true,
sourceMap: false,
uglifyOptions: {
compress: true,
ie8: false,
ecma: 5,
output: {comments: false},
warnings: false
},
warningsFilter: () => false
})
]
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new CleanWebpackPlugin([ 'dist' ]),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/spine/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
]
};

View file

@ -0,0 +1,76 @@
'use strict';
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpineCanvasPlugin': './SpineCanvasPlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpineCanvasPlugin',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // string
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]', // string
umdNamedDefine: true
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
}
]
},
resolve: {
alias: {
'SpineCanvas': './runtimes/spine-canvas.js',
'SpineWebGL': './runtimes/spine-webgl.js'
},
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(false)
}),
new CleanWebpackPlugin([ 'dist' ]),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/spine/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
],
devtool: 'source-map'
};

View file

@ -0,0 +1,94 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpineCanvasPlugin': './SpineCanvasPlugin.js',
'SpineCanvasPlugin.min': './SpineCanvasPlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpineCanvasPlugin',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // string
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]', // string
umdNamedDefine: true
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
}
]
},
resolve: {
alias: {
'SpineCanvas': './runtimes/spine-canvas.js',
'SpineWebGL': './runtimes/spine-webgl.js'
},
},
optimization: {
minimizer: [
new UglifyJSPlugin({
include: /\.min\.js$/,
parallel: true,
sourceMap: false,
uglifyOptions: {
compress: true,
ie8: false,
ecma: 5,
output: {comments: false},
warnings: false
},
warningsFilter: () => false
})
]
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(false)
}),
new CleanWebpackPlugin([ 'dist' ]),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/spine/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
]
};

View file

@ -0,0 +1,76 @@
'use strict';
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpineWebGLPlugin': './SpineWebGLPlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpineWebGLPlugin',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // string
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]', // string
umdNamedDefine: true
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
}
]
},
resolve: {
alias: {
'SpineCanvas': './runtimes/spine-canvas.js',
'SpineWebGL': './runtimes/spine-webgl.js'
},
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(false),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new CleanWebpackPlugin([ 'dist' ]),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/spine/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
],
devtool: 'source-map'
};

View file

@ -0,0 +1,94 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const exec = require('child_process').exec;
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpineWebGLPlugin': './SpineWebGLPlugin.js',
'SpineWebGLPlugin.min': './SpineWebGLPlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpineWebGLPlugin',
libraryTarget: 'umd',
sourceMapFilename: '[file].map',
devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // string
devtoolFallbackModuleFilenameTemplate: 'webpack:///[resource-path]?[hash]', // string
umdNamedDefine: true
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
use: 'exports-loader?spine'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'imports-loader?this=>window'
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
use: 'exports-loader?spine'
}
]
},
resolve: {
alias: {
'SpineCanvas': './runtimes/spine-canvas.js',
'SpineWebGL': './runtimes/spine-webgl.js'
},
},
optimization: {
minimizer: [
new UglifyJSPlugin({
include: /\.min\.js$/,
parallel: true,
sourceMap: false,
uglifyOptions: {
compress: true,
ie8: false,
ecma: 5,
output: {comments: false},
warnings: false
},
warningsFilter: () => false
})
]
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(false),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new CleanWebpackPlugin([ 'dist' ]),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/spine/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
]
};

View file

@ -5,8 +5,6 @@ BitmapMask.frag
BitmapMask.vert
DeferredDiffuse.frag
DeferredDiffuse.vert
FlatTint.frag
FlatTint.vert
ForwardDiffuse.frag
GBuffer.frag
TextureTint.frag

View file

@ -0,0 +1,30 @@
let fs = require('fs-extra');
let source = './build/phaser-facebook-instant-games.js';
let sourceMap = './build/phaser-facebook-instant-games.js.map';
let destFolder = '../fbtest1/lib/';
let dest = '../fbtest1/lib/phaser-facebook-instant-games.js';
let destMap = '../fbtest1/lib/phaser-facebook-instant-games.js.map';
if (fs.existsSync(destFolder))
{
fs.copy(sourceMap, destMap, function (err) {
if (err)
{
return console.error(err);
}
});
fs.copy(source, dest, function (err) {
if (err)
{
return console.error(err);
}
console.log('Build copied to ' + dest);
});
}

View file

@ -1,38 +1,43 @@
let fs = require('fs-extra');
// let sloc = require('node-sloc');
let sloc = require('node-sloc');
let source = './build/phaser.js';
let sourceMap = './build/phaser.js.map';
let dest = '../phaser3-examples/public/build/dev.js';
let destMap = '../phaser3-examples/public/build/phaser.js.map';
let sourceCore = './build/phaser-core.js';
let sourceMapCore = './build/phaser-core.js.map';
let destCore = '../phaser3-examples/public/build/phaser-core.js';
let destMapCore = '../phaser3-examples/public/build/phaser-core.js.map';
let sourceFB = './build/phaser-facebook-instant-games.js';
let sourceFBMap = './build/phaser-facebook-instant-games.js.map';
let destFB = '../fbtest1/lib/dev.js';
let destFBMap = '../fbtest1/lib/phaser.js.map';
/*
if (fs.existsSync(destFB))
{
fs.copy(source, destFB, function (err) {
if (err)
{
return console.error(err);
}
console.log('Build copied to ' + destFB);
});
fs.copy(sourceMap, destFBMap, function (err) {
if (err)
{
return console.error(err);
}
});
}
*/
if (fs.existsSync(dest))
{
fs.copy(sourceMapCore, destMapCore, function (err) {
if (err)
{
return console.error(err);
}
});
fs.copy(sourceCore, destCore, function (err) {
if (err)
{
return console.error(err);
}
console.log('Build copied to ' + destCore);
});
fs.copy(sourceMap, destMap, function (err) {
if (err)
@ -56,13 +61,13 @@ if (fs.existsSync(dest))
extensions: [ '.js' ]
};
// sloc(options).then((res) => {
// console.log('Source files: ' + res.sloc.files + '\nLines of code: ' + res.sloc.sloc);
// });
sloc(options).then((res) => {
console.log('Source files: ' + res.sloc.files + '\nLines of code: ' + res.sloc.sloc);
});
});
}
else
{
console.log('Copy-to-Examples failed: Phaser 3 Examples not present at ../phaser3-examples');
// console.log('Copy-to-Examples failed: Phaser 3 Examples not present at ../phaser3-examples');
}

View file

@ -9,11 +9,17 @@ v.log('{bgYellow}{black} \\/ \\/ \\/ \\/
v.log('{bgYellow}{black} Available commands: ');
v.log('{white}* npm run {green}build {cyan} Build dev version of Phaser with Webpack');
v.log('{white}* npm run {green}watch {cyan} Build dev & put Webpack into watch mode');
v.log('{white}* npm run {green}dist {cyan} Build dist & min versions of Phaser');
v.log('{white}* npm run {green}watch {cyan} Build dev & put Webpack in watch mode');
v.log('{white}* npm run {green}dist {cyan} Build dist versions of Phaser');
v.log('{white}* npm run {green}lint {cyan} ESLint check Phaser source');
v.log('{white}* npm run {green}lintfix {cyan} ESLint check and fix Phaser source');
v.log('{white}* npm run {green}sloc {cyan} Get source code & comments line count');
v.log('{white}* npm run {green}bundleshaders {cyan} Convert vert/frag shaders to js');
v.log('{white}* npm run {green}plugin.cam3d {cyan} Build Camera3D Plugin');
v.log('{white}Facebook Instant Games:');
v.log('{white}* npm run {green}buildfb {cyan} Build dev Phaser FB with Webpack');
v.log('{white}* npm run {green}watchfb {cyan} Build FB dev in Webpack watch mode');
v.log('{white}* npm run {green}distfb {cyan} Build dist versions of Phaser FB');
v.log('{white}* npm run {green}distfull {cyan} Build dist versions of Phaser + FB');
v.log('{bgYellow}{black} https://phaser.io https://labs.phaser.io ');

View file

@ -7,7 +7,7 @@
/**
* @callback CallCallback
*
* @param {Phaser.GameObjects.GameObject} item - [description]
* @param {Phaser.GameObjects.GameObject} item - The Game Object to run the callback on.
*/
/**

View file

@ -5,7 +5,9 @@
*/
/**
* [description]
* Takes an array of Game Objects and positions them on evenly spaced points around the perimeter of a Circle.
*
* If you wish to pass a `Phaser.GameObjects.Circle` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.PlaceOnCircle
* @since 3.0.0
@ -13,9 +15,9 @@
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Circle} circle - [description]
* @param {number} [startAngle=0] - [description]
* @param {number} [endAngle=6.28] - [description]
* @param {Phaser.Geom.Circle} circle - The Circle to position the Game Objects on.
* @param {number} [startAngle=0] - Optional angle to start position from, in radians.
* @param {number} [endAngle=6.28] - Optional angle to stop position at, in radians.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -5,7 +5,9 @@
*/
/**
* [description]
* Takes an array of Game Objects and positions them on evenly spaced points around the perimeter of an Ellipse.
*
* If you wish to pass a `Phaser.GameObjects.Ellipse` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.PlaceOnEllipse
* @since 3.0.0
@ -13,9 +15,9 @@
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Ellipse} ellipse - [description]
* @param {number} [startAngle=0] - [description]
* @param {number} [endAngle=6.28] - [description]
* @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to position the Game Objects on.
* @param {number} [startAngle=0] - Optional angle to start position from, in radians.
* @param {number} [endAngle=6.28] - Optional angle to stop position at, in radians.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,7 @@
var GetPoints = require('../geom/line/GetPoints');
/**
* [description]
* Positions an array of Game Objects on evenly spaced points of a Line.
*
* @function Phaser.Actions.PlaceOnLine
* @since 3.0.0
@ -15,7 +15,7 @@ var GetPoints = require('../geom/line/GetPoints');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Line} line - [description]
* @param {Phaser.Geom.Line} line - The Line to position the Game Objects on.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -8,14 +8,11 @@ var MarchingAnts = require('../geom/rectangle/MarchingAnts');
var RotateLeft = require('../utils/array/RotateLeft');
var RotateRight = require('../utils/array/RotateRight');
// Place the items in the array around the perimeter of the given rectangle.
// Placement starts from the top-left of the rectangle, and proceeds in a
// clockwise direction. If the shift parameter is given you can offset where
// placement begins.
/**
* [description]
* Takes an array of Game Objects and positions them on evenly spaced points around the perimeter of a Rectangle.
*
* Placement starts from the top-left of the rectangle, and proceeds in a clockwise direction.
* If the `shift` parameter is given you can offset where placement begins.
*
* @function Phaser.Actions.PlaceOnRectangle
* @since 3.0.0
@ -23,8 +20,8 @@ var RotateRight = require('../utils/array/RotateRight');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Rectangle} rect - [description]
* @param {integer} [shift=1] - [description]
* @param {Phaser.Geom.Rectangle} rect - The Rectangle to position the Game Objects on.
* @param {integer} [shift=1] - An optional positional offset.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -4,11 +4,12 @@
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
// var GetPointsOnLine = require('../geom/line/GetPointsOnLine');
var BresenhamPoints = require('../geom/line/BresenhamPoints');
/**
* [description]
* Takes an array of Game Objects and positions them on evenly spaced points around the edges of a Triangle.
*
* If you wish to pass a `Phaser.GameObjects.Triangle` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.PlaceOnTriangle
* @since 3.0.0
@ -16,8 +17,8 @@ var BresenhamPoints = require('../geom/line/BresenhamPoints');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Triangle} triangle - [description]
* @param {number} [stepRate=1] - [description]
* @param {Phaser.Geom.Triangle} triangle - The Triangle to position the Game Objects on.
* @param {number} [stepRate=1] - An optional step rate, to increase or decrease the packing of the Game Objects on the lines.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,9 @@
var Random = require('../geom/circle/Random');
/**
* [description]
* Takes an array of Game Objects and positions them at random locations within the Circle.
*
* If you wish to pass a `Phaser.GameObjects.Circle` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.RandomCircle
* @since 3.0.0
@ -15,7 +17,7 @@ var Random = require('../geom/circle/Random');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Circle} circle - [description]
* @param {Phaser.Geom.Circle} circle - The Circle to position the Game Objects within.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,9 @@
var Random = require('../geom/ellipse/Random');
/**
* [description]
* Takes an array of Game Objects and positions them at random locations within the Ellipse.
*
* If you wish to pass a `Phaser.GameObjects.Ellipse` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.RandomEllipse
* @since 3.0.0
@ -15,7 +17,7 @@ var Random = require('../geom/ellipse/Random');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Ellipse} ellipse - [description]
* @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to position the Game Objects within.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,9 @@
var Random = require('../geom/line/Random');
/**
* [description]
* Takes an array of Game Objects and positions them at random locations on the Line.
*
* If you wish to pass a `Phaser.GameObjects.Line` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.RandomLine
* @since 3.0.0
@ -15,7 +17,7 @@ var Random = require('../geom/line/Random');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Line} line - [description]
* @param {Phaser.Geom.Line} line - The Line to position the Game Objects randomly on.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,7 @@
var Random = require('../geom/rectangle/Random');
/**
* [description]
* Takes an array of Game Objects and positions them at random locations within the Ellipse.
*
* @function Phaser.Actions.RandomRectangle
* @since 3.0.0
@ -15,7 +15,7 @@ var Random = require('../geom/rectangle/Random');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Rectangle} rect - [description]
* @param {Phaser.Geom.Rectangle} rect - The Rectangle to position the Game Objects within.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,9 @@
var Random = require('../geom/triangle/Random');
/**
* [description]
* Takes an array of Game Objects and positions them at random locations within the Triangle.
*
* If you wish to pass a `Phaser.GameObjects.Triangle` Shape to this function, you should pass its `geom` property.
*
* @function Phaser.Actions.RandomTriangle
* @since 3.0.0
@ -15,7 +17,7 @@ var Random = require('../geom/triangle/Random');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {Phaser.Geom.Triangle} triangle - [description]
* @param {Phaser.Geom.Triangle} triangle - The Triangle to position the Game Objects within.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,7 @@
var MathRotateAroundDistance = require('../math/RotateAroundDistance');
/**
* [description]
* Rotates an array of Game Objects around a point by the given angle and distance.
*
* @function Phaser.Actions.RotateAroundDistance
* @since 3.0.0

View file

@ -5,7 +5,9 @@
*/
/**
* [description]
* Passes all provided Game Objects to the Input Manager to enable them for input with identical areas and callbacks.
*
* @see {@link Phaser.GameObjects.GameObject#setInteractive}
*
* @function Phaser.Actions.SetHitArea
* @since 3.0.0
@ -13,8 +15,8 @@
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {*} hitArea - [description]
* @param {HitAreaCallback} hitAreaCallback - [description]
* @param {*} hitArea - Either an input configuration object, or a geometric shape that defines the hit area for the Game Object. If not specified a Rectangle will be used.
* @param {HitAreaCallback} hitAreaCallback - A callback to be invoked when the Game Object is interacted with. If you provide a shape you must also provide a callback.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -5,7 +5,7 @@
*/
/**
* [description]
* Takes an array of Game Objects, or any objects that have the public method setTint() and then updates it to the given value(s). You can specify tint color per corner or provide only one color value for `topLeft` parameter, in which case whole item will be tinted with that color.
*
* @function Phaser.Actions.SetTint
* @since 3.0.0
@ -13,10 +13,10 @@
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {number} topLeft - [description]
* @param {number} [topRight] - [description]
* @param {number} [bottomLeft] - [description]
* @param {number} [bottomRight] - [description]
* @param {number} topLeft - The tint being applied to top-left corner of item. If other parameters are given no value, this tint will be applied to whole item.
* @param {number} [topRight] - The tint to be applied to top-right corner of item.
* @param {number} [bottomLeft] - The tint to be applied to the bottom-left corner of item.
* @param {number} [bottomRight] - The tint to be applied to the bottom-right corner of item.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,9 +7,11 @@
var Vector2 = require('../math/Vector2');
/**
* Iterate through items changing the position of each element to
* be that of the element that came before it in the array (or after it if direction = 1)
* Iterate through the items array changing the position of each element to be that of the element that came before
* it in the array (or after it if direction = 1)
*
* The first items position is set to x/y.
*
* The final x/y coords are returned
*
* @function Phaser.Actions.ShiftPosition
@ -19,10 +21,10 @@ var Vector2 = require('../math/Vector2');
* @generic {Phaser.Math.Vector2} O - [output,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {number} x - [description]
* @param {number} y - [description]
* @param {integer} [direction=0] - [description]
* @param {(Phaser.Math.Vector2|object)} [output] - [description]
* @param {number} x - The x coordinate to place the first item in the array at.
* @param {number} y - The y coordinate to place the first item in the array at.
* @param {integer} [direction=0] - The iteration direction. 0 = first to last and 1 = last to first.
* @param {(Phaser.Math.Vector2|object)} [output] - An optional objec to store the final objects position in.
*
* @return {Phaser.Math.Vector2} The output vector.
*/

View file

@ -7,7 +7,9 @@
var MathSmoothStep = require('../math/SmoothStep');
/**
* [description]
* Smoothstep is a sigmoid-like interpolation and clamping function.
*
* The function depends on three parameters, the input x, the "left edge" and the "right edge", with the left edge being assumed smaller than the right edge. The function receives a real number x as an argument and returns 0 if x is less than or equal to the left edge, 1 if x is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial, between 0 and 1 otherwise. The slope of the smoothstep function is zero at both edges. This is convenient for creating a sequence of transitions using smoothstep to interpolate each segment as an alternative to using more sophisticated or expensive interpolation techniques.
*
* @function Phaser.Actions.SmoothStep
* @since 3.0.0
@ -15,10 +17,10 @@ var MathSmoothStep = require('../math/SmoothStep');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {string} property - [description]
* @param {number} min - [description]
* @param {number} max - [description]
* @param {number} inc - [description]
* @param {string} property - The property of the Game Object to interpolate.
* @param {number} min - The minimum interpolation value.
* @param {number} max - The maximum interpolation value.
* @param {boolean} [inc=false] - Should the values be incremented? `true` or set (`false`)
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -7,7 +7,9 @@
var MathSmootherStep = require('../math/SmootherStep');
/**
* [description]
* Smootherstep is a sigmoid-like interpolation and clamping function.
*
* The function depends on three parameters, the input x, the "left edge" and the "right edge", with the left edge being assumed smaller than the right edge. The function receives a real number x as an argument and returns 0 if x is less than or equal to the left edge, 1 if x is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial, between 0 and 1 otherwise. The slope of the smoothstep function is zero at both edges. This is convenient for creating a sequence of transitions using smoothstep to interpolate each segment as an alternative to using more sophisticated or expensive interpolation techniques.
*
* @function Phaser.Actions.SmootherStep
* @since 3.0.0
@ -15,10 +17,10 @@ var MathSmootherStep = require('../math/SmootherStep');
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {string} property - [description]
* @param {number} min - [description]
* @param {number} max - [description]
* @param {number} inc - [description]
* @param {string} property - The property of the Game Object to interpolate.
* @param {number} min - The minimum interpolation value.
* @param {number} max - The maximum interpolation value.
* @param {boolean} [inc=false] - Should the values be incremented? `true` or set (`false`)
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
*/

View file

@ -5,7 +5,16 @@
*/
/**
* [description]
* Takes an array of Game Objects and then modifies their `property` so the value equals, or is incremented, the
* calculated spread value.
*
* The spread value is derived from the given `min` and `max` values and the total number of items in the array.//#endregion
*
* For example, to cause an array of Sprites to change in alpha from 0 to 1 you could call:
*
* ```javascript
* Phaser.Actions.Spread(itemsArray, 'alpha', 0, 1);
* ```
*
* @function Phaser.Actions.Spread
* @since 3.0.0
@ -13,12 +22,12 @@
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action.
* @param {string} property - [description]
* @param {number} min - [description]
* @param {number} max - [description]
* @param {number} [inc=false] - [description]
* @param {string} property - The property of the Game Object to spread.
* @param {number} min - The minimum value.
* @param {number} max - The maximum value.
* @param {boolean} [inc=false] - Should the values be incremented? `true` or set (`false`)
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action.
* @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that were passed to this Action.
*/
var Spread = function (items, property, min, max, inc)
{

View file

@ -5,7 +5,8 @@
*/
/**
* [description]
* Takes an array of Game Objects and toggles the visibility of each one.
* Those previously `visible = false` will become `visible = true`, and vice versa.
*
* @function Phaser.Actions.ToggleVisible
* @since 3.0.0

View file

@ -6,6 +6,7 @@
var Clamp = require('../math/Clamp');
var Class = require('../utils/Class');
var EventEmitter = require('eventemitter3');
var FindClosestInSorted = require('../utils/array/FindClosestInSorted');
var Frame = require('./AnimationFrame');
var GetValue = require('../utils/object/GetValue');
@ -64,7 +65,8 @@ var GetValue = require('../utils/object/GetValue');
* So multiple Game Objects can have playheads all pointing to this one Animation instance.
*
* @class Animation
* @memberOf Phaser.Animations
* @memberof Phaser.Animations
* @extends Phaser.Events.EventEmitter
* @constructor
* @since 3.0.0
*
@ -74,10 +76,14 @@ var GetValue = require('../utils/object/GetValue');
*/
var Animation = new Class({
Extends: EventEmitter,
initialize:
function Animation (manager, key, config)
{
EventEmitter.call(this);
/**
* A reference to the global Animation Manager
*
@ -529,14 +535,20 @@ var Animation = new Class({
component.msPerFrame = this.msPerFrame;
component.skipMissedFrames = this.skipMissedFrames;
component._timeScale = 1;
component._delay = this.delay;
component._repeat = this.repeat;
component._repeatDelay = this.repeatDelay;
component._yoyo = this.yoyo;
}
component.updateFrame(this.frames[startFrame]);
var frame = this.frames[startFrame];
if (startFrame === 0 && !component.forward)
{
frame = this.getLastFrame();
}
component.updateFrame(frame);
},
/**
@ -577,18 +589,21 @@ var Animation = new Class({
// Yoyo? (happens before repeat)
if (component._yoyo)
{
component.forward = false;
component.updateFrame(frame.prevFrame);
// Delay for the current frame
this.getNextTick(component);
this.handleYoyoFrame(component, false);
}
else if (component.repeatCounter > 0)
{
// Repeat (happens before complete)
if (component._reverse && component.forward)
{
component.forward = false;
}
else
{
this.repeatAnimation(component);
}
}
else
{
this.completeAnimation(component);
@ -596,12 +611,60 @@ var Animation = new Class({
}
else
{
component.updateFrame(frame.nextFrame);
this.getNextTick(component);
this.updateAndGetNextTick(component, frame.nextFrame);
}
},
/**
* Handle the yoyo functionality in nextFrame and previousFrame methods.
*
* @method Phaser.Animations.Animation#handleYoyoFrame
* @private
* @since 3.12.0
*
* @param {Phaser.GameObjects.Components.Animation} component - The Animation Component to advance.
* @param {boolean} isReverse - Is animation in reverse mode? (Default: false)
*/
handleYoyoFrame: function (component, isReverse)
{
if (!isReverse) { isReverse = false; }
if (component._reverse === !isReverse && component.repeatCounter > 0)
{
component.forward = isReverse;
this.repeatAnimation(component);
return;
}
if (component._reverse !== isReverse && component.repeatCounter === 0)
{
this.completeAnimation(component);
return;
}
component.forward = isReverse;
var frame = (isReverse) ? component.currentFrame.nextFrame : component.currentFrame.prevFrame;
this.updateAndGetNextTick(component, frame);
},
/**
* Returns the animation last frame.
*
* @method Phaser.Animations.Animation#getLastFrame
* @since 3.12.0
*
* @return {Phaser.Animations.AnimationFrame} component - The Animation Last Frame.
*/
getLastFrame: function ()
{
return this.frames[this.frames.length - 1];
},
/**
* [description]
*
@ -620,11 +683,24 @@ var Animation = new Class({
{
// We're at the start of the animation
if (component.repeatCounter > 0)
if (component._yoyo)
{
this.handleYoyoFrame(component, true);
}
else if (component.repeatCounter > 0)
{
if (component._reverse && !component.forward)
{
component.currentFrame = this.getLastFrame();
this.repeatAnimation(component);
}
else
{
// Repeat (happens before complete)
component.forward = true;
this.repeatAnimation(component);
}
}
else
{
this.completeAnimation(component);
@ -632,10 +708,24 @@ var Animation = new Class({
}
else
{
component.updateFrame(frame.prevFrame);
this.updateAndGetNextTick(component, frame.prevFrame);
}
},
/**
* Update Frame and Wait next tick.
*
* @method Phaser.Animations.Animation#updateAndGetNextTick
* @private
* @since 3.12.0
*
* @param {Phaser.Animations.AnimationFrame} frame - An Animation frame.
*/
updateAndGetNextTick: function (component, frame)
{
component.updateFrame(frame);
this.getNextTick(component);
}
},
/**
@ -705,9 +795,7 @@ var Animation = new Class({
{
component.repeatCounter--;
component.forward = true;
component.updateFrame(component.currentFrame.nextFrame);
component.updateFrame(component.currentFrame[(component.forward) ? 'nextFrame' : 'prevFrame']);
if (component.isPlaying)
{
@ -715,13 +803,20 @@ var Animation = new Class({
component.pendingRepeat = false;
component.parent.emit('animationrepeat', this, component.currentFrame, component.repeatCounter);
var frame = component.currentFrame;
var parent = component.parent;
this.emit('repeat', this, frame);
parent.emit('animationrepeat-' + this.key, this, frame, component.repeatCounter, parent);
parent.emit('animationrepeat', this, frame, component.repeatCounter, parent);
}
}
},
/**
* [description]
* Sets the texture frame the animation uses for rendering.
*
* @method Phaser.Animations.Animation#setFrame
* @since 3.0.0
@ -742,7 +837,7 @@ var Animation = new Class({
},
/**
* [description]
* Converts the animation data to JSON.
*
* @method Phaser.Animations.Animation#toJSON
* @since 3.0.0
@ -857,6 +952,8 @@ var Animation = new Class({
*/
destroy: function ()
{
this.removeAllListeners();
this.manager.off('pauseall', this.pause, this);
this.manager.off('resumeall', this.resume, this);

View file

@ -19,13 +19,12 @@ var Class = require('../utils/Class');
* A single frame in an Animation sequence.
*
* An AnimationFrame consists of a reference to the Texture it uses for rendering, references to other
* frames in the animation, and index data. It also has the ability to fire its own `onUpdate` callback
* and modify the animation timing.
* frames in the animation, and index data. It also has the ability to modify the animation timing.
*
* AnimationFrames are generated automatically by the Animation class.
*
* @class AnimationFrame
* @memberOf Phaser.Animations
* @memberof Phaser.Animations
* @constructor
* @since 3.0.0
*
@ -82,7 +81,7 @@ var AnimationFrame = new Class({
* @name Phaser.Animations.AnimationFrame#isFirst
* @type {boolean}
* @default false
* @readOnly
* @readonly
* @since 3.0.0
*/
this.isFirst = false;
@ -93,7 +92,7 @@ var AnimationFrame = new Class({
* @name Phaser.Animations.AnimationFrame#isLast
* @type {boolean}
* @default false
* @readOnly
* @readonly
* @since 3.0.0
*/
this.isLast = false;
@ -104,7 +103,7 @@ var AnimationFrame = new Class({
* @name Phaser.Animations.AnimationFrame#prevFrame
* @type {?Phaser.Animations.AnimationFrame}
* @default null
* @readOnly
* @readonly
* @since 3.0.0
*/
this.prevFrame = null;
@ -115,7 +114,7 @@ var AnimationFrame = new Class({
* @name Phaser.Animations.AnimationFrame#nextFrame
* @type {?Phaser.Animations.AnimationFrame}
* @default null
* @readOnly
* @readonly
* @since 3.0.0
*/
this.nextFrame = null;
@ -138,7 +137,7 @@ var AnimationFrame = new Class({
* @name Phaser.Animations.AnimationFrame#progress
* @type {number}
* @default 0
* @readOnly
* @readonly
* @since 3.0.0
*/
this.progress = 0;

View file

@ -14,8 +14,8 @@ var Pad = require('../utils/string/Pad');
/**
* @typedef {object} JSONAnimationManager
*
* @property {JSONAnimation[]} anims - [description]
* @property {number} globalTimeScale - [description]
* @property {JSONAnimation[]} anims - An array of all Animations added to the Animation Manager.
* @property {number} globalTimeScale - The global time scale of the Animation Manager.
*/
/**
@ -30,11 +30,11 @@ var Pad = require('../utils/string/Pad');
*
* @class AnimationManager
* @extends Phaser.Events.EventEmitter
* @memberOf Phaser.Animations
* @memberof Phaser.Animations
* @constructor
* @since 3.0.0
*
* @param {Phaser.Game} game - [description]
* @param {Phaser.Game} game - A reference to the Phaser.Game instance.
*/
var AnimationManager = new Class({
@ -47,7 +47,7 @@ var AnimationManager = new Class({
EventEmitter.call(this);
/**
* [description]
* A reference to the Phaser.Game instance.
*
* @name Phaser.Animations.AnimationManager#game
* @type {Phaser.Game}
@ -57,7 +57,7 @@ var AnimationManager = new Class({
this.game = game;
/**
* [description]
* A reference to the Texture Manager.
*
* @name Phaser.Animations.AnimationManager#textureManager
* @type {Phaser.Textures.TextureManager}
@ -67,7 +67,9 @@ var AnimationManager = new Class({
this.textureManager = null;
/**
* [description]
* The global time scale of the Animation Manager.
*
* This scales the time delta between two frames, thus influencing the speed of time for the Animation Manager.
*
* @name Phaser.Animations.AnimationManager#globalTimeScale
* @type {number}
@ -77,7 +79,9 @@ var AnimationManager = new Class({
this.globalTimeScale = 1;
/**
* [description]
* The Animations registered in the Animation Manager.
*
* This map should be modified with the {@link #add} and {@link #create} methods of the Animation Manager.
*
* @name Phaser.Animations.AnimationManager#anims
* @type {Phaser.Structs.Map.<string, Phaser.Animations.Animation>}
@ -87,7 +91,7 @@ var AnimationManager = new Class({
this.anims = new CustomMap();
/**
* [description]
* Whether the Animation Manager is paused along with all of its Animations.
*
* @name Phaser.Animations.AnimationManager#paused
* @type {boolean}
@ -97,7 +101,7 @@ var AnimationManager = new Class({
this.paused = false;
/**
* [description]
* The name of this Animation Manager.
*
* @name Phaser.Animations.AnimationManager#name
* @type {string}
@ -109,7 +113,7 @@ var AnimationManager = new Class({
},
/**
* [description]
* Registers event listeners after the Game boots.
*
* @method Phaser.Animations.AnimationManager#boot
* @since 3.0.0
@ -122,14 +126,14 @@ var AnimationManager = new Class({
},
/**
* [description]
* Adds an existing Animation to the Animation Manager.
*
* @method Phaser.Animations.AnimationManager#add
* @fires AddAnimationEvent
* @since 3.0.0
*
* @param {string} key - [description]
* @param {Phaser.Animations.Animation} animation - [description]
* @param {string} key - The key under which the Animation should be added. The Animation will be updated with it. Must be unique.
* @param {Phaser.Animations.Animation} animation - The Animation which should be added to the Animation Manager.
*
* @return {Phaser.Animations.AnimationManager} This Animation Manager.
*/
@ -151,43 +155,74 @@ var AnimationManager = new Class({
},
/**
* [description]
* Checks to see if the given key is already in use within the Animation Manager or not.
*
* Animations are global. Keys created in one scene can be used from any other Scene in your game. They are not Scene specific.
*
* @method Phaser.Animations.AnimationManager#exists
* @since 3.16.0
*
* @param {string} key - The key of the Animation to check.
*
* @return {boolean} `true` if the Animation already exists in the Animation Manager, or `false` if the key is available.
*/
exists: function (key)
{
return this.anims.has(key);
},
/**
* Creates a new Animation and adds it to the Animation Manager.
*
* Animations are global. Once created, you can use them in any Scene in your game. They are not Scene specific.
*
* If an invalid key is given this method will return `false`.
*
* If you pass the key of an animation that already exists in the Animation Manager, that animation will be returned.
*
* A brand new animation is only created if the key is valid and not already in use.
*
* If you wish to re-use an existing key, call `AnimationManager.remove` first, then this method.
*
* @method Phaser.Animations.AnimationManager#create
* @fires AddAnimationEvent
* @since 3.0.0
*
* @param {AnimationConfig} config - [description]
* @param {AnimationConfig} config - The configuration settings for the Animation.
*
* @return {Phaser.Animations.Animation} The Animation that was created.
* @return {(Phaser.Animations.Animation|false)} The Animation that was created, or `false` is the key is already in use.
*/
create: function (config)
{
var key = config.key;
if (!key || this.anims.has(key))
{
console.warn('Invalid Animation Key, or Key already in use: ' + key);
return;
}
var anim = false;
var anim = new Animation(this, key, config);
if (key)
{
anim = this.get(key);
if (!anim)
{
anim = new Animation(this, key, config);
this.anims.set(key, anim);
this.emit('add', key, anim);
}
}
return anim;
},
/**
* [description]
* Loads this Animation Manager's Animations and settings from a JSON object.
*
* @method Phaser.Animations.AnimationManager#fromJSON
* @since 3.0.0
*
* @param {(string|JSONAnimationManager|JSONAnimation)} data - [description]
* @param {boolean} [clearCurrentAnimations=false] - [description]
* @param {(string|JSONAnimationManager|JSONAnimation)} data - The JSON object to parse.
* @param {boolean} [clearCurrentAnimations=false] - If set to `true`, the current animations will be removed (`anims.clear()`). If set to `false` (default), the animations in `data` will be added.
*
* @return {Phaser.Animations.Animation[]} An array containing all of the Animation objects that were created as a result of this call.
*/
@ -232,13 +267,13 @@ var AnimationManager = new Class({
/**
* @typedef {object} GenerateFrameNamesConfig
*
* @property {string} [prefix=''] - [description]
* @property {integer} [start=0] - [description]
* @property {integer} [end=0] - [description]
* @property {string} [suffix=''] - [description]
* @property {integer} [zeroPad=0] - [description]
* @property {AnimationFrameConfig[]} [outputArray=[]] - [description]
* @property {boolean} [frames=false] - [description]
* @property {string} [prefix=''] - The string to append to every resulting frame name if using a range or an array of `frames`.
* @property {integer} [start=0] - If `frames` is not provided, the number of the first frame to return.
* @property {integer} [end=0] - If `frames` is not provided, the number of the last frame to return.
* @property {string} [suffix=''] - The string to append to every resulting frame name if using a range or an array of `frames`.
* @property {integer} [zeroPad=0] - The minimum expected lengths of each resulting frame's number. Numbers will be left-padded with zeroes until they are this long, then prepended and appended to create the resulting frame name.
* @property {AnimationFrameConfig[]} [outputArray=[]] - The array to append the created configuration objects to.
* @property {boolean} [frames=false] - If provided as an array, the range defined by `start` and `end` will be ignored and these frame numbers will be used.
*/
/**
@ -247,10 +282,10 @@ var AnimationManager = new Class({
* @method Phaser.Animations.AnimationManager#generateFrameNames
* @since 3.0.0
*
* @param {string} key - [description]
* @param {GenerateFrameNamesConfig} [config] - [description]
* @param {string} key - The key for the texture containing the animation frames.
* @param {GenerateFrameNamesConfig} [config] - The configuration object for the animation frame names.
*
* @return {AnimationFrameConfig[]} [description]
* @return {AnimationFrameConfig[]} The array of {@link AnimationFrameConfig} objects.
*/
generateFrameNames: function (key, config)
{
@ -319,23 +354,25 @@ var AnimationManager = new Class({
/**
* @typedef {object} GenerateFrameNumbersConfig
*
* @property {integer} [start=0] - [description]
* @property {integer} [end=-1] - [description]
* @property {boolean} [first=false] - [description]
* @property {AnimationFrameConfig[]} [outputArray=[]] - [description]
* @property {boolean} [frames=false] - [description]
* @property {integer} [start=0] - The starting frame of the animation.
* @property {integer} [end=-1] - The ending frame of the animation.
* @property {(boolean|integer)} [first=false] - A frame to put at the beginning of the animation, before `start` or `outputArray` or `frames`.
* @property {AnimationFrameConfig[]} [outputArray=[]] - An array to concatenate the output onto.
* @property {(boolean|integer[])} [frames=false] - A custom sequence of frames.
*/
/**
* [description]
* Generate an array of {@link AnimationFrameConfig} objects from a texture key and configuration object.
*
* Generates objects with numbered frame names, as configured by the given {@link GenerateFrameNumbersConfig}.
*
* @method Phaser.Animations.AnimationManager#generateFrameNumbers
* @since 3.0.0
*
* @param {string} key - [description]
* @param {GenerateFrameNumbersConfig} config - [description]
* @param {string} key - The key for the texture containing the animation frames.
* @param {GenerateFrameNumbersConfig} config - The configuration object for the animation frames.
*
* @return {AnimationFrameConfig[]} [description]
* @return {AnimationFrameConfig[]} The array of {@link AnimationFrameConfig} objects.
*/
generateFrameNumbers: function (key, config)
{
@ -391,14 +428,14 @@ var AnimationManager = new Class({
},
/**
* [description]
* Get an Animation.
*
* @method Phaser.Animations.AnimationManager#get
* @since 3.0.0
*
* @param {string} key - [description]
* @param {string} key - The key of the Animation to retrieve.
*
* @return {Phaser.Animations.Animation} [description]
* @return {Phaser.Animations.Animation} The Animation.
*/
get: function (key)
{
@ -406,16 +443,16 @@ var AnimationManager = new Class({
},
/**
* Load an Animation into a Game Objects Animation Component.
* Load an Animation into a Game Object's Animation Component.
*
* @method Phaser.Animations.AnimationManager#load
* @since 3.0.0
*
* @param {Phaser.GameObjects.GameObject} child - [description]
* @param {string} key - [description]
* @param {(string|integer)} [startFrame] - [description]
* @param {Phaser.GameObjects.GameObject} child - The Game Object to load the animation into.
* @param {string} key - The key of the animation to load.
* @param {(string|integer)} [startFrame] - The name of a start frame to set on the loaded animation.
*
* @return {Phaser.GameObjects.GameObject} [description]
* @return {Phaser.GameObjects.GameObject} The Game Object with the animation loaded into it.
*/
load: function (child, key, startFrame)
{
@ -430,7 +467,7 @@ var AnimationManager = new Class({
},
/**
* [description]
* Pause all animations.
*
* @method Phaser.Animations.AnimationManager#pauseAll
* @fires PauseAllAnimationEvent
@ -451,13 +488,13 @@ var AnimationManager = new Class({
},
/**
* [description]
* Play an animation on the given Game Objects that have an Animation Component.
*
* @method Phaser.Animations.AnimationManager#play
* @since 3.0.0
*
* @param {string} key - [description]
* @param {Phaser.GameObjects.GameObject} child - [description]
* @param {string} key - The key of the animation to play on the Game Object.
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Objects to play the animation on.
*
* @return {Phaser.Animations.AnimationManager} This Animation Manager.
*/
@ -484,13 +521,13 @@ var AnimationManager = new Class({
},
/**
* [description]
* Remove an animation.
*
* @method Phaser.Animations.AnimationManager#remove
* @fires RemoveAnimationEvent
* @since 3.0.0
*
* @param {string} key - [description]
* @param {string} key - The key of the animation to remove.
*
* @return {Phaser.Animations.Animation} [description]
*/
@ -509,7 +546,7 @@ var AnimationManager = new Class({
},
/**
* [description]
* Resume all paused animations.
*
* @method Phaser.Animations.AnimationManager#resumeAll
* @fires ResumeAllAnimationEvent
@ -530,7 +567,7 @@ var AnimationManager = new Class({
},
/**
* Takes an array of Game Objects that have the Animation Component and then
* Takes an array of Game Objects that have an Animation Component and then
* starts the given animation playing on them, each one offset by the
* `stagger` amount given to this method.
*
@ -540,7 +577,7 @@ var AnimationManager = new Class({
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {string} key - The key of the animation to play on the Game Objects.
* @param {Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have the Animation Component.
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component.
* @param {number} [stagger=0] - The amount of time, in milliseconds, to offset each play time by.
*
* @return {Phaser.Animations.AnimationManager} This Animation Manager.
@ -570,7 +607,7 @@ var AnimationManager = new Class({
},
/**
* [description]
* Get the animation data as javascript object by giving key, or get the data of all animations as array of objects, if key wasn't provided.
*
* @method Phaser.Animations.AnimationManager#toJSON
* @since 3.0.0
@ -602,7 +639,8 @@ var AnimationManager = new Class({
},
/**
* [description]
* Destroy this Animation Manager and clean up animation definitions and references to other objects.
* This method should not be called directly. It will be called automatically as a response to a `destroy` event from the Phaser.Game instance.
*
* @method Phaser.Animations.AnimationManager#destroy
* @since 3.0.0

View file

@ -6,10 +6,11 @@
var Class = require('../utils/Class');
var CONST = require('../const');
var Device = require('../device');
var GetFastValue = require('../utils/object/GetFastValue');
var GetValue = require('../utils/object/GetValue');
var IsPlainObject = require('../utils/object/IsPlainObject');
var MATH = require('../math/const');
var PhaserMath = require('../math/');
var NOOP = require('../utils/NOOP');
var DefaultPlugins = require('../plugins/DefaultPlugins');
var ValueToColor = require('../display/color/ValueToColor');
@ -23,98 +24,224 @@ var ValueToColor = require('../display/color/ValueToColor');
/**
* @callback BootCallback
*
* @param {Phaser.Game} game - [description]
* @param {Phaser.Game} game - The game.
*/
/**
* Config object containing various sound settings.
*
* @typedef {object} AudioConfig
*
* @property {boolean} [disableWebAudio=false] - Use HTML5 Audio instead of Web Audio.
* @property {AudioContext} [context] - An existing Web Audio context.
* @property {boolean} [noAudio=false] - Disable all audio output.
*
* @see Phaser.Sound.SoundManagerCreator
*/
/**
* @typedef {object} InputConfig
*
* @property {(boolean|KeyboardInputConfig)} [keyboard=true] - Keyboard input configuration. `true` uses the default configuration and `false` disables keyboard input.
* @property {(boolean|MouseInputConfig)} [mouse=true] - Mouse input configuration. `true` uses the default configuration and `false` disables mouse input.
* @property {(boolean|TouchInputConfig)} [touch=true] - Touch input configuration. `true` uses the default configuration and `false` disables touch input.
* @property {(boolean|GamepadInputConfig)} [gamepad=false] - Gamepad input configuration. `true` enables gamepad input.
* @property {integer} [activePointers=1] - The maximum number of touch pointers. See {@link Phaser.Input.InputManager#pointers}.
* @property {number} [smoothFactor=0] - The smoothing factor to apply during Pointer movement. See {@link Phaser.Input.Pointer#smoothFactor}.
*/
/**
* @typedef {object} MouseInputConfig
*
* @property {*} [target=null] - Where the Mouse Manager listens for mouse input events. The default is the game canvas.
* @property {boolean} [capture=true] - Whether mouse input events have `preventDefault` called on them.
*/
/**
* @typedef {object} KeyboardInputConfig
*
* @property {*} [target=window] - Where the Keyboard Manager listens for keyboard input events.
* @property {?integer} [capture] - `preventDefault` will be called on every non-modified key which has a key code in this array. By default it is empty.
*/
/**
* @typedef {object} TouchInputConfig
*
* @property {*} [target=null] - Where the Touch Manager listens for touch input events. The default is the game canvas.
* @property {boolean} [capture=true] - Whether touch input events have preventDefault() called on them.
*/
/**
* @typedef {object} GamepadInputConfig
*
* @property {*} [target=window] - Where the Gamepad Manager listens for gamepad input events.
*/
/**
* @typedef {object} BannerConfig
*
* @property {boolean} [hidePhaser=false] - Omit Phaser's name and version from the banner.
* @property {string} [text='#ffffff'] - The color of the banner text.
* @property {string[]} [background] - The background colors of the banner.
*/
/**
* @typedef {object} FPSConfig
*
* @property {integer} [min=10] - [description]
* @property {integer} [target=60] - [description]
* @property {boolean} [forceSetTimeOut=false] - [description]
* @property {integer} [deltaHistory=10] - [description]
* @property {integer} [panicMax=120] - [description]
* @property {integer} [min=5] - The minimum acceptable rendering rate, in frames per second.
* @property {integer} [target=60] - The optimum rendering rate, in frames per second.
* @property {boolean} [forceSetTimeOut=false] - Use setTimeout instead of requestAnimationFrame to run the game loop.
* @property {integer} [deltaHistory=10] - Calculate the average frame delta from this many consecutive frame intervals.
* @property {integer} [panicMax=120] - The amount of frames the time step counts before we trust the delta values again.
*/
/**
* @typedef {object} RenderConfig
*
* @property {boolean} [antialias=true] - When set to `true`, WebGL uses linear interpolation to draw scaled or rotated textures, giving a smooth appearance. When set to `false`, WebGL uses nearest-neighbor interpolation, giving a crisper appearance. `false` also disables antialiasing of the game canvas itself, if the browser supports it, when the game canvas is scaled.
* @property {boolean} [pixelArt=false] - Sets `antialias` and `roundPixels` to true. This is the best setting for pixel-art games.
* @property {boolean} [autoResize=true] - Automatically resize the Game Canvas if you resize the renderer.
* @property {boolean} [roundPixels=false] - Draw texture-based Game Objects at only whole-integer positions. Game Objects without textures, like Graphics, ignore this property.
* @property {boolean} [transparent=false] - Whether the game canvas will be transparent.
* @property {boolean} [clearBeforeRender=true] - Whether the game canvas will be cleared between each rendering frame.
* @property {boolean} [premultipliedAlpha=true] - In WebGL mode, the drawing buffer contains colors with pre-multiplied alpha.
* @property {boolean} [failIfMajorPerformanceCaveat=false] - Let the browser abort creating a WebGL context if it judges performance would be unacceptable.
* @property {string} [powerPreference='default'] - "high-performance", "low-power" or "default". A hint to the browser on how much device power the game might use.
* @property {integer} [batchSize=2000] - The default WebGL batch size.
* @property {integer} [maxLights=10] - The maximum number of lights allowed to be visible within range of a single Camera in the LightManager.
*/
/**
* @typedef {object} ScaleConfig
*
* @property {(integer|string)} [width=1024] - The base width of your game.
* @property {(integer|string)} [height=768] - The base height of your game.
* @property {integer} [zoom=1] - The zoom value of the game canvas.
* @property {number} [resolution=1] - The rendering resolution of the canvas.
* @property {(HTMLElement|string)} [parent] - The DOM element that will contain the game canvas, or its `id`. If null (the default) or if the named element doesn't exist, the game canvas is inserted directly into the document body.
* @property {integer} [mode=0] - The scale mode to apply to the canvas. SHOW_ALL, EXACT_FIT, USER_SCALE, or RESIZE.
* @property {integer} [minWidth] - The minimum width the canvas can be scaled down to.
* @property {integer} [minHeight] - The minimum height the canvas can be scaled down to.
* @property {integer} [maxWidth] - The maximum width the canvas can be scaled up to.
* @property {integer} [maxHeight] - The maximum height the canvas can be scaled up to.
*/
/**
* @typedef {object} CallbacksConfig
*
* @property {BootCallback} [preBoot=NOOP] - A function to run at the start of the boot sequence.
* @property {BootCallback} [postBoot=NOOP] - A function to run at the end of the boot sequence. At this point, all the game systems have started and plugins have been loaded.
*/
/**
* @typedef {object} LoaderConfig
*
* @property {string} [baseURL] - [description]
* @property {string} [path] - [description]
* @property {integer} [maxParallelDownloads=32] - [description]
* @property {(string|undefined)} [crossOrigin=undefined] - [description]
* @property {string} [responseType] - [description]
* @property {boolean} [async=true] - [description]
* @property {string} [user] - [description]
* @property {string} [password] - [description]
* @property {integer} [timeout=0] - [description]
* @property {string} [baseURL] - A URL used to resolve paths given to the loader. Example: 'http://labs.phaser.io/assets/'.
* @property {string} [path] - A URL path used to resolve relative paths given to the loader. Example: 'images/sprites/'.
* @property {integer} [maxParallelDownloads=32] - The maximum number of resources the loader will start loading at once.
* @property {(string|undefined)} [crossOrigin=undefined] - 'anonymous', 'use-credentials', or `undefined`. If you're not making cross-origin requests, leave this as `undefined`. See {@link https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes}.
* @property {string} [responseType] - The response type of the XHR request, e.g. `blob`, `text`, etc.
* @property {boolean} [async=true] - Should the XHR request use async or not?
* @property {string} [user] - Optional username for all XHR requests.
* @property {string} [password] - Optional password for all XHR requests.
* @property {integer} [timeout=0] - Optional XHR timeout value, in ms.
*/
/**
* @typedef {object} DOMContainerConfig
*
* @property {boolean} [createContainer=false] - Create a div element in which DOM Elements will be contained. You must also provide a parent.
* @property {boolean} [behindCanvas=false] - Place the DOM Container behind the Phaser Canvas. The default is to place it over the Canvas.
*/
/**
* @typedef {object} ImagesConfig
*
* @property {string} [default] - URL to use for the 'default' texture.
* @property {string} [missing] - URL to use for the 'missing' texture.
*/
/**
* @typedef {object} PhysicsConfig
*
* @property {string} [default] - The default physics system. It will be started for each scene. Phaser provides 'arcade', 'impact', and 'matter'.
* @property {ArcadeWorldConfig} [arcade] - Arcade Physics configuration.
* @property {Phaser.Physics.Impact.WorldConfig} [impact] - Impact Physics configuration.
* @property {object} [matter] - Matter Physics configuration.
*/
/**
* @typedef {object} PluginObjectItem
*
* @property {string} [key] - A key to identify the plugin in the Plugin Manager.
* @property {*} [plugin] - The plugin itself. Usually a class/constructor.
* @property {boolean} [start] - Whether the plugin should be started automatically.
* @property {string} [systemKey] - For a scene plugin, add the plugin to the scene's systems object under this key (`this.sys.KEY`, from the scene).
* @property {string} [sceneKey] - For a scene plugin, add the plugin to the scene object under this key (`this.KEY`, from the scene).
* @property {string} [mapping] - If this plugin is to be injected into the Scene Systems, this is the property key map used.
* @property {*} [data] - Arbitrary data passed to the plugin's init() method.
*
* @example
* // Global plugin
* { key: 'BankPlugin', plugin: BankPluginV3, start: true, data: { gold: 5000 } }
* @example
* // Scene plugin
* { key: 'WireFramePlugin', plugin: WireFramePlugin, systemKey: 'wireFramePlugin', sceneKey: 'wireframe' }
*/
/**
* @typedef {object} PluginObject
*
* @property {?PluginObjectItem[]} [global] - Global plugins to install.
* @property {?PluginObjectItem[]} [scene] - Scene plugins to install.
* @property {string[]} [default] - The default set of scene plugins (names).
* @property {string[]} [defaultMerge] - Plugins to *add* to the default set of scene plugins.
*/
/**
* @typedef {object} GameConfig
*
* @property {(integer|string)} [width=1024] - [description]
* @property {(integer|string)} [height=768] - [description]
* @property {number} [zoom=1] - [description]
* @property {number} [resolution=1] - [description]
* @property {number} [type=CONST.AUTO] - [description]
* @property {*} [parent=null] - [description]
* @property {(integer|string)} [width=1024] - The width of the game, in game pixels.
* @property {(integer|string)} [height=768] - The height of the game, in game pixels.
* @property {number} [zoom=1] - Simple scale applied to the game canvas. 2 is double size, 0.5 is half size, etc.
* @property {number} [resolution=1] - The size of each game pixel, in canvas pixels. Values larger than 1 are "high" resolution.
* @property {number} [type=CONST.AUTO] - Which renderer to use. Phaser.AUTO, Phaser.CANVAS, Phaser.HEADLESS, or Phaser.WEBGL. AUTO picks WEBGL if available, otherwise CANVAS.
* @property {(HTMLElement|string)} [parent=null] - The DOM element that will contain the game canvas, or its `id`. If null (the default) or if the named element doesn't exist, the game canvas is inserted directly into the document body.
* @property {HTMLCanvasElement} [canvas=null] - Provide your own Canvas element for Phaser to use instead of creating one.
* @property {string} [canvasStyle=null] - [description]
* @property {string} [canvasStyle=null] - CSS styles to apply to the game canvas instead of Phaser's default styles.
* @property {CanvasRenderingContext2D} [context] - Provide your own Canvas Context for Phaser to use, instead of creating one.
* @property {object} [scene=null] - [description]
* @property {string[]} [seed] - [description]
* @property {string} [title=''] - [description]
* @property {string} [url='http://phaser.io'] - [description]
* @property {string} [version=''] - [description]
* @property {boolean} [autoFocus=true] - Automatically call window.focus() when the game boots.
* @property {(boolean|object)} [input] - [description]
* @property {boolean} [input.keyboard=true] - [description]
* @property {*} [input.keyboard.target=window] - [description]
* @property {(boolean|object)} [input.mouse=true] - [description]
* @property {*} [input.mouse.target=null] - [description]
* @property {boolean} [input.touch=true] - [description]
* @property {integer} [input.activePointers=1] - [description]
* @property {*} [input.touch.target=null] - [description]
* @property {boolean} [input.touch.capture=true] - [description]
* @property {(boolean|object)} [input.gamepad=false] - [description]
* @property {boolean} [disableContextMenu=false] - [description]
* @property {(boolean|object)} [banner=false] - [description]
* @property {boolean} [banner.hidePhaser=false] - [description]
* @property {string} [banner.text='#ffffff'] - [description]
* @property {string[]} [banner.background] - [description]
* @property {FPSConfig} [fps] - [description]
* @property {boolean} [render.antialias=true] - [description]
* @property {boolean} [render.pixelArt=false] - [description]
* @property {boolean} [render.autoResize=false] - [description]
* @property {boolean} [render.roundPixels=false] - [description]
* @property {boolean} [render.transparent=false] - [description]
* @property {boolean} [render.clearBeforeRender=true] - [description]
* @property {boolean} [render.premultipliedAlpha=true] - [description]
* @property {boolean} [render.preserveDrawingBuffer=false] - [description]
* @property {boolean} [render.failIfMajorPerformanceCaveat=false] - [description]
* @property {string} [render.powerPreference='default'] - "high-performance", "low-power" or "default"
* @property {(string|number)} [backgroundColor=0x000000] - [description]
* @property {object} [callbacks] - [description]
* @property {BootCallback} [callbacks.preBoot=NOOP] - [description]
* @property {BootCallback} [callbacks.postBoot=NOOP] - [description]
* @property {LoaderConfig} [loader] - [description]
* @property {object} [images] - [description]
* @property {string} [images.default] - [description]
* @property {string} [images.missing] - [description]
* @property {object} [physics] - [description]
* @property {object} [scene=null] - A scene or scenes to add to the game. If several are given, the first is started; the remainder are started only if they have { active: true }.
* @property {string[]} [seed] - Seed for the random number generator.
* @property {string} [title=''] - The title of the game. Shown in the browser console.
* @property {string} [url='http://phaser.io'] - The URL of the game. Shown in the browser console.
* @property {string} [version=''] - The version of the game. Shown in the browser console.
* @property {boolean} [autoFocus=true] - Automatically call window.focus() when the game boots. Usually necessary to capture input events if the game is in a separate frame.
* @property {(boolean|InputConfig)} [input] - Input configuration, or `false` to disable all game input.
* @property {boolean} [disableContextMenu=false] - Disable the browser's default 'contextmenu' event (usually triggered by a right-button mouse click).
* @property {(boolean|BannerConfig)} [banner=false] - Configuration for the banner printed in the browser console when the game starts.
* @property {DOMContainerConfig} [dom] - The DOM Container configuration object.
* @property {FPSConfig} [fps] - Game loop configuration.
* @property {RenderConfig} [render] - Game renderer configuration.
* @property {(string|number)} [backgroundColor=0x000000] - The background color of the game canvas. The default is black.
* @property {CallbacksConfig} [callbacks] - Optional callbacks to run before or after game boot.
* @property {LoaderConfig} [loader] - Loader configuration.
* @property {ImagesConfig} [images] - Images configuration.
* @property {object} [physics] - Physics configuration.
* @property {PluginObject|PluginObjectItem[]} [plugins] - Plugins to install.
*/
/**
* @classdesc
* [description]
* The active game configuration settings, parsed from a {@link GameConfig} object.
*
* @class Config
* @memberOf Phaser.Boot
* @memberof Phaser.Boot
* @constructor
* @since 3.0.0
*
* @param {GameConfig} [GameConfig] - The configuration object for your Phaser Game instance.
*
* @see Phaser.Game#config
*/
var Config = new Class({
@ -135,35 +262,84 @@ var Config = new Class({
var defaultBannerTextColor = '#ffffff';
/**
* @const {(integer|string)} Phaser.Boot.Config#width - [description]
* @const {(integer|string)} Phaser.Boot.Config#width - The width of the underlying canvas, in pixels.
*/
this.width = GetValue(config, 'width', 1024);
/**
* @const {(integer|string)} Phaser.Boot.Config#height - [description]
* @const {(integer|string)} Phaser.Boot.Config#height - The height of the underlying canvas, in pixels.
*/
this.height = GetValue(config, 'height', 768);
/**
* @const {number} Phaser.Boot.Config#zoom - [description]
* @const {number} Phaser.Boot.Config#zoom - The zoom factor, as used by the Scale Manager.
*/
this.zoom = GetValue(config, 'zoom', 1);
/**
* @const {number} Phaser.Boot.Config#resolution - [description]
* @const {number} Phaser.Boot.Config#resolution - The canvas device pixel resolution.
*/
this.resolution = GetValue(config, 'resolution', 1);
/**
* @const {number} Phaser.Boot.Config#renderType - [description]
*/
this.renderType = GetValue(config, 'type', CONST.AUTO);
/**
* @const {?*} Phaser.Boot.Config#parent - [description]
* @const {?*} Phaser.Boot.Config#parent - A parent DOM element into which the canvas created by the renderer will be injected.
*/
this.parent = GetValue(config, 'parent', null);
/**
* @const {integer} Phaser.Boot.Config#scaleMode - The scale mode as used by the Scale Manager. The default is zero, which is no scaling.
*/
this.scaleMode = GetValue(config, 'scaleMode', 0);
/**
* @const {boolean} Phaser.Boot.Config#expandParent - Is the Scale Manager allowed to adjust the size of the parent container?
*/
this.expandParent = GetValue(config, 'expandParent', false);
/**
* @const {integer} Phaser.Boot.Config#minWidth - The minimum width, in pixels, the canvas will scale down to. A value of zero means no minimum.
*/
this.minWidth = GetValue(config, 'minWidth', 0);
/**
* @const {integer} Phaser.Boot.Config#maxWidth - The maximum width, in pixels, the canvas will scale up to. A value of zero means no maximum.
*/
this.maxWidth = GetValue(config, 'maxWidth', 0);
/**
* @const {integer} Phaser.Boot.Config#minHeight - The minimum height, in pixels, the canvas will scale down to. A value of zero means no minimum.
*/
this.minHeight = GetValue(config, 'minHeight', 0);
/**
* @const {integer} Phaser.Boot.Config#maxHeight - The maximum height, in pixels, the canvas will scale up to. A value of zero means no maximum.
*/
this.maxHeight = GetValue(config, 'maxHeight', 0);
// Scale Manager - Anything set in here over-rides anything set above
var scaleConfig = GetValue(config, 'scale', null);
if (scaleConfig)
{
this.width = GetValue(scaleConfig, 'width', this.width);
this.height = GetValue(scaleConfig, 'height', this.height);
this.zoom = GetValue(scaleConfig, 'zoom', this.zoom);
this.resolution = GetValue(scaleConfig, 'resolution', this.resolution);
this.parent = GetValue(scaleConfig, 'parent', this.parent);
this.scaleMode = GetValue(scaleConfig, 'mode', this.scaleMode);
this.expandParent = GetValue(scaleConfig, 'mode', this.expandParent);
this.minWidth = GetValue(scaleConfig, 'min.width', this.minWidth);
this.maxWidth = GetValue(scaleConfig, 'max.width', this.maxWidth);
this.minHeight = GetValue(scaleConfig, 'min.height', this.minHeight);
this.maxHeight = GetValue(scaleConfig, 'max.height', this.maxHeight);
}
/**
* @const {number} Phaser.Boot.Config#renderType - Force Phaser to use a specific renderer. Can be `CONST.CANVAS`, `CONST.WEBGL`, `CONST.HEADLESS` or `CONST.AUTO` (default)
*/
this.renderType = GetValue(config, 'type', CONST.AUTO);
/**
* @const {?HTMLCanvasElement} Phaser.Boot.Config#canvas - Force Phaser to use your own Canvas element instead of creating one.
*/
@ -175,128 +351,155 @@ var Config = new Class({
this.context = GetValue(config, 'context', null);
/**
* @const {?string} Phaser.Boot.Config#canvasStyle - [description]
* @const {?string} Phaser.Boot.Config#canvasStyle - Optional CSS attributes to be set on the canvas object created by the renderer.
*/
this.canvasStyle = GetValue(config, 'canvasStyle', null);
/**
* @const {?object} Phaser.Boot.Config#sceneConfig - [description]
* @const {boolean} Phaser.Boot.Config#customEnvironment - Is Phaser running under a custom (non-native web) environment? If so, set this to `true` to skip internal Feature detection. If `true` the `renderType` cannot be left as `AUTO`.
*/
this.customEnvironment = GetValue(config, 'customEnvironment', false);
/**
* @const {?object} Phaser.Boot.Config#sceneConfig - The default Scene configuration object.
*/
this.sceneConfig = GetValue(config, 'scene', null);
/**
* @const {string[]} Phaser.Boot.Config#seed - [description]
* @const {string[]} Phaser.Boot.Config#seed - A seed which the Random Data Generator will use. If not given, a dynamic seed based on the time is used.
*/
this.seed = GetValue(config, 'seed', [ (Date.now() * Math.random()).toString() ]);
MATH.RND.init(this.seed);
PhaserMath.RND = new PhaserMath.RandomDataGenerator(this.seed);
/**
* @const {string} Phaser.Boot.Config#gameTitle - [description]
* @const {string} Phaser.Boot.Config#gameTitle - The title of the game.
*/
this.gameTitle = GetValue(config, 'title', '');
/**
* @const {string} Phaser.Boot.Config#gameURL - [description]
* @const {string} Phaser.Boot.Config#gameURL - The URL of the game.
*/
this.gameURL = GetValue(config, 'url', 'https://phaser.io');
/**
* @const {string} Phaser.Boot.Config#gameVersion - [description]
* @const {string} Phaser.Boot.Config#gameVersion - The version of the game.
*/
this.gameVersion = GetValue(config, 'version', '');
/**
* @const {boolean} Phaser.Boot.Config#autoFocus - [description]
* @const {boolean} Phaser.Boot.Config#autoFocus - If `true` the window will automatically be given focus immediately and on any future mousedown event.
*/
this.autoFocus = GetValue(config, 'autoFocus', true);
// DOM Element Container
/**
* @const {?boolean} Phaser.Boot.Config#domCreateContainer - EXPERIMENTAL: Do not currently use.
*/
this.domCreateContainer = GetValue(config, 'dom.createContainer', false);
/**
* @const {?boolean} Phaser.Boot.Config#domBehindCanvas - EXPERIMENTAL: Do not currently use.
*/
this.domBehindCanvas = GetValue(config, 'dom.behindCanvas', false);
// Input
/**
* @const {boolean} Phaser.Boot.Config#inputKeyboard - [description]
* @const {boolean} Phaser.Boot.Config#inputKeyboard - Enable the Keyboard Plugin. This can be disabled in games that don't need keyboard input.
*/
this.inputKeyboard = GetValue(config, 'input.keyboard', true);
/**
* @const {*} Phaser.Boot.Config#inputKeyboardEventTarget - [description]
* @const {*} Phaser.Boot.Config#inputKeyboardEventTarget - The DOM Target to listen for keyboard events on. Defaults to `window` if not specified.
*/
this.inputKeyboardEventTarget = GetValue(config, 'input.keyboard.target', window);
/**
* @const {(boolean|object)} Phaser.Boot.Config#inputMouse - [description]
* @const {?integer[]} Phaser.Boot.Config#inputKeyboardCapture - `preventDefault` will be called on every non-modified key which has a key code in this array. By default, it is empty.
*/
this.inputKeyboardCapture = GetValue(config, 'input.keyboard.capture', []);
/**
* @const {(boolean|object)} Phaser.Boot.Config#inputMouse - Enable the Mouse Plugin. This can be disabled in games that don't need mouse input.
*/
this.inputMouse = GetValue(config, 'input.mouse', true);
/**
* @const {?*} Phaser.Boot.Config#inputMouseEventTarget - [description]
* @const {?*} Phaser.Boot.Config#inputMouseEventTarget - The DOM Target to listen for mouse events on. Defaults to the game canvas if not specified.
*/
this.inputMouseEventTarget = GetValue(config, 'input.mouse.target', null);
/**
* @const {boolean} Phaser.Boot.Config#inputMouseCapture - [description]
* @const {boolean} Phaser.Boot.Config#inputMouseCapture - Should mouse events be captured? I.e. have prevent default called on them.
*/
this.inputMouseCapture = GetValue(config, 'input.mouse.capture', true);
/**
* @const {boolean} Phaser.Boot.Config#inputTouch - [description]
* @const {boolean} Phaser.Boot.Config#inputTouch - Enable the Touch Plugin. This can be disabled in games that don't need touch input.
*/
this.inputTouch = GetValue(config, 'input.touch', true);
this.inputTouch = GetValue(config, 'input.touch', Device.input.touch);
/**
* @const {?*} Phaser.Boot.Config#inputTouchEventTarget - [description]
* @const {?*} Phaser.Boot.Config#inputTouchEventTarget - The DOM Target to listen for touch events on. Defaults to the game canvas if not specified.
*/
this.inputTouchEventTarget = GetValue(config, 'input.touch.target', null);
/**
* @const {boolean} Phaser.Boot.Config#inputTouchCapture - [description]
* @const {boolean} Phaser.Boot.Config#inputTouchCapture - Should touch events be captured? I.e. have prevent default called on them.
*/
this.inputTouchCapture = GetValue(config, 'input.touch.capture', true);
/**
* @const {integer} Phaser.Boot.Config#inputActivePointers - [description]
* @const {integer} Phaser.Boot.Config#inputActivePointers - The number of Pointer objects created by default. In a mouse-only, or non-multi touch game, you can leave this as 1.
*/
this.inputActivePointers = GetValue(config, 'input.activePointers', 1);
/**
* @const {boolean} Phaser.Boot.Config#inputGamepad - [description]
* @const {integer} Phaser.Boot.Config#inputSmoothFactor - The smoothing factor to apply during Pointer movement. See {@link Phaser.Input.Pointer#smoothFactor}.
*/
this.inputSmoothFactor = GetValue(config, 'input.smoothFactor', 0);
/**
* @const {boolean} Phaser.Boot.Config#inputGamepad - Enable the Gamepad Plugin. This can be disabled in games that don't need gamepad input.
*/
this.inputGamepad = GetValue(config, 'input.gamepad', false);
/**
* @const {*} Phaser.Boot.Config#inputGamepadEventTarget - [description]
* @const {*} Phaser.Boot.Config#inputGamepadEventTarget - The DOM Target to listen for gamepad events on. Defaults to `window` if not specified.
*/
this.inputGamepadEventTarget = GetValue(config, 'input.gamepad.target', window);
/**
* @const {boolean} Phaser.Boot.Config#disableContextMenu - [description]
* @const {boolean} Phaser.Boot.Config#disableContextMenu - Set to `true` to disable the right-click context menu.
*/
this.disableContextMenu = GetValue(config, 'disableContextMenu', false);
/**
* @const {any} Phaser.Boot.Config#audio - [description]
* @const {AudioConfig} Phaser.Boot.Config#audio - The Audio Configuration object.
*/
this.audio = GetValue(config, 'audio');
// If you do: { banner: false } it won't display any banner at all
/**
* @const {boolean} Phaser.Boot.Config#hideBanner - [description]
* @const {boolean} Phaser.Boot.Config#hideBanner - Don't write the banner line to the console.log.
*/
this.hideBanner = (GetValue(config, 'banner', null) === false);
/**
* @const {boolean} Phaser.Boot.Config#hidePhaser - [description]
* @const {boolean} Phaser.Boot.Config#hidePhaser - Omit Phaser's name and version from the banner.
*/
this.hidePhaser = GetValue(config, 'banner.hidePhaser', false);
/**
* @const {string} Phaser.Boot.Config#bannerTextColor - [description]
* @const {string} Phaser.Boot.Config#bannerTextColor - The color of the banner text.
*/
this.bannerTextColor = GetValue(config, 'banner.text', defaultBannerTextColor);
/**
* @const {string[]} Phaser.Boot.Config#bannerBackgroundColor - [description]
* @const {string[]} Phaser.Boot.Config#bannerBackgroundColor - The background colors of the banner.
*/
this.bannerBackgroundColor = GetValue(config, 'banner.background', defaultBannerColor);
@ -305,16 +508,8 @@ var Config = new Class({
this.hideBanner = true;
}
// Frame Rate config
// fps: {
// min: 10,
// target: 60,
// forceSetTimeOut: false,
// deltaHistory: 10
// }
/**
* @const {?FPSConfig} Phaser.Boot.Config#fps - [description]
* @const {?FPSConfig} Phaser.Boot.Config#fps - The Frame Rate Configuration object, as parsed by the Timestep class.
*/
this.fps = GetValue(config, 'fps', null);
@ -324,22 +519,22 @@ var Config = new Class({
var renderConfig = GetValue(config, 'render', config);
/**
* @const {boolean} Phaser.Boot.Config#autoResize - [description]
* @const {boolean} Phaser.Boot.Config#autoResize - Automatically resize the Game Canvas if you resize the renderer.
*/
this.autoResize = GetValue(renderConfig, 'autoResize', false);
this.autoResize = GetValue(renderConfig, 'autoResize', true);
/**
* @const {boolean} Phaser.Boot.Config#antialias - [description]
* @const {boolean} Phaser.Boot.Config#antialias - When set to `true`, WebGL uses linear interpolation to draw scaled or rotated textures, giving a smooth appearance. When set to `false`, WebGL uses nearest-neighbor interpolation, giving a crisper appearance. `false` also disables antialiasing of the game canvas itself, if the browser supports it, when the game canvas is scaled.
*/
this.antialias = GetValue(renderConfig, 'antialias', true);
/**
* @const {boolean} Phaser.Boot.Config#roundPixels - [description]
* @const {boolean} Phaser.Boot.Config#roundPixels - Draw texture-based Game Objects at only whole-integer positions. Game Objects without textures, like Graphics, ignore this property.
*/
this.roundPixels = GetValue(renderConfig, 'roundPixels', false);
/**
* @const {boolean} Phaser.Boot.Config#pixelArt - [description]
* @const {boolean} Phaser.Boot.Config#pixelArt - Prevent pixel art from becoming blurred when scaled. It will remain crisp (tells the WebGL renderer to automatically create textures using a linear filter mode).
*/
this.pixelArt = GetValue(renderConfig, 'pixelArt', false);
@ -350,39 +545,44 @@ var Config = new Class({
}
/**
* @const {boolean} Phaser.Boot.Config#transparent - [description]
* @const {boolean} Phaser.Boot.Config#transparent - Whether the game canvas will have a transparent background.
*/
this.transparent = GetValue(renderConfig, 'transparent', false);
/**
* @const {boolean} Phaser.Boot.Config#zoclearBeforeRenderom - [description]
* @const {boolean} Phaser.Boot.Config#clearBeforeRender - Whether the game canvas will be cleared between each rendering frame. You can disable this if you have a full-screen background image or game object.
*/
this.clearBeforeRender = GetValue(renderConfig, 'clearBeforeRender', true);
/**
* @const {boolean} Phaser.Boot.Config#premultipliedAlpha - [description]
* @const {boolean} Phaser.Boot.Config#premultipliedAlpha - In WebGL mode, sets the drawing buffer to contain colors with pre-multiplied alpha.
*/
this.premultipliedAlpha = GetValue(renderConfig, 'premultipliedAlpha', true);
/**
* @const {boolean} Phaser.Boot.Config#preserveDrawingBuffer - [description]
*/
this.preserveDrawingBuffer = GetValue(renderConfig, 'preserveDrawingBuffer', false);
/**
* @const {boolean} Phaser.Boot.Config#failIfMajorPerformanceCaveat - [description]
* @const {boolean} Phaser.Boot.Config#failIfMajorPerformanceCaveat - Let the browser abort creating a WebGL context if it judges performance would be unacceptable.
*/
this.failIfMajorPerformanceCaveat = GetValue(renderConfig, 'failIfMajorPerformanceCaveat', false);
/**
* @const {string} Phaser.Boot.Config#powerPreference - [description]
* @const {string} Phaser.Boot.Config#powerPreference - "high-performance", "low-power" or "default". A hint to the browser on how much device power the game might use.
*/
this.powerPreference = GetValue(renderConfig, 'powerPreference', 'default');
/**
* @const {integer} Phaser.Boot.Config#batchSize - The default WebGL Batch size.
*/
this.batchSize = GetValue(renderConfig, 'batchSize', 2000);
/**
* @const {integer} Phaser.Boot.Config#maxLights - The maximum number of lights allowed to be visible within range of a single Camera in the LightManager.
*/
this.maxLights = GetValue(renderConfig, 'maxLights', 10);
var bgc = GetValue(config, 'backgroundColor', 0);
/**
* @const {Phaser.Display.Color} Phaser.Boot.Config#backgroundColor - [description]
* @const {Phaser.Display.Color} Phaser.Boot.Config#backgroundColor - The background color of the game canvas. The default is black. This value is ignored if `transparent` is set to `true`.
*/
this.backgroundColor = ValueToColor(bgc);
@ -391,110 +591,96 @@ var Config = new Class({
this.backgroundColor.alpha = 0;
}
// Callbacks
/**
* @const {BootCallback} Phaser.Boot.Config#preBoot - [description]
* @const {BootCallback} Phaser.Boot.Config#preBoot - Called before Phaser boots. Useful for initializing anything not related to Phaser that Phaser may require while booting.
*/
this.preBoot = GetValue(config, 'callbacks.preBoot', NOOP);
/**
* @const {BootCallback} Phaser.Boot.Config#postBoot - [description]
* @const {BootCallback} Phaser.Boot.Config#postBoot - A function to run at the end of the boot sequence. At this point, all the game systems have started and plugins have been loaded.
*/
this.postBoot = GetValue(config, 'callbacks.postBoot', NOOP);
// Physics
// physics: {
// system: 'impact',
// setBounds: true,
// gravity: 0,
// cellSize: 64
// }
/**
* @const {object} Phaser.Boot.Config#physics - [description]
* @const {PhysicsConfig} Phaser.Boot.Config#physics - The Physics Configuration object.
*/
this.physics = GetValue(config, 'physics', {});
/**
* @const {boolean} Phaser.Boot.Config#defaultPhysicsSystem - [description]
* @const {(boolean|string)} Phaser.Boot.Config#defaultPhysicsSystem - The default physics system. It will be started for each scene. Either 'arcade', 'impact' or 'matter'.
*/
this.defaultPhysicsSystem = GetValue(this.physics, 'default', false);
// Loader Defaults
/**
* @const {string} Phaser.Boot.Config#loaderBaseURL - [description]
* @const {string} Phaser.Boot.Config#loaderBaseURL - A URL used to resolve paths given to the loader. Example: 'http://labs.phaser.io/assets/'.
*/
this.loaderBaseURL = GetValue(config, 'loader.baseURL', '');
/**
* @const {string} Phaser.Boot.Config#loaderPath - [description]
* @const {string} Phaser.Boot.Config#loaderPath - A URL path used to resolve relative paths given to the loader. Example: 'images/sprites/'.
*/
this.loaderPath = GetValue(config, 'loader.path', '');
/**
* @const {integer} Phaser.Boot.Config#loaderMaxParallelDownloads - [description]
* @const {integer} Phaser.Boot.Config#loaderMaxParallelDownloads - Maximum parallel downloads allowed for resources (Default to 32).
*/
this.loaderMaxParallelDownloads = GetValue(config, 'loader.maxParallelDownloads', 32);
/**
* @const {(string|undefined)} Phaser.Boot.Config#loaderCrossOrigin - [description]
* @const {(string|undefined)} Phaser.Boot.Config#loaderCrossOrigin - 'anonymous', 'use-credentials', or `undefined`. If you're not making cross-origin requests, leave this as `undefined`. See {@link https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes}.
*/
this.loaderCrossOrigin = GetValue(config, 'loader.crossOrigin', undefined);
/**
* @const {string} Phaser.Boot.Config#loaderResponseType - [description]
* @const {string} Phaser.Boot.Config#loaderResponseType - The response type of the XHR request, e.g. `blob`, `text`, etc.
*/
this.loaderResponseType = GetValue(config, 'loader.responseType', '');
/**
* @const {boolean} Phaser.Boot.Config#loaderAsync - [description]
* @const {boolean} Phaser.Boot.Config#loaderAsync - Should the XHR request use async or not?
*/
this.loaderAsync = GetValue(config, 'loader.async', true);
/**
* @const {string} Phaser.Boot.Config#loaderUser - [description]
* @const {string} Phaser.Boot.Config#loaderUser - Optional username for all XHR requests.
*/
this.loaderUser = GetValue(config, 'loader.user', '');
/**
* @const {string} Phaser.Boot.Config#loaderPassword - [description]
* @const {string} Phaser.Boot.Config#loaderPassword - Optional password for all XHR requests.
*/
this.loaderPassword = GetValue(config, 'loader.password', '');
/**
* @const {integer} Phaser.Boot.Config#loaderTimeout - [description]
* @const {integer} Phaser.Boot.Config#loaderTimeout - Optional XHR timeout value, in ms.
*/
this.loaderTimeout = GetValue(config, 'loader.timeout', 0);
// Plugins
/*
* Allows `plugins` property to either be an array, in which case it just replaces
* the default plugins like previously, or a config object.
*
* plugins: {
* global: [
* { key: 'TestPlugin', plugin: TestPlugin, start: true },
* { key: 'TestPlugin', plugin: TestPlugin, start: true, data: { msg: 'The plugin is alive' } },
* ],
* scene: [
* { key: 'WireFramePlugin', plugin: WireFramePlugin, systemKey: 'wireFramePlugin', sceneKey: 'wireframe' }
* ],
* default: [], OR
* defaultMerge: {
* defaultMerge: [
* 'ModPlayer'
* }
* ]
* }
*/
/**
* @const {any} Phaser.Boot.Config#installGlobalPlugins - [description]
* @const {any} Phaser.Boot.Config#installGlobalPlugins - An array of global plugins to be installed.
*/
this.installGlobalPlugins = [];
/**
* @const {any} Phaser.Boot.Config#installScenePlugins - [description]
* @const {any} Phaser.Boot.Config#installScenePlugins - An array of Scene level plugins to be installed.
*/
this.installScenePlugins = [];
@ -533,14 +719,26 @@ var Config = new Class({
var pngPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAg';
/**
* @const {string} Phaser.Boot.Config#defaultImage - [description]
* @const {string} Phaser.Boot.Config#defaultImage - A base64 encoded PNG that will be used as the default blank texture.
*/
this.defaultImage = GetValue(config, 'images.default', pngPrefix + 'AQMAAABJtOi3AAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAABVJREFUeF7NwIEAAAAAgKD9qdeocAMAoAABm3DkcAAAAABJRU5ErkJggg==');
/**
* @const {string} Phaser.Boot.Config#missingImage - [description]
* @const {string} Phaser.Boot.Config#missingImage - A base64 encoded PNG that will be used as the default texture when a texture is assigned that is missing or not loaded.
*/
this.missingImage = GetValue(config, 'images.missing', pngPrefix + 'CAIAAAD8GO2jAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJ9JREFUeNq01ssOwyAMRFG46v//Mt1ESmgh+DFmE2GPOBARKb2NVjo+17PXLD8a1+pl5+A+wSgFygymWYHBb0FtsKhJDdZlncG2IzJ4ayoMDv20wTmSMzClEgbWYNTAkQ0Z+OJ+A/eWnAaR9+oxCF4Os0H8htsMUp+pwcgBBiMNnAwF8GqIgL2hAzaGFFgZauDPKABmowZ4GL369/0rwACp2yA/ttmvsQAAAABJRU5ErkJggg==');
if (window)
{
if (window.FORCE_WEBGL)
{
this.renderType = CONST.WEBGL;
}
else if (window.FORCE_CANVAS)
{
this.renderType = CONST.CANVAS;
}
}
}
});

View file

@ -0,0 +1,36 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var AddToDOM = require('../dom/AddToDOM');
var CreateDOMContainer = function (game)
{
var config = game.config;
if (!config.parent || !config.domCreateContainer)
{
return;
}
// DOM Element Container
var div = document.createElement('div');
div.style = [
'display: block;',
'width: ' + game.canvas.width + 'px;',
'height: ' + game.canvas.height + 'px;',
'padding: 0; margin: 0;',
'position: absolute;',
'overflow: hidden;',
'pointer-events: none;'
].join(' ');
game.domContainer = div;
AddToDOM(div, config.parent);
};
module.exports = CreateDOMContainer;

View file

@ -23,10 +23,13 @@ var CreateRenderer = function (game)
{
var config = game.config;
// Game either requested Canvas,
// or requested AUTO or WEBGL but the browser doesn't support it, so fall back to Canvas
if ((config.customEnvironment || config.canvas) && config.renderType === CONST.AUTO)
{
throw new Error('Must set explicit renderType in custom environment');
}
if (config.renderType !== CONST.HEADLESS)
// Not a custom environment, didn't provide their own canvas and not headless, so determine the renderer:
if (!config.customEnvironment && !config.canvas && config.renderType !== CONST.HEADLESS)
{
if (config.renderType === CONST.CANVAS || (config.renderType !== CONST.CANVAS && !Features.webGL))
{
@ -57,10 +60,13 @@ var CreateRenderer = function (game)
if (config.canvas)
{
game.canvas = config.canvas;
game.canvas.width = game.scale.canvasWidth;
game.canvas.height = game.scale.canvasHeight;
}
else
{
game.canvas = CanvasPool.create(game, config.width, config.height, config.renderType);
game.canvas = CanvasPool.create(game, game.scale.canvasWidth, game.scale.canvasHeight, config.renderType);
}
// Does the game config provide some canvas css styles to use?
@ -75,13 +81,6 @@ var CreateRenderer = function (game)
CanvasInterpolation.setCrisp(game.canvas);
}
// Zoomed?
if (config.zoom !== 1)
{
game.canvas.style.width = (config.width * config.zoom).toString() + 'px';
game.canvas.style.height = (config.height * config.zoom).toString() + 'px';
}
if (config.renderType === CONST.HEADLESS)
{
// Nothing more to do here
@ -100,9 +99,6 @@ var CreateRenderer = function (game)
if (config.renderType === CONST.WEBGL)
{
game.renderer = new WebGLRenderer(game);
// The WebGL Renderer sets this value during its init, not on construction
game.context = null;
}
else
{
@ -119,9 +115,6 @@ var CreateRenderer = function (game)
config.renderType = CONST.WEBGL;
game.renderer = new WebGLRenderer(game);
// The WebGL Renderer sets this value during its init, not on construction
game.context = null;
}
if (!typeof WEBGL_RENDERER && typeof CANVAS_RENDERER)

View file

@ -101,9 +101,11 @@ var DebugHeader = function (game)
}
}
var fb = (typeof PLUGIN_FBINSTANT) ? '-FB' : '';
if (!config.hidePhaser)
{
c = c.concat('Phaser v' + CONST.VERSION + ' (' + renderType + ' | ' + audioType + ')');
c = c.concat('Phaser v' + CONST.VERSION + fb + ' (' + renderType + ' | ' + audioType + ')');
}
c = c.concat(' %c ' + config.gameURL);

View file

@ -17,13 +17,25 @@ var Device = require('../device');
var DOMContentLoaded = require('../dom/DOMContentLoaded');
var EventEmitter = require('eventemitter3');
var InputManager = require('../input/InputManager');
var PluginCache = require('../plugins/PluginCache');
var PluginManager = require('../plugins/PluginManager');
var ScaleManager = require('../dom/ScaleManager');
var SceneManager = require('../scene/SceneManager');
var SoundManagerCreator = require('../sound/SoundManagerCreator');
var TextureManager = require('../textures/TextureManager');
var TimeStep = require('./TimeStep');
var VisibilityHandler = require('./VisibilityHandler');
if (typeof EXPERIMENTAL)
{
var CreateDOMContainer = require('./CreateDOMContainer');
}
if (typeof PLUGIN_FBINSTANT)
{
var FacebookInstantGamesPlugin = require('../../plugins/fbinstant/src/FacebookInstantGamesPlugin');
}
/**
* @classdesc
* The Phaser.Game instance is the main controller for the entire Phaser game. It is responsible
@ -35,7 +47,7 @@ var VisibilityHandler = require('./VisibilityHandler');
* made available to you via the Phaser.Scene Systems class instead.
*
* @class Game
* @memberOf Phaser
* @memberof Phaser
* @constructor
* @since 3.0.0
*
@ -54,7 +66,7 @@ var Game = new Class({
*
* @name Phaser.Game#config
* @type {Phaser.Boot.Config}
* @readOnly
* @readonly
* @since 3.0.0
*/
this.config = new Config(config);
@ -68,6 +80,23 @@ var Game = new Class({
*/
this.renderer = null;
if (typeof EXPERIMENTAL)
{
/**
* A reference to an HTML Div Element used as a DOM Element Container.
*
* Only set if `createDOMContainer` is `true` in the game config (by default it is `false`) and
* if you provide a parent element to insert the Phaser Game inside.
*
* See the DOM Element Game Object for more details.
*
* @name Phaser.Game#domContainer
* @type {HTMLDivElement}
* @since 3.12.0
*/
this.domContainer = null;
}
/**
* A reference to the HTML Canvas Element that Phaser uses to render the game.
* This is created automatically by Phaser unless you provide a `canvas` property
@ -97,7 +126,7 @@ var Game = new Class({
*
* @name Phaser.Game#isBooted
* @type {boolean}
* @readOnly
* @readonly
* @since 3.0.0
*/
this.isBooted = false;
@ -107,7 +136,7 @@ var Game = new Class({
*
* @name Phaser.Game#isRunning
* @type {boolean}
* @readOnly
* @readonly
* @since 3.0.0
*/
this.isRunning = false;
@ -197,6 +226,17 @@ var Game = new Class({
*/
this.device = Device;
/**
* An instance of the Scale Manager.
*
* The Scale Manager is a global system responsible for handling game scaling events.
*
* @name Phaser.Game#scale
* @type {Phaser.Boot.ScaleManager}
* @since 3.15.0
*/
this.scale = new ScaleManager(this, this.config);
/**
* An instance of the base Sound Manager.
*
@ -232,6 +272,21 @@ var Game = new Class({
*/
this.plugins = new PluginManager(this, this.config);
if (typeof PLUGIN_FBINSTANT)
{
/**
* An instance of the Facebook Instant Games Plugin.
*
* This will only be available if the plugin has been built into Phaser,
* or you're using the special Facebook Instant Games custom build.
*
* @name Phaser.Game#facebook
* @type {Phaser.FacebookInstantGamesPlugin}
* @since 3.13.0
*/
this.facebook = new FacebookInstantGamesPlugin(this);
}
/**
* Is this Game pending destruction at the start of the next frame?
*
@ -252,28 +307,28 @@ var Game = new Class({
*/
this.removeCanvas = false;
/**
* Remove everything when the game is destroyed.
* You cannot create a new Phaser instance on the same web page after doing this.
*
* @name Phaser.Game#noReturn
* @type {boolean}
* @private
* @since 3.12.0
*/
this.noReturn = false;
/**
* Does the window the game is running in currently have focus or not?
* This is modified by the VisibilityHandler.
*
* @name Phaser.Game#hasFocus
* @type {boolean}
* @readOnly
* @readonly
* @since 3.9.0
*/
this.hasFocus = false;
/**
* Is the mouse pointer currently over the game canvas or not?
* This is modified by the VisibilityHandler.
*
* @name Phaser.Game#isOver
* @type {boolean}
* @readOnly
* @since 3.10.0
*/
this.isOver = true;
// Wait for the DOM Ready event, then call boot.
DOMContentLoaded(this.boot.bind(this));
},
@ -299,20 +354,51 @@ var Game = new Class({
*/
boot: function ()
{
if (!PluginCache.hasCore('EventEmitter'))
{
console.warn('Aborting. Core Plugins missing.');
return;
}
this.isBooted = true;
this.config.preBoot(this);
this.scale.preBoot();
CreateRenderer(this);
if (typeof EXPERIMENTAL)
{
CreateDOMContainer(this);
}
DebugHeader(this);
AddToDOM(this.canvas, this.config.parent);
this.events.emit('boot');
// The Texture Manager has to wait on a couple of non-blocking events before it's fully ready, so it will emit this event
this.events.once('ready', this.start, this);
// The Texture Manager has to wait on a couple of non-blocking events before it's fully ready.
// So it will emit this internal event when done:
this.events.once('texturesready', this.texturesReady, this);
},
/**
* Called automatically when the Texture Manager has finished setting up and preparing the
* default textures.
*
* @method Phaser.Game#texturesReady
* @private
* @fires Phaser.Game#ready
* @since 3.12.0
*/
texturesReady: function ()
{
// Start all the other systems
this.events.emit('ready');
this.start();
},
/**
@ -352,40 +438,48 @@ var Game = new Class({
/**
* Game Pre-Step event.
*
* Listen for it using the event type `prestep`.
*
* This event is dispatched before the main Step starts.
* By this point none of the Scene updates have happened.
* Hook into it from plugins or systems that need to update before the Scene Manager does.
*
* @event Phaser.Game#prestepEvent
* @param {number} time - [description]
* @param {number} delta - [description]
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
/**
* Game Step event.
*
* Listen for it using the event type `step`.
*
* This event is dispatched after Pre-Step and before the Scene Manager steps.
* Hook into it from plugins or systems that need to update before the Scene Manager does, but after core Systems.
*
* @event Phaser.Game#stepEvent
* @param {number} time - [description]
* @param {number} delta - [description]
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
/**
* Game Post-Step event.
*
* Listen for it using the event type `poststep`.
*
* This event is dispatched after the Scene Manager has updated.
* Hook into it from plugins or systems that need to do things before the render starts.
*
* @event Phaser.Game#poststepEvent
* @param {number} time - [description]
* @param {number} delta - [description]
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
/**
* Game Pre-Render event.
*
* Listen for it using the event type `prerender`.
*
* This event is dispatched immediately before any of the Scenes have started to render.
* The renderer will already have been initialized this frame, clearing itself and preparing to receive
* the Scenes for rendering, but it won't have actually drawn anything yet.
@ -397,6 +491,8 @@ var Game = new Class({
/**
* Game Post-Render event.
*
* Listen for it using the event type `postrender`.
*
* This event is dispatched right at the end of the render process.
* Every Scene will have rendered and drawn to the canvas.
*
@ -420,8 +516,8 @@ var Game = new Class({
* @fires Phaser.Game#postrenderEvent
* @since 3.0.0
*
* @param {integer} time - The current timestamp as generated by the Request Animation Frame or SetTimeout.
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
step: function (time, delta)
{
@ -484,8 +580,8 @@ var Game = new Class({
* @fires Phaser.Game#postrenderEvent
* @since 3.2.0
*
* @param {integer} time - The current timestamp as generated by the Request Animation Frame or SetTimeout.
* @param {number} delta - The delta time elapsed since the last frame.
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
headlessStep: function (time, delta)
{
@ -513,6 +609,8 @@ var Game = new Class({
/**
* Game Pause event.
*
* Listen for it using the event type `pause`.
*
* This event is dispatched when the game loop enters a paused state, usually as a result of the Visibility Handler.
*
* @event Phaser.Game#pauseEvent
@ -537,6 +635,8 @@ var Game = new Class({
/**
* Game Resume event.
*
* Listen for it using the event type `resume`.
*
* This event is dispatched when the game loop leaves a paused state and resumes running.
*
* @event Phaser.Game#resumeEvent
@ -591,6 +691,8 @@ var Game = new Class({
/**
* Game Resize event.
*
* Listen for it using the event type `resize`.
*
* @event Phaser.Game#resizeEvent
* @param {number} width - The new width of the Game.
* @param {number} height - The new height of the Game.
@ -601,6 +703,7 @@ var Game = new Class({
* Then resizes the Renderer and Input Manager scale.
*
* @method Phaser.Game#resize
* @fires Phaser.Game#resizeEvent
* @since 3.2.0
*
* @param {number} width - The new width of the game.
@ -611,6 +714,15 @@ var Game = new Class({
this.config.width = width;
this.config.height = height;
if (typeof EXPERIMENTAL)
{
if (this.domContainer)
{
this.domContainer.style.width = width + 'px';
this.domContainer.style.height = height + 'px';
}
}
this.renderer.resize(width, height);
this.input.resize();
@ -620,20 +732,64 @@ var Game = new Class({
this.events.emit('resize', width, height);
},
/**
* Returns the current game frame.
* When the game starts running, the frame is incremented every time Request Animation Frame, or Set Timeout, fires.
*
* @method Phaser.Game#getFrame
* @since 3.16.0
*
* @return {number} The current game frame.
*/
getFrame: function ()
{
return this.loop.frame;
},
/**
* Returns the current game timestamp.
* When the game starts running, the frame is incremented every time Request Animation Frame, or Set Timeout, fires.
*
* @method Phaser.Game#getTime
* @since 3.16.0
*
* @return {number} The current game timestamp.
*/
getTime: function ()
{
return this.loop.frame.time;
},
/**
* Game Destroy event.
*
* Listen for it using the event type `destroy`.
*
* @event Phaser.Game#destroyEvent
*/
/**
* Flags this Game instance as needing to be destroyed on the next frame.
* It will wait until the current frame has completed and then call `runDestroy` internally.
*
* If you **do not** need to run Phaser again on the same web page you can set the `noReturn` argument to `true` and it will free-up
* memory being held by the core Phaser plugins. If you do need to create another game instance on the same page, leave this as `false`.
*
* @method Phaser.Game#destroy
* @fires Phaser.Game#destroyEvent
* @since 3.0.0
*
* @param {boolean} removeCanvas - Set to `true` if you would like the parent canvas element removed from the DOM, or `false` to leave it in place.
* @param {boolean} [noReturn=false] - If `true` all the core Phaser plugins are destroyed. You cannot create another instance of Phaser on the same web page if you do this.
*/
destroy: function (removeCanvas)
destroy: function (removeCanvas, noReturn)
{
if (noReturn === undefined) { noReturn = false; }
this.pendingDestroy = true;
this.removeCanvas = removeCanvas;
this.noReturn = noReturn;
},
/**
@ -666,6 +822,14 @@ var Game = new Class({
}
}
if (typeof EXPERIMENTAL)
{
if (this.domContainer)
{
this.domContainer.parentNode.removeChild(this.domContainer);
}
}
this.loop.destroy();
this.pendingDestroy = false;
@ -673,4 +837,8 @@ var Game = new Class({
});
/**
* "Computers are good at following instructions, but not at reading your mind." - Donald Knuth
*/
module.exports = Game;

View file

@ -33,7 +33,7 @@ var RequestAnimationFrame = require('../dom/RequestAnimationFrame');
* [description]
*
* @class TimeStep
* @memberOf Phaser.Boot
* @memberof Phaser.Boot
* @constructor
* @since 3.0.0
*
@ -51,7 +51,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#game
* @type {Phaser.Game}
* @readOnly
* @readonly
* @since 3.0.0
*/
this.game = game;
@ -61,7 +61,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#raf
* @type {Phaser.DOM.RequestAnimationFrame}
* @readOnly
* @readonly
* @since 3.0.0
*/
this.raf = new RequestAnimationFrame();
@ -71,7 +71,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#started
* @type {boolean}
* @readOnly
* @readonly
* @default false
* @since 3.0.0
*/
@ -85,7 +85,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#running
* @type {boolean}
* @readOnly
* @readonly
* @default false
* @since 3.0.0
*/
@ -142,7 +142,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#actualFps
* @type {integer}
* @readOnly
* @readonly
* @default 60
* @since 3.0.0
*/
@ -153,7 +153,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#nextFpsUpdate
* @type {integer}
* @readOnly
* @readonly
* @default 0
* @since 3.0.0
*/
@ -164,7 +164,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#framesThisSecond
* @type {integer}
* @readOnly
* @readonly
* @default 0
* @since 3.0.0
*/
@ -186,7 +186,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#forceSetTimeOut
* @type {boolean}
* @readOnly
* @readonly
* @default false
* @since 3.0.0
*/
@ -227,7 +227,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#frame
* @type {integer}
* @readOnly
* @readonly
* @default 0
* @since 3.0.0
*/
@ -238,7 +238,7 @@ var TimeStep = new Class({
*
* @name Phaser.Boot.TimeStep#inFocus
* @type {boolean}
* @readOnly
* @readonly
* @default true
* @since 3.0.0
*/
@ -450,8 +450,6 @@ var TimeStep = new Class({
*/
step: function (time)
{
this.frame++;
var before = time - this.lastTime;
if (before < 0)
@ -561,6 +559,8 @@ var TimeStep = new Class({
// Shift time value over
this.lastTime = time;
this.frame++;
},
/**
@ -607,7 +607,7 @@ var TimeStep = new Class({
}
else if (seamless)
{
this.startTime += -this.lastTime + (this.lastTime = window.performance.now());
this.startTime += -this.lastTime + (this.lastTime + window.performance.now());
}
this.raf.start(this.step.bind(this), this.useRAF);

View file

@ -109,26 +109,6 @@ var VisibilityHandler = function (game)
if (window.focus && game.config.autoFocus)
{
window.focus();
game.canvas.addEventListener('mousedown', function ()
{
window.focus();
}, { passive: true });
}
if (game.canvas)
{
game.canvas.onmouseout = function ()
{
game.isOver = false;
eventEmitter.emit('mouseout');
};
game.canvas.onmouseover = function ()
{
game.isOver = true;
eventEmitter.emit('mouseover');
};
}
};

View file

@ -17,7 +17,7 @@ var EventEmitter = require('eventemitter3');
* Keys are string-based.
*
* @class BaseCache
* @memberOf Phaser.Cache
* @memberof Phaser.Cache
* @constructor
* @since 3.0.0
*/

View file

@ -16,7 +16,7 @@ var Class = require('../utils/Class');
* instances, one per type of file. You can also add your own custom caches.
*
* @class CacheManager
* @memberOf Phaser.Cache
* @memberof Phaser.Cache
* @constructor
* @since 3.0.0
*
@ -102,6 +102,15 @@ var CacheManager = new Class({
*/
this.text = new BaseCache();
/**
* A Cache storing all html files, typically added via the Loader.
*
* @name Phaser.Cache.CacheManager#html
* @type {Phaser.Cache.BaseCache}
* @since 3.12.0
*/
this.html = new BaseCache();
/**
* A Cache storing all WaveFront OBJ files, typically added via the Loader.
*
@ -181,6 +190,7 @@ var CacheManager = new Class({
'shader',
'audio',
'text',
'html',
'obj',
'tilemap',
'xml'

1855
src/cameras/2d/BaseCamera.js Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -63,7 +63,7 @@ var RectangleContains = require('../../geom/rectangle/Contains');
* A Camera also has built-in special effects including Fade, Flash, Camera Shake, Pan and Zoom.
*
* @class CameraManager
* @memberOf Phaser.Cameras.Scene2D
* @memberof Phaser.Cameras.Scene2D
* @constructor
* @since 3.0.0
*
@ -188,7 +188,20 @@ var CameraManager = new Class({
{
if (!this.main)
{
this.boot();
var sys = this.systems;
if (sys.settings.cameras)
{
// We have cameras to create
this.fromJSON(sys.settings.cameras);
}
else
{
// Make one
this.add();
}
this.main = this.cameras[0];
}
var eventEmitter = this.systems.events;
@ -209,7 +222,7 @@ var CameraManager = new Class({
* By default Cameras are transparent and will render anything that they can see based on their `scrollX`
* and `scrollY` values. Game Objects can be set to be ignored by a Camera by using the `Camera.ignore` method.
*
* The Camera will have its `roundPixels` propery set to whatever `CameraManager.roundPixels` is. You can change
* The Camera will have its `roundPixels` property set to whatever `CameraManager.roundPixels` is. You can change
* it after creation if required.
*
* See the Camera class documentation for more details.
@ -258,7 +271,7 @@ var CameraManager = new Class({
*
* The Camera should either be a `Phaser.Cameras.Scene2D.Camera` instance, or a class that extends from it.
*
* The Camera will have its `roundPixels` propery set to whatever `CameraManager.roundPixels` is. You can change
* The Camera will have its `roundPixels` property set to whatever `CameraManager.roundPixels` is. You can change
* it after addition if required.
*
* The Camera will be assigned an ID, which is used for Game Object exclusion and then added to the
@ -518,18 +531,22 @@ var CameraManager = new Class({
* If found in the Camera Manager it will be immediately removed from the local cameras array.
* If also currently the 'main' camera, 'main' will be reset to be camera 0.
*
* The removed Camera is not destroyed. If you also wish to destroy the Camera, you should call
* `Camera.destroy` on it, so that it clears all references to the Camera Manager.
* The removed Cameras are automatically destroyed if the `runDestroy` argument is `true`, which is the default.
* If you wish to re-use the cameras then set this to `false`, but know that they will retain their references
* and internal data until destroyed or re-added to a Camera Manager.
*
* @method Phaser.Cameras.Scene2D.CameraManager#remove
* @since 3.0.0
*
* @param {(Phaser.Cameras.Scene2D.Camera|Phaser.Cameras.Scene2D.Camera[])} camera - The Camera, or an array of Cameras, to be removed from this Camera Manager.
* @param {boolean} [runDestroy=true] - Automatically call `Camera.destroy` on each Camera removed from this Camera Manager.
*
* @return {integer} The total number of Cameras removed.
*/
remove: function (camera)
remove: function (camera, runDestroy)
{
if (runDestroy === undefined) { runDestroy = true; }
if (!Array.isArray(camera))
{
camera = [ camera ];
@ -544,12 +561,18 @@ var CameraManager = new Class({
if (index !== -1)
{
if (runDestroy)
{
cameras[index].destroy();
}
cameras.splice(index, 1);
total++;
}
}
if (!this.main)
if (!this.main && cameras[0])
{
this.main = cameras[0];
}

View file

@ -20,7 +20,7 @@ var Class = require('../../../utils/Class');
* which is invoked each frame for the duration of the effect, if required.
*
* @class Fade
* @memberOf Phaser.Cameras.Scene2D.Effects
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.5.0
*
@ -37,7 +37,7 @@ var Fade = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readOnly
* @readonly
* @since 3.5.0
*/
this.camera = camera;
@ -47,7 +47,7 @@ var Fade = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#isRunning
* @type {boolean}
* @readOnly
* @readonly
* @default false
* @since 3.5.0
*/
@ -61,7 +61,7 @@ var Fade = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#isComplete
* @type {boolean}
* @readOnly
* @readonly
* @default false
* @since 3.5.0
*/
@ -73,7 +73,7 @@ var Fade = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#direction
* @type {boolean}
* @readOnly
* @readonly
* @since 3.5.0
*/
this.direction = true;
@ -83,7 +83,7 @@ var Fade = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#duration
* @type {integer}
* @readOnly
* @readonly
* @default 0
* @since 3.5.0
*/
@ -337,7 +337,7 @@ var Fade = new Class({
var camera = this.camera;
ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')';
ctx.fillRect(camera.x, camera.y, camera.width, camera.height);
ctx.fillRect(camera._cx, camera._cy, camera._cw, camera._ch);
return true;
},
@ -348,7 +348,7 @@ var Fade = new Class({
* @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.FlatTintPipeline} pipeline - The WebGL Pipeline to render to.
* @param {Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline} pipeline - The WebGL Pipeline to render to.
* @param {function} getTintFunction - A function that will return the gl safe tint colors.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.
@ -365,13 +365,10 @@ var Fade = new Class({
var blue = this.blue / 255;
var green = this.green / 255;
pipeline.batchFillRect(
0, 0, 1, 1, 0,
camera.x, camera.y, camera.width, camera.height,
pipeline.drawFillRect(
camera._cx, camera._cy, camera._cw, camera._ch,
getTintFunction(red, green, blue, 1),
this.alpha,
1, 0, 0, 1, 0, 0,
[ 1, 0, 0, 1, 0, 0 ]
this.alpha
);
return true;

View file

@ -20,7 +20,7 @@ var Class = require('../../../utils/Class');
* which is invoked each frame for the duration of the effect, if required.
*
* @class Flash
* @memberOf Phaser.Cameras.Scene2D.Effects
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.5.0
*
@ -37,7 +37,7 @@ var Flash = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readOnly
* @readonly
* @since 3.5.0
*/
this.camera = camera;
@ -47,7 +47,7 @@ var Flash = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#isRunning
* @type {boolean}
* @readOnly
* @readonly
* @default false
* @since 3.5.0
*/
@ -58,7 +58,7 @@ var Flash = new Class({
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#duration
* @type {integer}
* @readOnly
* @readonly
* @default 0
* @since 3.5.0
*/
@ -284,7 +284,7 @@ var Flash = new Class({
var camera = this.camera;
ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')';
ctx.fillRect(camera.x, camera.y, camera.width, camera.height);
ctx.fillRect(camera._cx, camera._cy, camera._cw, camera._ch);
return true;
},
@ -295,7 +295,7 @@ var Flash = new Class({
* @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.FlatTintPipeline} pipeline - The WebGL Pipeline to render to.
* @param {Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline} pipeline - The WebGL Pipeline to render to.
* @param {function} getTintFunction - A function that will return the gl safe tint colors.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.
@ -312,13 +312,10 @@ var Flash = new Class({
var blue = this.blue / 255;
var green = this.green / 255;
pipeline.batchFillRect(
0, 0, 1, 1, 0,
camera.x, camera.y, camera.width, camera.height,
pipeline.drawFillRect(
camera._cx, camera._cy, camera._cw, camera._ch,
getTintFunction(red, green, blue, 1),
this.alpha,
1, 0, 0, 1, 0, 0,
[ 1, 0, 0, 1, 0, 0 ]
this.alpha
);
return true;

Some files were not shown because too many files have changed in this diff Show more