Merge branch 'photonstorm-master3' into master

This commit is contained in:
Svipal 2020-09-19 10:57:54 +02:00
commit 73dc884e61
580 changed files with 745042 additions and 683403 deletions

View file

@ -1,13 +1,12 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View file

@ -1,103 +1,103 @@
{
"root": true,
"env": {
"browser": true,
"es6": true,
"commonjs": true
},
"plugins": [
"es5"
],
"extends": [
"eslint:recommended"
],
"globals": {
"WEBGL_RENDERER": true,
"CANVAS_RENDERER": true,
"Phaser": true,
"process": true,
"ActiveXObject": true,
"FBInstant": true
},
"rules": {
"es5/no-arrow-functions": 2,
"es5/no-binary-and-octal-literals": 2,
"es5/no-block-scoping": 2,
"es5/no-classes": 2,
"es5/no-computed-properties": 2,
"es5/no-default-parameters": 2,
"es5/no-destructuring": 2,
"es5/no-es6-static-methods": 2,
"es5/no-for-of": 2,
"es5/no-generators": 2,
"es5/no-modules": 2,
"es5/no-object-super": 2,
"es5/no-rest-parameters": 2,
"es5/no-shorthand-properties": 2,
"es5/no-spread": 2,
"es5/no-template-literals": 2,
"es5/no-typeof-symbol": 2,
"es5/no-unicode-code-point-escape": 2,
"es5/no-unicode-regex": 2,
"no-cond-assign": [ "error", "except-parens" ],
"no-duplicate-case": [ "error" ],
"accessor-pairs": "error",
"curly": "error",
"eqeqeq": [ "error", "smart" ],
"no-alert": "error",
"no-caller": "error",
"no-console": [ "error", { "allow": ["warn", "log"] } ],
"no-floating-decimal": "error",
"no-invalid-this": "error",
"no-multi-spaces": "error",
"no-multi-str": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-redeclare": "error",
"no-self-assign": "error",
"no-self-compare": "error",
"yoda": [ "error", "never" ],
"array-bracket-spacing": [ "error", "always" ],
"block-spacing": [ "error", "always" ],
"brace-style": [ "error", "allman", { "allowSingleLine": true } ],
"camelcase": "error",
"comma-dangle": [ "error", "never" ],
"comma-style": [ "error", "last" ],
"computed-property-spacing": [ "error", "never" ],
"consistent-this": [ "error", "_this" ],
"eol-last": [ "error" ],
"func-call-spacing": [ "error", "never" ],
"indent": [ "error", 4, { "SwitchCase": 1 } ],
"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",
"no-constant-condition": 0,
"no-array-constructor": "error",
"no-lonely-if": "error",
"no-mixed-spaces-and-tabs": "error",
"no-plusplus": "off",
"no-prototype-builtins": "off",
"no-trailing-spaces": [ "error", { "skipBlankLines": true, "ignoreComments": true } ],
"no-underscore-dangle": "off",
"no-whitespace-before-property": "error",
"object-curly-newline": [ "error", { "multiline": true, "minProperties": 0, "consistent": true } ],
"one-var-declaration-per-line": [ "error", "initializations" ],
"quote-props": [ "error", "as-needed" ],
"quotes": [ "error", "single" ],
"semi-spacing": [ "error", { "before": false, "after": true } ],
"semi": [ "error", "always" ],
"space-before-blocks": "error",
"space-before-function-paren": "error",
"space-in-parens": [ "error", "never" ],
"space-infix-ops": [ "error", { "int32Hint": true } ],
"wrap-regex": "error",
"spaced-comment": [ "error", "always", { "block": { "balanced": true, "exceptions": ["*", "!"] }} ]
}
}
{
"root": true,
"env": {
"browser": true,
"es6": true,
"commonjs": true
},
"plugins": [
"es5"
],
"extends": [
"eslint:recommended"
],
"globals": {
"WEBGL_RENDERER": true,
"CANVAS_RENDERER": true,
"Phaser": true,
"process": true,
"ActiveXObject": true,
"FBInstant": true
},
"rules": {
"es5/no-arrow-functions": 2,
"es5/no-binary-and-octal-literals": 2,
"es5/no-block-scoping": 2,
"es5/no-classes": 2,
"es5/no-computed-properties": 2,
"es5/no-default-parameters": 2,
"es5/no-destructuring": 2,
"es5/no-es6-static-methods": 2,
"es5/no-for-of": 2,
"es5/no-generators": 2,
"es5/no-modules": 2,
"es5/no-object-super": 2,
"es5/no-rest-parameters": 2,
"es5/no-shorthand-properties": 2,
"es5/no-spread": 2,
"es5/no-template-literals": 2,
"es5/no-typeof-symbol": 2,
"es5/no-unicode-code-point-escape": 2,
"es5/no-unicode-regex": 2,
"no-cond-assign": [ "error", "except-parens" ],
"no-duplicate-case": [ "error" ],
"accessor-pairs": "error",
"curly": "error",
"eqeqeq": [ "error", "smart" ],
"no-alert": "error",
"no-caller": "error",
"no-console": [ "error", { "allow": ["warn", "log"] } ],
"no-floating-decimal": "error",
"no-invalid-this": "error",
"no-multi-spaces": "error",
"no-multi-str": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-redeclare": "error",
"no-self-assign": "error",
"no-self-compare": "error",
"yoda": [ "error", "never" ],
"array-bracket-spacing": [ "error", "always" ],
"block-spacing": [ "error", "always" ],
"brace-style": [ "error", "allman", { "allowSingleLine": true } ],
"camelcase": "error",
"comma-dangle": [ "error", "never" ],
"comma-style": [ "error", "last" ],
"computed-property-spacing": [ "error", "never" ],
"consistent-this": [ "error", "_this" ],
"eol-last": [ "error" ],
"func-call-spacing": [ "error", "never" ],
"indent": [ "error", 4, { "SwitchCase": 1 } ],
"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",
"no-constant-condition": 0,
"no-array-constructor": "error",
"no-lonely-if": "error",
"no-mixed-spaces-and-tabs": "error",
"no-plusplus": "off",
"no-prototype-builtins": "off",
"no-trailing-spaces": [ "error", { "skipBlankLines": true, "ignoreComments": true } ],
"no-underscore-dangle": "off",
"no-whitespace-before-property": "error",
"object-curly-newline": [ "error", { "multiline": true, "minProperties": 0, "consistent": true } ],
"one-var-declaration-per-line": [ "error", "initializations" ],
"quote-props": [ "error", "as-needed" ],
"quotes": [ "error", "single" ],
"semi-spacing": [ "error", { "before": false, "after": true } ],
"semi": [ "error", "always" ],
"space-before-blocks": "error",
"space-before-function-paren": "error",
"space-in-parens": [ "error", "never" ],
"space-infix-ops": [ "error", { "int32Hint": true } ],
"wrap-regex": "error",
"spaced-comment": [ "error", "always", { "block": { "balanced": true, "exceptions": ["*", "!"] }} ]
}
}

13
.gitattributes vendored Normal file
View file

@ -0,0 +1,13 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.js text
*.ts text
*.md text
*.json text
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

View file

@ -1,94 +1,94 @@
# How to contribute
It's important to us that you feel you can contribute towards the evolution of Phaser. This can take many forms: from helping to fix bugs or improve the docs, to adding in new features to the source. This guide should help you in making that process as smooth as possible.
Before contributing, please read the [code of conduct](https://github.com/photonstorm/phaser/blob/master/.github/CODE_OF_CONDUCT.md).
## Reporting issues
[GitHub Issues][0] is the place to report bugs you may have found. When submitting a bug please do the following:
**1. Search for existing issues.** Your bug may have already been fixed, or cannot, or will not, be fixed. So be sure to search the issues first before putting in a duplicate issue.
**2. Not sure if it's a bug?.** Please ask on the [forum][4]. If something is blatantly wrong then post it to GitHub. But if you feel it might just be because you're not sure of expected behavior, then it might save us time, and get you a response faster, if you post it to the Phaser forum instead.
**3. Create an isolated and reproducible test case.** If you are reporting a bug, make sure you also have a minimal, runnable, code example that reproduces the problem you have.
**4. Include a live example.** After narrowing your code down to only the problem areas, make use of [jsFiddle][1], [jsBin][2], [CodePen][5], or a link to your live site so that we can view a live example of the problem.
**5. Share as much information as possible.** Include browser version affected, your OS, version of the library, steps to reproduce, etc. "X isn't working!!!1!" will probably just be closed.
## Support Forum
We have a very active [Phaser Support Forum][4]. If you need general support, or are struggling to understand how to do something or need your code checked over, then we would urge you to post it to our forum. There are a lot of friendly devs in there who can help, as well as the core Phaser team, so it's a great place to get support. You're welcome to report bugs directly on GitHub, but for general support we'd always recommend using the forum first.
## Contribute with online one-click setup
You can use Gitpod (a free online VS Code-like IDE) for contributing. With a single click, it will launch a workspace and automatically:
- clone the `phaser` repo.
- install the dependencies.
- run `npm run build`.
- run `npm run watch`.
- clone `phaser-3-examples` and afterwards install dependencies and run `npm start` in there.
So that anyone interested in contributing can start straight away.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/photonstorm/phaser)
## Making Changes
I'm assuming you already have a recent version of [Node](https://nodejs.org) installed locally and can run `npm`. This guide is tested and works on both Windows 10 and OS X.
### 1. Checkout the repos
Check-out both the [Phaser repo](https://github.com/photonstorm/phaser) and the [Phaser 3 Examples Repo](https://github.com/photonstorm/phaser3-examples). Make sure the Phaser 3 Examples repo is saved locally in a folder called `phaser3-examples`, which will be the default for most Git clients.
### 2. Matching Directory Levels
Ensure that both repos live at the same depth in your directory structure. For example: `/usr/home/web/phaser` and `/usr/home/web/phaser3-examples`. This is so the dev build scripts in the Phaser repo can safely copy files to `../phaser3-examples` and have them end up in the correct place.
### 3. Install dependencies
Using your console, run `npm install` or `yarn install` as we've configs for both. This process will install a local copy of webpack and a handful of small support scripts. Note that Yarn on Windows seems to have issues making some packages global, so stick with npm if this is the case.
### 4. Webpack
Making sure you've got both repos checked out, and at the same directory level in your filesystem, issue the command `webpack`. If you can't issue the command then webpack may need [installing globally](https://webpack.js.org/guides/installation/). Webpack will build Phaser and if there are any path errors in the code they'll be flagged during the build process.
What you need is the ability to issue the command `webpack` within the v3 folder and have it work.
### 5. ESLint
There is an ESLint configuration and an Editor Configuration in the v3 folder. **Please adhere to them!** Although not enforced in the build process yet, I will be adding that at a later point. There are lots of tools you can install so your editor of choice will check the ESLint config during development.
To test if your code passes our lint config issue the command `npm run lint`.
## Coding style preferences are not contributions
If your PR is doing little more than changing the Phaser source code into a format / coding style that you prefer then we will automatically close it. All PRs must adhere to the coding style already set-out across the thousands of lines of code in Phaser. Your personal preferences for how things should "look" or be structured do not apply here, sorry. PRs should fix bugs, fix documentation or add features. No changes for the sake of change.
## I don't really like git / node.js, but I can fix this bug
That is fine too. While Pull Requests are the best thing in the world for us, they are not the only way to help. You're welcome to post fixes to our forum or even just email them to us. All we ask is that you still adhere to the guidelines presented here re: ESLint, etc.
## Code Style Guide
We provide an .editorconfig and eslint config for you to use, but generally:
- Use 4 spaces for tabs, never tab characters.
- No trailing whitespace, blank lines should have no whitespace.
- Always favor strict equals `===` unless you *need* to use type coercion.
- Follow conventions already in the code, and listen to eslint. Our config is set-up for a reason.
Thanks to Chad for creating the original Pixi.js Contributing file which we adapted for Phaser.
[0]: https://github.com/photonstorm/phaser/issues
[1]: http://jsfiddle.net
[2]: http://jsbin.com/
[3]: http://nodejs.org
[4]: https://phaser.discourse.group/
[5]: https://codepen.io/pen?template=YeEWom "Phaser 3 game template"
# How to contribute
It's important to us that you feel you can contribute towards the evolution of Phaser. This can take many forms: from helping to fix bugs or improve the docs, to adding in new features to the source. This guide should help you in making that process as smooth as possible.
Before contributing, please read the [code of conduct](https://github.com/photonstorm/phaser/blob/master/.github/CODE_OF_CONDUCT.md).
## Reporting issues
[GitHub Issues][0] is the place to report bugs you may have found. When submitting a bug please do the following:
**1. Search for existing issues.** Your bug may have already been fixed, or cannot, or will not, be fixed. So be sure to search the issues first before putting in a duplicate issue.
**2. Not sure if it's a bug?.** Please ask on the [forum][4]. If something is blatantly wrong then post it to GitHub. But if you feel it might just be because you're not sure of expected behavior, then it might save us time, and get you a response faster, if you post it to the Phaser forum instead.
**3. Create an isolated and reproducible test case.** If you are reporting a bug, make sure you also have a minimal, runnable, code example that reproduces the problem you have.
**4. Include a live example.** After narrowing your code down to only the problem areas, make use of [jsFiddle][1], [jsBin][2], [CodePen][5], or a link to your live site so that we can view a live example of the problem.
**5. Share as much information as possible.** Include browser version affected, your OS, version of the library, steps to reproduce, etc. "X isn't working!!!1!" will probably just be closed.
## Support Forum
We have a very active [Phaser Support Forum][4]. If you need general support, or are struggling to understand how to do something or need your code checked over, then we would urge you to post it to our forum. There are a lot of friendly devs in there who can help, as well as the core Phaser team, so it's a great place to get support. You're welcome to report bugs directly on GitHub, but for general support we'd always recommend using the forum first.
## Contribute with online one-click setup
You can use Gitpod (a free online VS Code-like IDE) for contributing. With a single click, it will launch a workspace and automatically:
- clone the `phaser` repo.
- install the dependencies.
- run `npm run build`.
- run `npm run watch`.
- clone `phaser-3-examples` and afterwards install dependencies and run `npm start` in there.
So that anyone interested in contributing can start straight away.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/photonstorm/phaser)
## Making Changes
I'm assuming you already have a recent version of [Node](https://nodejs.org) installed locally and can run `npm`. This guide is tested and works on both Windows 10 and OS X.
### 1. Checkout the repos
Check-out both the [Phaser repo](https://github.com/photonstorm/phaser) and the [Phaser 3 Examples Repo](https://github.com/photonstorm/phaser3-examples). Make sure the Phaser 3 Examples repo is saved locally in a folder called `phaser3-examples`, which will be the default for most Git clients.
### 2. Matching Directory Levels
Ensure that both repos live at the same depth in your directory structure. For example: `/usr/home/web/phaser` and `/usr/home/web/phaser3-examples`. This is so the dev build scripts in the Phaser repo can safely copy files to `../phaser3-examples` and have them end up in the correct place.
### 3. Install dependencies
Using your console, run `npm install` or `yarn install` as we've configs for both. This process will install a local copy of webpack and a handful of small support scripts. Note that Yarn on Windows seems to have issues making some packages global, so stick with npm if this is the case.
### 4. Webpack
Making sure you've got both repos checked out, and at the same directory level in your filesystem, issue the command `webpack`. If you can't issue the command then webpack may need [installing globally](https://webpack.js.org/guides/installation/). Webpack will build Phaser and if there are any path errors in the code they'll be flagged during the build process.
What you need is the ability to issue the command `webpack` within the v3 folder and have it work.
### 5. ESLint
There is an ESLint configuration and an Editor Configuration in the v3 folder. **Please adhere to them!** Although not enforced in the build process yet, I will be adding that at a later point. There are lots of tools you can install so your editor of choice will check the ESLint config during development.
To test if your code passes our lint config issue the command `npm run lint`.
## Coding style preferences are not contributions
If your PR is doing little more than changing the Phaser source code into a format / coding style that you prefer then we will automatically close it. All PRs must adhere to the coding style already set-out across the thousands of lines of code in Phaser. Your personal preferences for how things should "look" or be structured do not apply here, sorry. PRs should fix bugs, fix documentation or add features. No changes for the sake of change.
## I don't really like git / node.js, but I can fix this bug
That is fine too. While Pull Requests are the best thing in the world for us, they are not the only way to help. You're welcome to post fixes to our forum or even just email them to us. All we ask is that you still adhere to the guidelines presented here re: ESLint, etc.
## Code Style Guide
We provide an .editorconfig and eslint config for you to use, but generally:
- Use 4 spaces for tabs, never tab characters.
- No trailing whitespace, blank lines should have no whitespace.
- Always favor strict equals `===` unless you *need* to use type coercion.
- Follow conventions already in the code, and listen to eslint. Our config is set-up for a reason.
Thanks to Chad for creating the original Pixi.js Contributing file which we adapted for Phaser.
[0]: https://github.com/photonstorm/phaser/issues
[1]: http://jsfiddle.net
[2]: http://jsbin.com/
[3]: http://nodejs.org
[4]: https://phaser.discourse.group/
[5]: https://codepen.io/pen?template=YeEWom "Phaser 3 game template"

581
CHANGELOG-v3.50.md Normal file
View file

@ -0,0 +1,581 @@
## Version 3.50.0 - Subaru - in development
### WebGL Pipeline Updates
If you use a custom WebGL Pipeline in your game, you must update your code in order to use Phaser 3.50.
Due to the huge amount of work that has taken place in this area, all of the pipelines have been renamed. If you extend any of these pipelines or use them in your game code (referenced by name), then please update accordingly. The name changes are:
* `TextureTintPipeline` is now called the `MultiPipeline`.
* `TextureTintStripPipeline` is now called the `RopePipeline`.
* `ForwardDiffuseLightPipeline` is now called the `LightPipeline`.
To match the new pipeline names, the shader source code has also been renamed.
* `ForwardDiffuse.frag` is now called `Light.frag`.
* `TextureTint.frag` is now called `Multi.frag`.
* `TextureTint.vert` is now called `Multi.vert`.
Other pipeline changes are as follows:
* `Types.Renderer.WebGL.WebGLPipelineConfig` is a new TypeDef that helps you easily configure your own Custom Pipeline when using TypeScript and also provides better JSDocs.
* `Types.Renderer.WebGL.WebGLPipelineAttributesConfig` is a new TypeDef that helps you easily configure the attributes for your own Custom Pipelines when using TypeScript and also provides better JSDocs.
* All pipelines will now work out the `renderer` property automatically, so it's no longer required in the config.
* All pipelines will now work out the `gl` property automatically, so it's no longer required in the config.
* All pipelines will now extract the `name` property from the config, allowing you to set it externally.
* All pipelines will now extract the `vertexCapacity` property from the config, allowing you to set it externally.
* All pipelines will now extract the `vertexSize` property from the config, allowing you to set it externally.
* All pipelines will now extract the `vertexData` property from the config, allowing you to set it externally.
* All pipelines will now extract the `attributes` property from the config, allowing you to set it externally.
* All pipelines will now extract the `topology` property from the config, allowing you to set it externally.
* The `WebGLPipeline.shouldFlush` method now accepts an optional parameter `amount`. If given, it will return `true` if when the amount is added to the vertex count it will exceed the vertex capacity. The Multi Pipeline has been updated to now use this method instead of performing the comparison multiple times itself.
### Pipeline Manager
The `WebGL.PipelineManager` is a new class that is responsbile for managing all of the WebGL Pipelines in Phaser. An instance of the Pipeline Manager is created by the WebGL Renderer and is available under the `pipelines` property. This means that the WebGL Renderer no longer handles pipelines directly, causing the following API changes:
* `WebGLRenderer.pipelines` is no longer a plain object containing pipeline instances. It's now an instance of the `PipelineManager` class. This instance is created during the init and boot phase of the renderer.
* The `WebGLRenderer.currentPipeline` property no longer exists, instead use `PipelineManager.current`.
* The `WebGLRenderer.previousPipeline` property no longer exists, instead use `PipelineManager.previous`.
* The `WebGLRenderer.hasPipeline` method no longer exists, instead use `PipelineManager.has`.
* The `WebGLRenderer.getPipeline` method no longer exists, instead use `PipelineManager.get`.
* The `WebGLRenderer.removePipeline` method no longer exists, instead use `PipelineManager.remove`.
* The `WebGLRenderer.addPipeline` method no longer exists, instead use `PipelineManager.add`.
* The `WebGLRenderer.setPipeline` method no longer exists, instead use `PipelineManager.set`.
* The `WebGLRenderer.rebindPipeline` method no longer exists, instead use `PipelineManager.rebind`.
* The `WebGLRenderer.clearPipeline` method no longer exists, instead use `PipelineManager.clear`.
The Pipeline Manager also offers the following new features:
* The `PipelineManager.resize` method automatically handles resize events across all pipelines.
* The `PipelineManager.preRender` method calls the pre-render method of all pipelines.
* The `PipelineManager.render` method calls the render method of all pipelines.
* The `PipelineManager.postRender` method calls the post-render method of all pipelines.
* The `PipelineManager.setMulti` method automatically binds the Multi Texture Pipeline, Phaser's default.
* The `PipelineManager.clear` method will clear the pipeline, store it in `previous` and free the renderer.
* The `PipelineManager.rebind` method will reset the rendering context and restore the `previous` pipeline, if set.
New constants have been created to help you reference a pipeline without needing to use strings:
* `Phaser.Renderer.WebGL.Pipelines.BITMAPMASK_PIPELINE` for the Bitmap Mask Pipeline.
* `Phaser.Renderer.WebGL.Pipelines.LIGHT_PIPELINE` for the Light 2D Pipeline.
* `Phaser.Renderer.WebGL.Pipelines.SINGLE_PIPELINE` for the Single Pipeline.
* `Phaser.Renderer.WebGL.Pipelines.MULTI_PIPELINE` for the Multi Pipeline.
* `Phaser.Renderer.WebGL.Pipelines.ROPE_PIPELINE` for the Rope Pipeline.
All Game Objects have been updated to use the new constants and Pipeline Manager.
#### Single Pipeline
There is also a new pipeline called `SinglePipeline`, created to emulate the old `TextureTintPipeline`. This special pipeline uses just a single texture and makes things a lot easier if you wish to create a custom pipeline, but not have to recode your shaders to work with multiple textures. Instead, just extend `SinglePipeline`, where-as before you extended the `TextureTintPipeline` and you won't have to change any of your shader code. However, if you can, you should update it to make it perform faster, but that choice is left up to you.
### WebGL Multi-Texture Rendering
The Multi Pipeline (previously called the Texture Tint Pipeline) has had its core flow rewritten to eliminate the need for constantly creating `batch` objects. Instead, it now supports the new multi-texture shader, vastly increasing rendering performance, especially on draw-call bound systems.
All of the internal functions, such as `batchQuad` and `batchSprite` have been updated to use the new method of texture setting. The method signatures all remain the same unless indicated below.
* `Config.render.maxTextures` is a new game config setting that allows you to control how many texture units will be used in WebGL.
* `WebGL.Utils.checkShaderMax` is a new function, used internally by the renderer, to determine the maximum number of texture units the GPU + browser supports.
* The property `WebGLRenderer.currentActiveTextureUnit` has been renamed to `currentActiveTexture`.
* `WebGLRenderer.startActiveTexture` is a new read-only property contains the current starting active texture unit.
* `WebGLRenderer.maxTextures` is a new read-only property that contains the maximum number of texture units WebGL can use.
* `WebGLRenderer.textureIndexes` is a new read-only array that contains all of the available WebGL texture units.
* `WebGLRenderer.tempTextures` is a new read-only array that contains temporary WebGL textures.
* The `WebGLRenderer.currentTextures` property has been removed, as it's no longer used.
* `TextureSource.glIndex` is a new property that holds the currently assigned texture unit for the Texture Source.
* `TextureSource.glIndexCounter` is a new property that holds the time the index was assigned to the Texture Source.
* `WebGLRenderer.currentTextures` has been removed, as it's no longer used internally.
* `WebGLRenderer.setBlankTexture` no longer has a `force` parameter, as it's set by default.
* The Mesh Game Object WebGL Renderer function has been updated to support multi-texture units.
* The Blitter Game Object WebGL Renderer function has been updated to support multi-texture units.
* The Bitmap Text Game Object WebGL Renderer function has been updated to support multi-texture units.
* The Dynamic Bitmap Text Game Object WebGL Renderer function has been updated to support multi-texture units.
* The Particle Emitter Game Object WebGL Renderer function has been updated to support multi-texture units.
* The Texture Tint vertex and fragment shaders have been updated to support the `inTexId` float attribute and dynamic generation.
* The Texture Tint Pipeline has a new attribute, `inTexId` which is a `gl.FLOAT`.
* `TextureTintPipeline.bind` is a new method that sets the `uMainSampler` uniform.
* The `TextureTintPipeline.requireTextureBatch` method has been removed, as it's no longer required.
* The `TextureTintPipeline.pushBatch` method has been removed, as it's no longer required.
* The `TextureTintPipeline.maxQuads` property has been removed, as it's no longer required.
* The `TextureTintPipeline.batches` property has been removed, as it's no longer required.
* `TextureTintPipeline.flush` has been rewritten to support multi-textures.
* `TextureTintPipeline.flush` no longer creates a sub-array if the batch is full, but instead uses `bufferData` for speed.
* `WebGLPipeline.currentUnit` is a new property that holds the most recently assigned texture unit. Treat as read-only.
* `WebGLRenderer.setTextureSource` is a new method, used by pipelines and Game Objects, that will assign a texture unit to the given Texture Source.
* The `WebGLRenderer.setTexture2D` method has been updated to use the new texture unit assignment. It no longer takes the `textureUnit` or `flush` parameters and these have been removed from its method signature.
* `WebGLRenderer.setTextureZero` is a new method that activates texture zero and binds the given texture to it. Useful for fbo backed game objects.
* `WebGLRenderer.clearTextureZero` is a new method that clears the texture that was bound to unit zero.
* `WebGLRenderer.textureZero` is a new property that holds the currently bound unit zero texture.
* `WebGLRenderer.normalTexture` is a new property that holds the currently bound normal map (texture unit one).
* `WebGLRenderer.setNormalMap` is a new method that sets the current normal map texture.
* `WebGLRenderer.clearNormalMap` is a new method that clears the current normal map texture.
* `WebGLRenderer.resetTextures` is a new method that flushes the pipeline, resets all textures back to the temporary ones, and resets the active texture counter.
* `WebGLPipeline.boot` will now check all of the attributes and store the pointer location within the attribute entry.
* `WebGLPipeline.bind` no longer looks-up and enables every attribute, every frame. Instead, it uses the cached pointer location stored in the attribute entry, cutting down on redundant WebGL operations.
* `WebGLRenderer.isNewNormalMap` is a new method that returns a boolean if the given parameters are not currently used.
* `WebGLPipeline.forceZero` is a new property that informs Game Objects if the pipeline requires a zero bound texture unit.
* `WebGLPipeline.setAttribPointers` is a new method that will set the vertex attribute pointers for the pipeline.
* `WebGLRenderer.unbindTextures` is a new method that will activate and then null bind all WebGL textures.
* `Renderer.WebGL.Utils.parseFragmentShaderMaxTextures` is a new function that will take fragment shader source and search it for `%count%` and `%forloop%` declarations, replacing them with the required GLSL for multi-texture support, returning the modified source.
### Light Pipeline Changes
The Light Pipeline (previously called the Forward Diffuse Light Pipeline), which is responsible for rendering lights under WebGL, has been rewritten to work with the new Multi Pipeline features. Lots of redundant code has been removed and the following changes and improvements took place:
* The pipeline now works with Game Objects that do not have a normal map. They will be rendered using the new default normal map, which allows for a flat light effect to pass over them and merge with their diffuse map colors.
* Fixed a bug in the way lights were handled that caused Tilemaps to render one tile at a time, causing massive slow down. They're now batched properly, making a combination of lights and tilemaps possible again.
* The Bitmap Text (Static and Dynamic) Game Objects now support rendering with normal maps.
* The TileSprite Game Objects now support rendering with normal maps.
* Mesh and Quad Game Objects now support rendering with normal maps.
* The Graphics Game Objects now support rendering in Light2d. You can even use normal map textures for the texture fills.
* Particle Emitter Game Object now supports rendering in Light2d.
* All Shape Game Objects (Rectangle, IsoBox, Star, Polygon, etc) now support rendering in Light2d.
* The Text Game Object now supports rendering in Light2d, no matter which font, stroke or style it is using.
* Both Static and Dynamic Tilemap Layer Game Objects now support the Light2d pipeline, with or without normal maps.
* The pipeline will no longer look-up and set all of the light uniforms unless the `Light` is dirty.
* The pipeline will no longer reset all of the lights unless the quantity of lights has changed.
* The `ForwardDiffuseLightPipeline.defaultNormalMap` property has changed, it's now an object with a `glTexture` property that maps to the pipelines default normal map.
* The `ForwardDiffuseLightPipeline.boot` method has been changed to now generate a default normal map.
* The `ForwardDiffuseLightPipeline.onBind` method has been removed as it's no longer required.
* The `ForwardDiffuseLightPipeline.setNormalMap` method has been removed as it's no longer required.
* `ForwardDiffuseLightPipeline.bind` is a new method that handles setting-up the shader uniforms.
* The `ForwardDiffuseLightPipeline.batchTexture` method has been rewritten to use the Texture Tint Pipeline function instead.
* The `ForwardDiffuseLightPipeline.batchSprite` method has been rewritten to use the Texture Tint Pipeline function instead.
* `ForwardDiffuseLightPipeline.lightCount` is a new property that stores the previous number of lights rendered.
* `ForwardDiffuseLightPipeline.getNormalMap` is a new method that will look-up and return a normal map for the given object.
### Lights
* `Light.dirty` is a new property that controls if the light is dirty, or not, and needs its uniforms updating.
* `Light` has been recoded so that all of its properties are now setters that activate its `dirty` flag.
* `LightsManager.destroy` will now clear the `lightPool` array when destroyed, where-as previously it didn't.
* `LightsManager.cull` now takes the viewport height from the renderer instead of the game config (thanks zenwaichi)
### WebGL ModelViewProjection API Changes
The `ModelViewProjection` object contained a lot of functions that Phaser never used internally. These have now been
moved to external functions, which can be easily excluded from Custom builds to save space.
If you used any of them in your code, please update to the new function names below:
* `Phaser.Renderer.WebGL.MVP` is a new namespace under which the Model View Projection functions now live.
* `projIdentity` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ProjectIdentity`
* `projPersp` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ProjectPerspective`
* `modelRotateX` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.RotateX`
* `modelRotateY` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.RotateY`
* `modelRotateZ` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.RotateZ`
* `viewLoad` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewLoad`
* `viewRotateX` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewRotateX`
* `viewRotateY` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewRotateY`
* `viewRotateZ` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewRotateZ`
* `viewScale` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewScale`
* `viewTranslate` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewTranslate`
* `modelIdentity` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.Identity`
* `modelScale` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.Scale`
* `modelTranslate` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.Translate`
* `viewIdentity` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewIdentity`
* `viewLoad2D` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ViewLoad2D`
* `projOrtho` is now available as a stand-alone function `Phaser.Renderer.WebGL.MVP.ProjectOrtho`
* `Phaser.Renderer.WebGL.MVP.SetIdentity` is a new function the others use, to save on space.
### BitmapText - New Features, Updates and API Changes
* `BitmapText.setCharacterTint` is a new method that allows you to set a tint color (either additive or fill) on a specific range of characters within a static Bitmap Text. You can specify the start and length offsets and per-corner tint colors.
* `BitmapText.setWordTint` is a new method that allows you to set a tint color (either additive or fill) on all matching words within a static Bitmap Text. You can specify the word by string, or numeric offset, and the number of replacements to tint.
* `BitmapText.setDropShadow` is a new method that allows you to apply a drop shadow effect to a Bitmap Text object. You can set the horizontal and vertical offset of the shadow, as well as the color and alpha levels. Call this method with no parameters to clear a shadow.
* `BitmapTextWebGLRenderer` has been rewritten from scratch to make use of the new pre-cached WebGL uv texture and character location data generated by `GetBitmapTextSize`. This has reduced the number of calculations made in the function dramatically, as it no longer has work out glyph advancing or offsets during render, but only when the text content updates.
* `BitmapText.getCharacterAt` is a new method that will return the character data from the BitmapText at the given `x` and `y` coordinates. The character data includes the code, position, dimensions, and glyph information.
* The `BitmapTextSize` object returned by `BitmapText.getTextBounds` has a new property called `characters` which is an array that contains the scaled position coordinates of each character in the BitmapText, which you could use for tasks such as determining which character in the BitmapText was clicked.
* `ParseXMLBitmapFont` will now calculate the WebGL uv data for the glyphs during parsing. This avoids it having to be done during rendering, saving CPU cycles on an operation that never changes.
* `ParseXMLBitmapFont` will now create a Frame object for each glyph. This means you could, for example, create a Sprite using the BitmapText texture and the glyph as the frame key, i.e.: `this.add.sprite(x, y, fontName, 'A')`.
* `BitmapTextWord`, `BitmapTextCharacter` and `BitmapTextLines` are three new type defs that are now part of the `BitmapTextSize` config object, as returned by `getTextBounds`. This improves the TypeScript defs and JS Docs for this object.
* The signature of the `ParseXMLBitmapFont` function has changed. The `frame` parameter is no longer optional, and is now the second parameter in the list, instead of being the 4th. If you call this function directly, please update your code.
* The `BitmapText.getTextBounds` method was being called every frame, even if the bounds didn't change, potentially costing a lot of CPU time depending on the text length and quantity of them. It now only updates the bounds if they change.
* The `GetBitmapTextSize` function used `Math.round` on the values, if the `round` parameter was `true`, which didn't create integers. It now uses `Math.ceil` instead to give integer results.
* The `GetBitmapTextSize` function has a new boolean parameter `updateOrigin`, which will adjust the origin of the parent BitmapText if set, based on the new bounds calculations.
* `BitmapText.preDestroy` is a new method that will tidy-up all of the BitmapText data during object destruction.
* `BitmapText.dropShadowX` is a new property that controls the horizontal offset of the drop shadow on the Bitmap Text.
* `BitmapText.dropShadowY` is a new property that controls the vertical offset of the drop shadow on the Bitmap Text.
* `BitmapText.dropShadowColor` is a new property that sets the color of the Bitmap Text drop shadow.
* `BitmapText.dropShadowAlpha` is a new property that sets the alpha of the Bitmap Text drop shadow.
* `BatchChar` is a new internal private function for batching a single character of a Bitmap Text to the pipeline.
* If you give an invalid Bitmap Font key, the Bitmap Text object will now issue a `console.warn`.
* Setting the `color` value in the `DynamicBitmapText.setDisplayCallback` would inverse the red and blue channels if the color was not properly encoded for WebGL. It is now encoded automatically, meaning you can pass normal hex values as the colors in the display callback. Fix #5225 (thanks @teebarjunk)
* If you apply `setSize` to the Dynamic BitmapText the scissor is now calculated based on the parent transforms, not just the local ones, meaning you can crop Bitmap Text objects that exist within Containers. Fix #4653 (thanks @lgibson02)
* `ParseXMLBitmapFont` has a new optional parameter `texture`. If defined, this Texture is populated with Frame data, one frame per glyph. This happens automatically when loading Bitmap Text data in Phaser.
### Update List Changes
The way in which Game Objects add themselves to the Scene Update List has changed. Instead of being added by the Factory methods, they will now add and remove themselves based on the new `ADDED_TO_SCENE` and `REMOVED_FROM_SCENE` events. This means, you can now add Sprites directly to a Container, or Group, and they'll animate properly without first having to be part of the Display List. The full set of changes and new features relating to this follow:
* `GameObjects.Events.ADDED_TO_SCENE` is a new event, emitted by a Game Object, when it is added to a Scene, or a Container that is part of the Scene.
* `GameObjects.Events.REMOVED_FROM_SCENE` is a new event, emitted by a Game Object, when it is removed from a Scene, or a Container that is part of the Scene.
* `Scenes.Events.ADDED_TO_SCENE` is a new event, emitted by a Scene, when a new Game Object is added to the display list in the Scene, or a Container that is on the display list.
* `Scenes.Events.REMOVED_FROM_SCENE` is a new event, emitted by a Scene, when it a Game Object is removed from the display list in the Scene, or a Container that is on the display list.
* `GameObject.addedToScene` is a new method that custom Game Objects can use to perform additional set-up when a Game Object is added to a Scene. For example, Sprite uses this to add itself to the Update List.
* `GameObject.removedFromScene` is a new method that custom Game Objects can use to perform additional tear-down when a Game Object is removed from a Scene. For example, Sprite uses this to remove themselves from the Update List.
* Game Objects no longer automatically remove themselves from the Update List during `preDestroy`. This should be handled directly in the `removedFromScene` method now.
* The `Container` will now test to see if any Game Object added to it is already on the display list, or not, and emit its ADDED and REMOVED events accordingly. Fix #5267 #3876 (thanks @halgorithm @mbpictures)
* `DisplayList.events` is a new property that references the Scene's Event Emitter. This is now used internally.
* `DisplayList.addChildCallback` is a new method that overrides the List callback and fires the new ADDED events.
* `DisplayList.removeChildCallback` is a new method that overrides the List callback and fires the new REMOVED events.
* `GameObjectCreator.events` is a new property that references the Scene's Event Emitter. This is now used internally.
* `GameObjectFactory.events` is a new property that references the Scene's Event Emitter. This is now used internally.
* `ProcessQueue.checkQueue` is a new boolean property that will make sure only unique objects are added to the Process Queue.
* The `Update List` now uses the new `checkQueue` property to ensure no duplicate objects are on the active list.
* `DOMElementFactory`, `ExternFactory`, `ParticleManagerFactor`, `RopeFactory` and `SpriteFactory` all no longer add the objects to the Update List, this is now handled by the ADDED events instead.
* `Sprite`, `Rope`, `ParticleEmitterManager`, `Extern` and `DOMElement` now all override the `addedToScene` and `removedFromScene` callbacks to handle further set-up tasks.
### Spine Plugin Updates
* The Spine Runtimes have been updated to 3.8.95, which are the most recent non-beta versions. Please note, you will _need_ to re-export your animations if you're working in a version of Spine lower than 3.8.20.
* `SpineContainer` is a new Game Object available via `this.add.spineContainer` to which you can add Spine Game Objects only. It uses a special rendering function to retain batching, even across multiple container or Spine Game Object instances, resulting in dramatically improved performance over using regular Containers.
* A Spine Game Object with `setVisible(false)` will no longer still cause internal gl commands and is now properly skipped, retaining any current batch in the process. Fix #5174 (thanks @Kitsee)
* The Spine Game Object WebGL Renderer will no longer clear the type if invisible and will only end the batch if the next type doesn't match.
* The Spine Game Object WebGL Renderer will no longer rebind the pipeline if it was the final object on the display list, saving lots of gl commands.
* The Webpack build scripts have all been updated for Webpack 4.44.x. Fix #5243 (thanks @RollinSafary)
* There is a new npm script `npm run plugin.spine.runtimes` which will build all of the Spine runtimes, for ingestion by the plugin. Note: You will need to check-out the Esoteric Spine Runtimes repo into `plugins/spine/` in order for this to work.
* Spine Game Objects can now be rendered to Render Textures. Fix #5184 (thanks @Kitsee)
* Using > 128 Spine objects in a Container would cause a `WebGL: INVALID_OPERATION: vertexAttribPointer: no ARRAY_BUFFER is bound and offset is non-zero` error if you added any subsequent Spine objects to the Scene. There is now no limit. Fix #5246 (thanks @d7561985)
* The Spine Plugin will now work in HEADLESS mode without crashing. Fix #4988 (thanks @raimon-segura)
* Spine Game Objects now use -1 as their default blend mode, which means 'skip setting it'.
* The Spine TypeScript defs have been updated for the latest version of the plugin and to add SpineContainers.
* The `SpineGameObject.setAnimation` method will now use the `trackIndex` parameter if `ignoreIfPlaying` is set and run the check against this track index. Fix #4842 (thanks @vinerz)
* The `SpineFile` will no longer throw a warning if adding a texture into the Texture Manager that already exists. This allows you to have multiple Spine JSON use the same texture file, however, it also means you now get no warning if you accidentally load a texture that exists, so be careful with your keys! Fix #4947 (thanks @Nomy1)
* The Spine Plugin `destroy` method will now no longer remove the Game Objects from the Game Object Factory, or dispose of the Scene Renderer. This means when a Scene is destroyed, it will keep the Game Objects in the factory for other Scene's to use. Fix #5279 (thanks @Racoonacoon)
* `SpinePlugin.gameDestroy` is a new method that is called if the Game instance emits a `destroy` event. It removes the Spine Game Objects from the factory and disposes of the Spine scene renderer.
### Animation API - New Features and Updates
If you use Animations in your game, please read the following important API changes in 3.50:
The Animation API has had a significant overhaul to improve playback handling. Instead of just playing an animation based on its global key, you can now supply a new `PlayAnimationConfig` object instead, which allows you to override any of the default animation settings, such as `duration`, `delay` and `yoyo` (see below for the full list). This means you no longer have to create lots of duplicate animations just to change properties such as `duration`, and can now set them dynamically at run-time as well.
* The `Animation` class no longer extends `EventEmitter`, as it no longer emits any events directly. This means you cannot now listen for events directly from an Animation instance. All of the events are now dispatched by the Game Objects instead.
* All of the `SPRITE_ANIMATION_KEY` events have been removed. Instead, please use the new events which all carry the `frameKey` parameter, which can be used to handle frame specific events. The only exception to this is `ANIMATION_COMPLETE_KEY`, which is a key specific version of the completion event.
* `ANIMATION_UPDATE_EVENT` is a new event that is emitted from a Sprite when an animation updates, i.e. its frame changes.
* `ANIMATION_STOP_EVENT` is a new event that is emitted from a Sprite when its current animation is stopped. This can happen if any of the `stop` methods are called, or a new animation is played prior to this one reaching completion. Fix #4894 (thanks @scott20145)
* The Game Object `Component.Animation` component has been renamed to `AnimationState` and has moved namespace. It's now in `Phaser.Animations` instead of `GameObjects.Components` to help differentiate it from the `Animation` class when browsing the documentation.
* The `play`, `playReverse`, `playAfterDelay`, `playAfterRepeat` and `chain` Sprite and Animation Component methods can now all take a `Phaser.Types.Animations.PlayAnimationConfig` configuration object, as well as a string, as the `key` parameter. This allows you to override any default animation setting with those defined in the config, giving you far greater control over animations on a Game Object level, without needing to globally duplicate them.
* `AnimationState.create` is a new method that allows you to create animations directly on a Sprite. These are not global and never enter the Animation Manager, instead risiding within the Sprite itself. This allows you to use the same keys across both local and global animations and set-up Sprite specific local animations.
* All playback methods: `play`, `playReverse`, `playAfterDelay` and `playAfterRepeat` will now check to see if the given animation key exists locally on the Sprite first. If it does, it's used, otherwise it then checks the global Animation Manager for the key instead.
* `AnimationState.skipMissedFrames` is now used when playing an animation, allowing you to create animations that run at frame rates far exceeding the refresh rate, or that will update to the correct frame should the game lag. Feature #4232 (thanks @colorcube)
* `AnimationManager.addMix` is a new method that allows you to create mixes between two animations. Mixing allows you to specify a unique delay between a pairing of animations. When playing Animation A on a Game Object, if you then play Animation B, and a mix exists, it will wait for the specified delay to be over before playing Animation B. This allows you to customise smoothing between different types of animation, such as blending between an idle and a walk state, or a running and a firing state.
* `AnimationManager.getMix` is a new method that will return the mix duration between the two given animations.
* `AnimationManager.removeMix` is a new method that will remove the mixture between either two animations, or all mixtures for the given animation.
* `AnimationState.remove` is a new method that will remove a locally stored Animation instance from a Sprite.
* `AnimationState.get` is a new method that will return a locally stored Animation instance from the Sprite.
* `AnimationState.exists` is a new method that will check if a locally stored Animation exists on the Sprite.
* The internal `AnimationState.remove` method has been renamed to `globalRemove`.
* `AnimationState.textureManager` is a new property that references the global Texture Manager.
* `AnimationState.anims` is a new property that contains locally created Animations in a Custom Map.
* `AnimationState.play` and `Sprite.play` no longer accept a `startFrame` parameter. Please set it via the `PlayAnimationConfig` instead.
* `AnimationState.playReverse` and `Sprite.playReverse` no longer accept a `startFrame` parameter. Please set it via the `PlayAnimationConfig` instead.
* The `AnimationState.delayedPlay` method has been renamed to `playAfterDelay`. The parameter order has also changed, so the key now comes first instead of the duration.
* The `AnimationState.stopOnRepeat` method has been renamed to `stopAfterRepeat`
* The `AnimationState.getCurrentKey` method has been renamed to `getName`.
* `AnimationState.getFrameName` is a new method that will return the key of the current Animation Frame, if an animation has been loaded.
* `AnimationState.playAfterDelay` and `Sprite.playAfterDelay` are new methods that will play the given animation after the delay in ms expires.
* `AnimationState.playAfterRepeat` and `Sprite.playAfterRepeat` are new methods that will play the given animation after the current animation finishes repeating. You can also specify the number of repeats allowed left to run.
* The `AnimationState.chain` method is now available on the Sprite class.
* The `AnimationState.stopAfterDelay` method is now available on the Sprite class.
* The `AnimationState.stopAfterRepeat` method is now available on the Sprite class.
* The `AnimationState.stopOnFrame` method is now available on the Sprite class.
* `AnimationManager.createFromAseprite` is a new method that allows you to use animations created in the Aseprite editor directly in Phaser. Please see the comprehensive documentation for this method for full details on how to do this.
* `AnimationState` now handles all of the loading of the animation. It no longer has to make calls out to the Animation Manager or Animation instance itself and will load the animation data directly, replacing as required from the optional `PlayAnimationConfig`. This improves performance and massively reduces CPU calls in animation heavy games.
* The `PlayAnimationConfig.frameRate` property lets you optionally override the animation frame rate.
* The `PlayAnimationConfig.duration` property lets you optionally override the animation duration.
* The `PlayAnimationConfig.delay` property lets you optionally override the animation delay.
* The `PlayAnimationConfig.repeat` property lets you optionally override the animation repeat counter.
* The `PlayAnimationConfig.repeatDelay` property lets you optionally override the animation repeat delay value.
* The `PlayAnimationConfig.yoyo` property lets you optionally override the animation yoyo boolean.
* The `PlayAnimationConfig.showOnStart` property lets you optionally override the animation show on start value.
* The `PlayAnimationConfig.hideOnComplete` property lets you optionally override the animation hide on complete value.
* The `PlayAnimationConfig.startFrame` property lets you optionally set the animation frame to start on.
* The `PlayAnimationConfig.timeScale` property lets you optionally set the animation time scale factor.
* `AnimationState.delayCounter` is a new property that allows you to control the delay before an animation will start playing. Only once this delay has expired, will the animation `START` events fire. Fix #4426 (thanks @bdaenen)
* `AnimationState.hasStarted` is a new boolean property that allows you to tell if the current animation has started playing, or is still waiting for a delay to expire.
* `AnimationState.showOnStart` is a new boolean property that controls if the Game Object should have `setVisible(true)` called on it when the animation starts.
* `AnimationState.hideOnComplete` is a new boolean property that controls if the Game Object should have `setVisible(false)` called on it when the animation completes.
* The `AnimationState.chain` method docs said it would remove all pending animations if called with no parameters. However, it didn't - and now does!
* The `AnimationState.setDelay` method has been removed. It never actually worked and you can now perform the same thing by calling either `playAfterDelay` or setting the `delay` property in the play config.
* The `AnimationState.getDelay` method has been removed. You can now read the `delay` property directly.
* The `AnimationState.setRepeat` method has been removed. You can achieve the same thing by setting the `repeat` property in the play config, or adjusting the public `repeatCounter` property if the animation has started.
* `AnimationState.handleStart` is a new internal private method that handles the animation start process.
* `AnimationState.handleRepeat` is a new internal private method that handles the animation repeat process.
* `AnimationState.handleStop` is a new internal private method that handles the animation stop process.
* `AnimationState.handleComplete` is a new internal private method that handles the animation complete process.
* `AnimationState.emitEvents` is a new internal private method that emits animation events, cutting down on duplicate code.
* The `AnimationState.restart` method has a new optional boolean parameter `resetRepeats` which controls if you want to reset the repeat counter during the restart, or not.
* `Animation.getTotalFrames` is a new method that will return the total number of frames in the animation. You can access it via `this.anims.currentAnim.getTotalFrames` from a Sprite.
* `Animation.calculateDuration` is a new method that calculates the duration, frameRate and msPerFrame for a given animation target.
* The `BuildGameObjectAnimation` function now uses the `PlayAnimationConfig` object to set the values.
* `Sprite.playReverse` is a new method that allows you to play the given animation in reverse on the Sprite.
* `Sprite.playAfterDelay` is a new method that allows you to play the given animation on the Sprite after a delay.
* `Sprite.stop` is a new method that allows you to stop the current animation on the Sprite.
* `AnimationManager.load` has been removed as it's no longer required.
* `AnimationManager.staggerPlay` has been fixed so you can now pass in negative stagger values.
* `AnimationManager.staggerPlay` has a new optional boolean parameter `staggerFirst`, which allows you to either include or exclude the first child in the stagger calculations.
* The `Animation.completeAnimation` method has been removed as it's no longer required.
* The `Animation.load` method has been removed as it's no longer required.
* The `Animation.setFrame` method has been removed as it's no longer required.
* The `Animation.getFirstTick` method has no longer needs the `includeDelay` parameter, as it's handled by `AnimationState` now.
* The `Animation.getFrames` method has a new optional boolean parameter `sortFrames` which will run a numeric sort on the frame names after constructing them, if a string-based frame is given.
* `Types.Animations.Animation` has a new boolean property `sortFrames`, which lets Phaser numerically sort the generated frames.
* `AnimationState.timeScale` is a new public property that replaces the old private `_timeScale` property.
* `AnimationState.delay` is a new public property that replaces the old private `_delay` property.
* `AnimationState.repeat` is a new public property that replaces the old private `_repeat` property.
* `AnimationState.repeatDelay` is a new public property that replaces the old private `_repeatDelay` property.
* `AnimationState.yoyo` is a new public property that replaces the old private `_yoyo` property.
* `AnimationState.inReverse` is a new public property that replaces the old private `_reverse` property.
* `AnimationState.startAnimation` is a new public method that replaces the old private `_startAnimation` method.
* The `AnimationState.getProgress` method has been fixed so it will return correctly if the animation is playing in reverse.
* The `AnimationState.globalRemove` method will now always be called when an animation is removed from the global Animation Manager, not just once.
* The `AnimationState.getRepeat` method has now been removed. You can get the value from the `repeat` property.
* The `AnimationState.setRepeatDelay` method has now been removed. You can set the value using the `repeatDelay` config property, or changing it at run-time.
* `AnimationState.complete` is a new method that handles the completion in animation playback.
* The `AnimationState.setTimeScale` method has now been removed. You can set the value using the `timeScale` config property, or changing it at run-time.
* The `AnimationState.getTimeScale` method has now been removed. You can read the value using the `timeScale` property.
* The `AnimationState.getTotalFrames` method has been fixed and won't error if called when no animation is loaded.
* The `AnimationState.setYoyo` method has now been removed. You can set the value using the `yoyo` config property, or changing it at run-time.
* The `AnimationState.getYoyo` method has now been removed. You can read the value using the `yoyo` property.
* The `AnimationState.stopAfterRepeat` method now has an optional parameter `repeatCount`, so you can tell the animation to stop after a specified number of repeats, not just 1.
* When playing an animation in reverse, if it reached the first frame and had to repeat, it would then jump to the frame before the final frame and carry on, skipping out the final frame.
* The `AnimationState.updateFrame` method has now been removed. Everything is handled by `setCurrentFrame` instead, which removes one extra step out of the update process.
* `GenerateFrameNames` will now `console.warn` if the generated frame isn't present in the texture, which should help with debugging animation creation massively.
* `GenerateFrameNumbers` will now `console.warn` if the generated frame isn't present in the texture, which should help with debugging animation creation massively.
* `GenerateFrameNumbers` would include the __BASE frame by mistake in its calculations. This didn't end up in the final animation, but did cause a cache miss when building the animation.
* `GenerateFrameNumbers` can now accept the `start` and `end` parameters in reverse order, meaning you can now do `{ start: 10, end: 1 }` to create the animation in reverse.
* `GenerateFrameNames` can now accept the `start` and `end` parameters in reverse order, meaning you can now do `{ start: 10, end: 1 }` to create the animation in reverse.
### Mesh Game Object - New Features, Updates and API Changes
The Mesh Game Object has been rewritten in v3.50 with a lot of changes to make it more useful and able to handle 3D objects:
* `GameObject.Vertex` is a new micro class that encapsulates all of the data required for a single vertex, such as position, uv, color and alpha. This class is now created internally by the Mesh Game Object.
* `GameObject.Face` is a new micro class that consists of references to the three `Vertex` instances that construct the single Face.
* The Mesh constructor and `MeshFactory` signatures have changed to `scene, x, y, texture, frame, vertices, uvs, indicies, colors, alphas`. Note the way the Texture and Frame parameters now comes first. `indicies` is a new parameter added to the list. It allows you to provide indexed vertex data to create the Mesh from, where the `indicies` array holds the vertex index information. The final list of vertices is built from this index along with the provided vertices and uvs arrays. The `indicies` array is optional. If your data is not indexed, then simply pass `null` or an empty array for this parameter.
* The `Mesh` Game Object now extends the `SingleAlpha` component and the alpha value is factored into the final alpha value per vertex during rendering. This means you can now set the whole alpha across the Mesh using the standard `setAlpha` methods. But, if you wish to, you can still control the alpha on a per-vertex basis as well.
* The `Mesh` Game Object now has the Animation State Component. This allows you to create and play animations across the texture of a Mesh, something that previously wasn't possible. As a result, the Mesh now adds itself to the Update List when added to a Scene.
* `Geom.ParseObj` is a new function that will parse a triangulated Wavefront OBJ file into model data that can be consumed by the Mesh Game Object.
* `Loader.OBJFile` is a new File Loader type that can load triangulated Wavefront OBJ files, which are then parsed and stored in the OBJ Cache.
* `Mesh.hideCCW` is a new boolean property that, when enabled, tells a Face to not render if it isn't counter-clockwise. You can use this to hide backward facing Faces.
* `Mesh.addOBJ` is a new method that will add the model data from a loaded Wavefront OBJ file to a Mesh. You load it via the new `OBJFile` with a `this.load.obj` call, then you can use the key with the `addOBJ` method. This method also takes an optional scale and position parameters to control placement of the created model within the Mesh.
* `Mesh.addModel` is a new method that will add the model data to a Mesh. You can prepare the model data yourself, pull it in from a server, or get it by calling `Geom.ParseObj`, or a similar custom function. This method also takes an optional scale and position parameters to control placement of the created model within the Mesh.
* `Mesh.rotateX` is a new method that will rotate all vertices of the Mesh around the x axis, by the amount given. It then depth sorts the faces.
* `Mesh.rotateY` is a new method that will rotate all vertices of the Mesh around the y axis, by the amount given. It then depth sorts the faces.
* `Mesh.rotateZ` is a new method that will rotate all vertices of the Mesh around the z axis, by the amount given. It then depth sorts the faces.
* `Mesh.depthSort` is a new method that will run a depth sort across all Faces in the Mesh by sorting them on their average depth.
* `Mesh.addVertex` is a new method that allows you to add a new single Vertex into the Mesh.
* `Mesh.addFace` is a new method that allows you to add a new Face into the Mesh. A Face must consist of 3 Vertex instances.
* `Mesh.addVertices` is a new method that allows you to add vertices to a Mesh Game Object based on the given parameters. This allows you to modify a mesh post-creation, or populate it with data at a later stage.
* `Mesh.getFaceCount` new is a new method that will return the total number of Faces in the Mesh.
* `Mesh.getVertexCount` new is a new method that will return the total number of Vertices in the Mesh.
* `Mesh.getFace` new is a new method that will return a Face instance from the Mesh based on the given index.
* `Mesh.getFaceAt` new is a new method that will return an array of Face instances from the Mesh based on the given position. The position is checked against each Face, translated through the optional Camera and Mesh matrix. If more than one Face intersects, they will all be returned but the array will be depth sorted first, so the first element will be that closest to the camera.
* `Mesh.vertices` is now an array of `GameObject.Vertex` instances, not a Float32Array.
* `Mesh.faces` is a new array of `GameObject.Face` instances, which is populated during a call to methods like `addVertices` or `addModel`.
* `Mesh.clearVertices` is a new method that will destroy all Faces and Vertices and clear the Mesh.
* `Mesh.setDebug` is a new method that allows you to render a debug visualisation of the Mesh vertices to a Graphics Game Object. You can provide your own Graphics instance and optionally callback that is invoked during rendering. This allows you to easily visualise the vertices of your Mesh to help debug UV mapping.
* The Mesh now renders by iterating through the Faces array, not the vertices. This allows you to use Array methods such as `BringToTop` to reposition a Face, thus changing the drawing order without having to repopulate all of the vertices. Or, for a 3D model, you can now depth sort the Faces.
* The Mesh renderer will now check to see if the pipeline capacity has been exceeded for every Face added, allowing you to use Meshes with vertex counts that exceed the pipeline capacity without causing runtime errors.
* You can now supply just a single numerical value as the `colors` parameter in the constructor, factory method and `addVertices` method. If a number, instead of an array, it will be used as the color for all vertices created.
* You can now supply just a single numerical value as the `alphas` parameter in the constructor, factory method and `addVertices` method. If a number, instead of an array, it will be used as the alpha for all vertices created.
* `Mesh.debugGraphic` is a new property that holds the debug Graphics instance reference.
* `Mesh.debugCallback` is a new property that holds the debug render callback.
* `Mesh.renderDebugVerts` is a new method that acts as the default render callback for `setDebug` if none is provided.
* `Mesh.preDestroy` is a new method that will clean-up the Mesh arrays and debug references on destruction.
* The `Mesh.uv` array has been removed. All UV data is now bound in the Vertex instances.
* The `Mesh.colors` array has been removed. All color data is now bound in the Vertex instances.
* The `Mesh.alphas` array has been removed. All color data is now bound in the Vertex instances.
* The `Mesh.tintFill` property is now a `boolean` and defaults to `false`.
### Input / Mouse Updates and API Changes
* `ScaleManager.refresh` is now called when the `Game.READY` event fires. This fixes a bug where the Scale Manager would have the incorrect canvas bounds, because they were calculated before a previous canvas was removed from the DOM. Fix #4862 (thanks @dranitski)
* The Game Config property `inputMouseCapture` has been removed, as this is now split into 3 new config options:
* `inputMousePreventDefaultDown` is a new config option that allows you to control `preventDefault` calls specifically on mouse down events. Set it via `input.mouse.preventDefaultDown` in the Game Config. It defaults to `true`, the same as the previous `capture` property did.
* `inputMousePreventDefaultUp` is a new config option that allows you to control `preventDefault` calls specifically on mouse up events. Set it via `input.mouse.preventDefaultUp` in the Game Config. It defaults to `true`, the same as the previous `capture` property did.
* `inputMousePreventDefaultMove` is a new config option that allows you to control `preventDefault` calls specifically on mouse move events. Set it via `input.mouse.preventDefaultMove` in the Game Config. It defaults to `true`, the same as the previous `capture` property did.
* The `MouseManager.capture` property has been removed, as this is now split into 3 new config options (see below)
* `MouseManager.preventDefaultDown` is a new boolean property, set via the `inputMousePreventDefaultDown` config option that allows you to toggle capture of mouse down events at runtime.
* `MouseManager.preventDefaultUp` is a new boolean property, set via the `inputMousePreventDefaultUp` config option that allows you to toggle capture of mouse up events at runtime.
* `MouseManager.preventDefaultMove` is a new boolean property, set via the `inputMousePreventDefaultMove` config option that allows you to toggle capture of mouse move events at runtime.
* In the `MouseManager` the up, down and move events are no longer set as being passive if captured. Over, Out, Wheel and the Window level Down and Up events are always flagged as being passive.
* The `GamepadPlugin` will now call `refreshPads` as part of its start process. This allows you to use Gamepads across multiple Scenes, without having to wait for a connected event from each one of them. If you've already had a connected event in a previous Scene, you can now just read the pads directly via `this.input.gamepad.pad1` and similar. Fix #4890 (thanks @Sytten)
* Shutting down the Gamepad plugin (such as when sleeping a Scene) no longer calls `GamepadPlugin.disconnectAll`, but destroying it does.
* `Gamepad._created` is a new private internal property that keeps track of when the instance was created. This is compared to the navigator timestamp in the update loop to avoid event spamming. Fix #4890.
### Tint Updates and Shader Changes
Phaser has had the ability to apply an additive tint to a Game Object since the beginning, and gained 'filled tints', with and without texture alpha, in v3.11. While this was handy, it introduced a 3-way if-else condition to the shaders to handle the different modes. Plus, setting tint colors was also generating rgb order Float32 color values for each Game Object, making reading those colors back again difficult (as they'd return in BGR order).
This has all changed in 3.50, as outlined below. Tint values are now used directly in the shader and don't pass through a color conversion function first. Lots of private properties have been removed and the shaders no longer have a 3-way if-else block. All of this means improved performance and a slight reduction in memory overhead.
* `Tint.tintTopLeft` is now a normal property in RGB order, not a setter, and no longer passes through the `GetColorFromValue` function. This directly replaces the private property `_tintTL` which has now been removed.
* `Tint.tintTopRight` is now a normal property in RGB order, not a setter, and no longer passes through the `GetColorFromValue` function. This directly replaces the private property `_tintTR` which has now been removed.
* `Tint.tintBottomLeft` is now a normal property in RGB order, not a setter, and no longer passes through the `GetColorFromValue` function. This directly replaces the private property `_tintBL` which has now been removed.
* `Tint.tintBottomRight` is now a normal property in RGB order, not a setter, and no longer passes through the `GetColorFromValue` function. This directly replaces the private property `_tintBR` which has now been removed.
* The property `Tint._isTinted` has been removed as it's no longer required.
* The `Single.frag`, `Light.frag` and `Multi.frag` shaders have all been updated so they now read the color value as `outTint.bgr` instead of `outTint.rgb`. This allows the colors to remain in RGB order within the Tint component.
* The `Single.frag`, `Light.frag` and `Multi.frag` shaders have all been updated so they no longer have a 3-way check on the `outTintEffect` value.
* The `Multi Pipeline`, `Bitmap Text`, `Render Texture`, `Text`, `TileSprite` and `Camera` now all read the tint values from the public properties instead of the private `_tintTL` etc ones. They also now set the `tintEffect` value directly from the `tintFill` property, removing another conditional check.
* The function `GetColorFromValue` has been removed as it's no longer used internally.
* The `Rope.tintFill` property is now a boolean, not an integer, and can no longer take `2` as a value for a complete fill. Instead, you should provide a solid color texture with no alpha.
* As a result of the change to the shader, all uses of the WebGL Util function `getTintAppendFloatAlphaAndSwap` have been replaced with `getTintAppendFloatAlpha` instead.
* As a result of the change to the shader, the Multi Pipeline now uses the `WebGLRenderer.whiteTexture` and `tintEffect` mode of 1 by default, instead of mode 2 (which has been removed) and a transparent texture. This ensures Graphics and Shapes objects still render correctly under the new smaller shader code.
* `WebGLRenderer.whiteTexture` is a new property that is a reference to a pure white 4x4 texture that is created during Boot by the Texture Manager. The Multi Pipeline uses this internally for all Graphic, Shape and fill rendering.
* The `TextureManager` now generates a new texture with the key `__WHITE` durings its boot process. This is a pure white 4x4 texture used by the Graphics pipelines.
* `Config.images.white` is a new Game Config property that specifies the 4x4 white PNG texture used by Graphics rendering. You can override this via the config, but only do so if needed.
### Removal of 'resolution' property from across the API
For legacy reasons, Phaser 3 has never properly supported HighDPI devices. It will render happily to them of course, but wouldn't let you set a 'resolution' for the Canvas beyond 1. Earlier versions of 3.x had a resolution property in the Game Config, but it was never fully implemented (for example, it would break zooming cameras). When the Scale Manager was introduced in v3.16 we forced the resolution to be 1 to avoid it breaking anything else internally.
For a long time, the 'resolution' property has been present - taunting developers and confusing new comers. In this release we have finally gone through and removed all references to it. The Game Config option is now gone, it's removed from the Scale Manager, Base Camera and everywhere else where it matters. As much as we would have liked to implement the feature, we've spent too long without it, and things have been built around the assumption it isn't present. The API just wouldn't cope with having it shoe-horned in at this stage. As frustrating as this is, it's even more annoying to just leave the property there confusing people and wasting CPU cycles. Phaser 4 has been built with HighDPI screens in mind from the very start, but it's too late for v3. The following changes are a result of this removal:
* The `Phaser.Scale.Events#RESIZE` event no longer sends the `resolution` as a parameter.
* The `BaseCamera.resolution` property has been removed.
* The internal private `BaseCamera._cx`, `_cy`, `_cw` and `_ch` properties has been removed.
* The `BaseCamera.preRender` method no longer receives or uses the `resolution` parameter.
* The `Camera.preRender` method no longer receives or uses the `resolution` parameter.
* The `CameraManager.onResize` method no longer receives or uses the `resolution` parameter.
* The `Core.Config.resolution` property has been removed.
* The `TextStyle.resolution` property is no longer read from the Game Config. You can still set it via the Text Style config to a value other than 1, but it will default to this now.
* The `CanvasRenderer` no longer reads or uses the Game Config resolution property.
* The `PipelineManager.resize` method along with `WebGLPipeline.resize` and anything else that extends them no longer receives or uses the `resolution` parameter.
* The `WebGLRenderer.resize` and `onResize` methods no longer receives or uses the `resolution` parameter.
* The `ScaleManager.resolution` property has been removed and all internal use of it.
### Removed 'interpolationPercentage' parameter from all render functions
Since v3.0.0 the Game Object `render` functions have received a parameter called `interpolationPercentage` that was never used. The renderers do not calculate this value and no Game Objects apply it, so for the sake of clairty, reducing code and removing complexity from the API it has been removed from every single function that either sent or expected the parameter. This touches every single Game Object and changes the parameter order as a result, so please be aware of this if you have your own _custom_ Game Objects that implement their own `render` methods. In terms of surface API changes, you shouldn't notice anything at all from this removal.
### New Features
* `Geom.Intersects.GetLineToLine` is a new function that will return a Vector3 containing the point of intersection between 2 line segments, with the `z` property holding the distance value.
* `Geom.Intersects.GetLineToPolygon` is a new function that checks for the closest point of intersection between a line segment and an array of polygons.
* `Geom.Intersects.GetLineToPoints` is a new function that checks for the closest point of intersection between a line segment and an array of points, where each pair of points form a line segment.
* `Geom.Intersects.GetRaysFromPointToPolygon` is a new function that emits rays out from the given point and detects for intersection against all given polygons, returning the points of intersection in the results array.
* `Geom.Polygon.Translate` is a new function that allows you to translate all the points of a polygon by the given values.
* `Geom.Polygon.Simplify` is a new function that takes a polygon and simplifies the points by running them through a combination of Douglas-Peucker and Radial Distance algorithms, potentially dramatically reducing the number of points while retaining its shape.
* `WebGLRenderer.setInt1iv` will allow you to look-up and set a 1iv uniform on the given shader.
* `Phaser.Types.Math.Vector3Like` is a new data type representing as Vector 3 like object.
* `Phaser.Types.Math.Vector4Like` is a new data type representing as Vector 4 like object.
* `Transform.getLocalPoint` is a new method, available on all Game Objects, that takes an `x` / `y` pair and translates them into the local space of the Game Object, factoring in parent transforms and display origins.
* The `KeyboardPlugin` will now track the key code and timestamp of the previous key pressed and compare it to the current event. If they match, it will skip the event. On some systems, if you were to type quickly, you would sometimes get duplicate key events firing (the exact same event firing more than once). This is now prevented from happening.
* `Display.Color.GetColorFromValue` is a new function that will take a hex color value and return it as an integer, for use in WebGL. This is now used internally by the Tint component and other classes.
* `Utils.String.RemoveAt` is a new function that will remove a character from the given index in a string and return the new string.
* `Frame.setUVs` is a new method that allows you to directly set the canvas and UV data for a frame. Use this if you need to override the values set automatically during frame creation.
* `TweenManager.getTweensOf` has a new parameter `includePending`. If set, it will also check the pending tweens for the given targets and return those in the results as well. Fix #5260 (thanks @pcharest2000)
* `WebGLPipeline.hasBooted` is a new boolean property that tracks if the pipeline has been booted or not, which is now far more important in 3.5 than in previous versions. This is checked in the `WebGLRenderer.addPipeline` method, and if not set, the pipeline is booted. Fix #5251 #5255 (thanks @telinc1 @rexrainbow)
* The WebGL Renderer will now add the pipelines during the `boot` method, instead of `init`.
* You can now use `this.renderer` from within a Scene, as it's now a Scene-level property and part of the Injection Map.
* `Clock.addEvent` can now take an existing `TimerEvent` object, as well as a config object. If a `TimerEvent` is given it will be removed from the Clock, reset and then added. This allows you to pool TimerEvents rather than constantly create and delete them. Fix #4115 (thanks @jcyuan)
* `Clock.removeEvent` is a new method that allows you to remove a `TimerEvent`, or an array of them, from all internal lists of the current Clock.
* `Group.getMatching` is a new method that will return any members of the Group that match the given criteria, such as `getMatching('visible', true)` (thanks @atursams)
* `ArcadePhysics.disableUpdate` is a new method that will prevent the Arcade Physics World `update` method from being called when the Scene updates. By disabling it, you're free to call the update method yourself, passing in your own delta and time values.
* `ArcadePhysics.enableUpdate` is a new method that will make the Arcade Physics World update in time with the Scene update. This is the default, so only call this if you have specifically disabled it previously.
* `ArcadeWorldConfig.customUpdate` is a new boolean property you can set in the Arcade Physics config object, either in the Scene or in the Game Config. If `true` the World update will never be called, allowing you to call it yourself from your own component. Close #5190 (thanks @cfortuner)
* `Utils.Array.SortByDigits` is a new function that takes the given array of strings and runs a numeric sort on it, ignoring any non-digits.
* `GroupCreateConfig`, which is used when calling `Group.createMultiple` or `Group.createFromConfig`, can now accept the following new properties: `setOrigin: { x, y, stepX, stepY }` which are applied to the items created by the Group.
* `Transform.copyPosition` is a new method that will copy the position from the given object to the Game Object (thanks @samme)
* The `Text.MeasureText` function, which is used to calculate the ascent and descent of Text Game Objects whenever the style, or font size, is changed, has been updated to use the new `actualBoundingBoxAscent` functions present in modern browsers. This allows for significantly faster ascent calculations than previously. Older browsers, such as IE, will still fall back (thanks @rexrainbow)
* `GameObjects.GetCalcMatrix` is a new function that is used to calculate the transformed Game Object matrix, based on the given Game Object, Camera and Parent. This function is now used by the following Game Objects: `BitmapText` (Static and Dynamic), `Graphics`, `Extern`, `Mesh`, `Rope`, `Shader`, `Arc`, `Curve`, `Ellipse`, `Grid`, `IsoBox`, `IsoTriangle`, `Line`, `Polygon`, `Rectangle`, `Star` and `Triangle`. This dramatically reduces the amount of duplicate code across the API.
* `Utils.Array.Matrix.Translate` is a new function that will translate an Array Matrix by horizontally and vertically by the given amounts.
* `Vertor3.addScale` is a new method that will add the given vector and multiply it in the process.
### Updates and API Changes
* Earcut, used for polygon triangulation, has been updated from 2.1.4 to 2.2.2.
* Earcut has now been exposed and is available via `Geom.Polygon.Earcut` and is fully documented.
* `Config.batchSize` has been increased from 2000 to 4096.
* Removed the Deferred Diffuse fragment and vertex shaders from the project, as they're not used.
* `StaticTilemapLayer.upload` will now set the vertex attributes and buffer the data, and handles internal checks more efficiently.
* `StaticTilemapLayer` now includes the `ModelViewProjection` mixin, so it doesn't need to modify the pipeline during rendering.
* `WebGLRenderer.textureFlush` is a new property that keeps track of the total texture flushes per frame.
* The `TextureTintStripPipeline` now extends `TextureTintPipeline` and just changes the topolgy, vastly reducing the filesize.
* `TransformMatrix.getXRound` is a new method that will return the X component, optionally passed via `Math.round`.
* `TransformMatrix.getYRound` is a new method that will return the Y component, optionally passed via `Math.round`.
* The `KeyboardPlugin` no longer emits `keydown_` events. These were replaced with `keydown-` events in v3.15. The previous event string was deprecated in v3.20.
* The `KeyboardPlugin` no longer emits `keyup_` events. These were replaced with `keyup-` events in v3.15. The previous event string was deprecated in v3.20.
* The `ScaleManager.updateBounds` method is now called every time the browser fires a 'resize' or 'orientationchange' event. This will update the offset of the canvas element Phaser is rendering to, which is responsible for keeping input positions correct. However, if you change the canvas position, or visibility, via any other method (i.e. via an Angular route) you should call the `updateBounds` method directly, yourself.
* The constant `Phaser.Renderer.WebGL.BYTE` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.SHORT` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.UNSIGNED_BYTE` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.UNSIGNED_SHORT` value has been removed as it wasn't used internally.
* The constant `Phaser.Renderer.WebGL.FLOAT` value has been removed as it wasn't used internally.
* `global.Phaser = Phaser` has been removed, as it's no longer required by the UMD loader, which should make importing in Angular 10 easier. Fix #5212 (thanks @blackyale)
* `Pointer.downTime` now stores the event timestamp of when the first button on the input device was pressed down, not just when button 1 was pressed down.
* `Pointer.upTime` now stores the event timestamp of when the final depressed button on the input device was released, not just when button 1 was released.
* The `Pointer.getDuration` method now uses the new Pointer `downTime` and `upTime` values, meaning it will accurately report the duration of when any button is being held down, not just the primary one. Fix #5112 (thanks @veleek)
* The `BaseShader` default vertex shader now includes the `outTexCoord` vec2 varying, mapped to be the same as that found in the pipeline shaders. Fix #5120 (@pavel-shirobok)
* When using the `GameObjectCreator` for `Containers` you can now specify the `children` property in the configuration object.
* `WebGLRenderer.finalType` is a new boolean property that signifies if the current Game Object being rendered is the final one in the list.
* The `WebGLRenderer.updateCanvasTexture` method will now set `gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL` to true, which should stop issues where you update a Text Game Object, having added a Render Texture or Spine Game Object to the Scene after it, which switches the PMA setting. Fix #5064 #5155 (thanks @hugoruscitti @immangrove-supertree)
* `Textures.Parsers.JSONHash` will now perform a `hasOwnProperty` check when iterating the frames, skipping anything that isn't a direct property. This should allow you to use generated atlas data that comes from `JSON.parse`. Fix #4768 (thanks @RollinSafary)
* The `Camera3D` Plugin has been rebuilt for Phaser 3.50 and the webpack config updated. This plugin is now considered deprecated and will not be updated beyond this release.
* `Tween.seek` will no longer issue a console warning for `'Tween.seek duration too long'`, it's now up to you to check on the performance of tween seeking.
* `WebGLRenderer.previousPipeline` is a new property that is set during a call to `clearPipeline` and used during calls to `rebindPipeline`, allowing the renderer to rebind any previous pipeline, not just the Multi Pipeline.
* The `WebGLRenderer.rebindPipeline` method has been changed slightly. Previously, you had to specify the `pipelineInstance`, but this is now optional. If you don't, it will use the new `previousPipeline` property instead. If not set, or none given, it will now return without throwing gl errors as well.
* If `inputWindowEvents` is set in the Game Config, then the `MouseManager` will now listen for the events on `window.top` instead of just `window`, which should help in situations where the pointer is released outside of an embedded iframe. Fix #4824 (thanks @rexrainbow)
* `Types.GameObjects.Text.GetTextSizeObject` is a new type def for the GetTextSize function results.
* The `Arcade.Body.resetFlags` method has a new optional boolean parameter `clear`. If set, it clears the `wasTouching` flags on the Body. This happens automatically when `Body.reset` is called. Previous to this, the flags were not reset until the next physics step (thanks @samme)
* `Utils.Array.StableSort` has been recoded. It's now based on Two-Screens stable sort 0.1.8 and has been updated to fit into Phaser better and no longer create any window bound objects. The `inplace` function has been removed, just call `StableSort(array)` directly now. All classes that used `StableSort.inplace` have been updated to call it directly.
* If a Scene is paused, or sent to sleep, it will automatically call `Keyboard.resetKeys`. This means that if you hold a key down, then sleep or pause a Scene, then release the key and resume or wake the Scene, it will no longer think it is still being held down (thanks @samme)
* `Actions.setOrigin` will now call `updateDisplayOrigin` on the items array, otherwise the effects can't be seen when rendering.
* You can now set the `ArcadeWorld.fixedStep` property via the `ArcadeWorldConfig` object (thanks @samme)
* `Utils.Array.NumerArray` can now accept the `start` and `end` parameters in reverse order, i.e. `10, 1` will generate a number array running from 10 to 1. Internally it has also been optimized to skip string based returns.
* `DataManager.Events.DESTROY` is a new event that the Data Manager will _listen_ for from its parent and then call its own `destroy` method when received.
### Bug Fixes
* `RenderTexture.resize` (which is called from `setSize`) wouldn't correctly set the `TextureSource.glTexture` property, leading to `bindTexture: attempt to use a deleted object` errors under WebGL.
* `RenderTexture.fill` would fail to fill the correct area under WebGL if the RenderTexture wasn't the same size as the Canvas. It now fills the given region properly.
* The `MatterAttractors` plugin, which enables attractors between bodies, has been fixed. The original plugin only worked if the body with the attractor was _first_ in the world bodies list. It can now attract any body, no matter where in the world list it is. Fix #5160 (thanks @strahius)
* The `KeyboardManager` and `KeyboardPlugin` were both still checking for the `InputManager.useQueue` property, which was removed several versions ago.
* In Arcade Physics, Dynamic bodies would no longer hit walls when riding on horizontally moving platforms. The horizontal (and vertical) friction is now re-applied correctly in these edge-cases. Fix #5210 (thanks @Dercetech @samme)
* Calling `Rectangle.setSize()` wouldn't change the underlying geometry of the Shape Game Object, causing any stroke to be incorrectly rendered after a size change.
* The `ProcessQueue` was emitting the wrong events internally. It now emits 'add' and 'remove' correctly (thanks @halilcakar)
* The `GridAlign` action didn't work if only the `height` parameter was set. Fix #5019 (thanks @halilcakar)
* The `Color.HSVToRGB` function has been rewritten to use the HSL and HSV formula from Wikipedia, giving much better results. Fix #5089 (thanks @DiamondeX)
* Previously, the `easeParams` array within a Tweens `props` object, or a multi-object tween, were ignored and it was only used if set on the root Tween object. It will now work correctly set at any depth. Fix #4292 (thanks @willblackmore)
* When using `Camera.setRenderToTexture` its `zoom` and `rotation` values would be applied twice. Fix #4221 #4924 #4713 (thanks @wayfu @DanMcgraw @pavel-shirobok)
* `GameObjects.Shape.Grid` would render a white fill even if you passed `undefined` as the fill color in the constructor. It now doesn't render cells if no fill color is given.
* The `onMouse` events in the Input Manager didn't reset the `activePointer` property to the mouse, meaning on dual-input systems such as Touch Screen devices, the active pointer would become locked to whichever input method was used first. Fix #4615 #5232 (thanks @mmolina01 @JstnPwll @Legomite)
* The Scale Managers `GetScreenOrientation` function will now check for `window.orientation` first, because iOS mobile browsers have an incomplete implementation of the Screen API, forcing us to use the window value as a priority. This means the Scale Manager will now emit `orientationchange` events correctly on iOS. Fix #4361 #4914 (thanks @pfdtravalmatic @jackfreak @cuihu)
* `Time.Clock.addEvent` can now take an instance of a `TimerEvent` as its parameter. Fix #5294 (thanks @samme @EmilSV)
* `GameConfig.audio` now defaults to an empty object, which simplifies access to the config in later checks (thanks @samme)
* The `Loader.path` was being added to the File URL even if the URL was absolute. This is now checked for and the path is not applied unless the URL is relative (thanks @firesoft)
### Namespace Updates
* The `Phaser.Curves.MoveTo` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.DOM.GetInnerHeight` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.Bob` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.LightsManager` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.LightsPlugin` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.Particles.EmitterOp` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.GetTextSize` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.MeasureText` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.GameObjects.TextStyle` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Input.CreatePixelPerfectHandler` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Arcade.Components.OverlapCirc` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Arcade.Components.OverlapRect` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Arcade.Tilemap` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.Components` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.Events` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.MatterGameObject` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Physics.Matter.PointerConstraint` class has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Scenes.GetPhysicsPlugins` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Scenes.GetScenePlugins` function has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Structs.Events` namespace has now been exposed on the Phaser namespace (thanks @samme)
* The `Phaser.Tilemaps.Parsers.Tiled` function has now been exposed on the Phaser namespace (thanks @samme)
* Every single `Tilemap.Component` function has now been made public. This means you can call the Component functions directly, should you need to, outside of the Tilemap system.
### 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:
@samme @16patsle @scott20145 @khasanovbi @mk360 @volkans80 @jaabberwocky @maikthomas @atursams @LearningCode2023 @DylanC @BenjaminDRichards @rexrainbow @Riderrr @spwilson2 @EmilSV @PhaserEditor2D

11431
CHANGELOG.md

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018 Richard Davey, Photon Storm Ltd.
Copyright (c) 2020 Richard Davey, Photon Storm Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

810
README.md
View file

@ -1,405 +1,405 @@
# Phaser - HTML5 Game Framework
![Phaser Header](https://phaser.io/images/github/300/phaser-header.png "Phaser 3 Header Banner")
[![Discord chat](https://img.shields.io/discord/244245946873937922?style=for-the-badge)](https://discord.gg/phaser)
[![Twitter Follow](https://img.shields.io/twitter/follow/phaser_?style=for-the-badge)](https://twitter.com/phaser_)
![GitHub All Releases](https://img.shields.io/github/downloads/photonstorm/phaser/total?style=for-the-badge)
![npm](https://img.shields.io/npm/dy/phaser?label=npm&style=for-the-badge)
Phaser is a fast, free, and fun open source HTML5 game framework that offers WebGL and Canvas rendering across desktop and mobile web browsers. Games can be compiled to iOS, Android and native apps by using 3rd party tools. You can use JavaScript or TypeScript for development.
Along with the fantastic open source community, Phaser is actively developed and maintained by [Photon Storm](http://www.photonstorm.com). As a result of rapid support, and a developer friendly API, Phaser is currently one of the [most starred](https://github.com/collections/javascript-game-engines) game frameworks on GitHub.
Thousands of developers from indie and multi-national digital agencies, and universities worldwide use Phaser. You can take a look at their incredible [games](https://phaser.io/games/).
**Visit:** The [Phaser website](https://phaser.io) and follow on [Twitter](https://twitter.com/phaser_) (#phaserjs)<br />
**Learn:** [API Docs](https://photonstorm.github.io/phaser3-docs/index.html), [Support Forum][forum] and [StackOverflow](https://stackoverflow.com/questions/tagged/phaser-framework)<br />
**Code:** 1700+ [Examples](https://phaser.io/examples) (source available in this [repo][examples])<br />
**Read:** The [Phaser World](#newsletter) Newsletter<br />
**Discord:** Join us on [Discord](https://phaser.io/community/discord)<br />
**Extend:** With [Phaser Plugins](https://phaser.io/shop/plugins)<br />
**Be awesome:** [Support](#support) the future of Phaser<br />
Grab the source and join the fun!
![What's New](https://phaser.io/images/github/div-whats-new.png "What's New")
<div align="center"><img src="https://phaser.io/images/github/news.jpg"></div>
> 13th July 2020
I'm pleased to announce the immediate availability of Phaser 3.24. This release is primarily a maintenance release, with the focus mostly on bug fixes and updates. Even so, there are over 70 updates in this version alone. From improvements to the Arcade Physics system, to new Tween events and the ability to chain multiple animations, to some important fixes. If you're currently using 3.23 then we recommend this upgrade. As usual, I'd like to send my thanks to the Phaser community for their help in both reporting issues and submitting pull requests to fix them.
So, please do spend some time digging through the [Change Log](#changelog). I assure you, it's worth while :)
I'd like to send a massive thank-you to everyone who supports [Phaser on Patreon](https://www.patreon.com/photonstorm) (and now even GitHub Sponsors, too!) Your continued backing keeps allowing me to work on Phaser full-time and this great new releases is the very real result of that. If you've ever considered becoming a backer, now is the perfect time!
As well as all of these updates, development has been progressing rapidly on Phaser 4. If you'd like to stay abreast of developments then I'm now publishing them to the [Phaser Patreon](https://www.patreon.com/photonstorm). Here you can find details about the latest developments and concepts behind Phaser 4.
You can also follow Phaser on [Twitter](https://twitter.com/phaser_) and chat with fellow Phaser devs in our [Discord](https://phaser.io/community/discord).
Phaser 3 wouldn't have been possible without the fantastic support of the community and Patreon. Thank you to everyone who supports our work, who shares our belief in the future of HTML5 gaming, and Phaser's role in that.
Happy coding everyone!
Cheers,
Rich - [@photonstorm](https://twitter.com/photonstorm)
![boogie](https://www.phaser.io/images/spacedancer.gif)
![Support Phaser](https://phaser.io/images/github/div-support-phaser.png "Support Phaser")
Because Phaser is an open source project, we cannot charge for it in the same way as traditional retail software. What's more, we don't ever want to. After all, it's built on, and was born from, open web standards. It's part of our manifesto that the core framework will always be free, even if you use it commercially, as many of you do.
**You may not realize it, but because of this, we rely 100% on community backing to fund development.**
Those funds allow Phaser to improve, and when it improves, everyone involved benefits. Your support helps secure a constant cycle of updates, fixes, new features and planning for the future.
There are other benefits to [backing Phaser](https://www.patreon.com/join/photonstorm), too:
![Backers Perks](https://phaser.io/images/github/patreon-perk-chart.png)
We use [Patreon](https://www.patreon.com/photonstorm) to manage the backing and you can [support Phaser](https://www.patreon.com/join/photonstorm?) from $1 per month. The amount you pledge is entirely up to you and can be changed as often as you like. Patreon renews monthly, just like Netflix. You can, of course, cancel at any point. Tears will be shed on this end, but that's not your concern.
Extra special thanks to the following companies who's support makes Phaser possible:
* [Cerebral Fix](https://cerebralfix.com)
* [CrossInstall](https://crossinstall.com)
* [Facebook](https://www.facebook.com)
* [Game Distribution](https://gamedistribution.com)
* [GameCommerce](https://www.gamecommerce.com)
* [Mozilla](https://www.mozilla.org)
* [Texture Packer](https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3?utm_source=ad&utm_medium=banner&utm_campaign=phaser-2018-10-16)
* [Twilio](https://www.twilio.com)
* [Poki](https://developers.poki.com/)
* [CrazyGames](https://www.crazygames.com)
* [Lagged](https://www.lagged.com)
![Sponsors](https://phaser.io/images/github/sponsors-2020-06.png "Our Awesome Sponsors")
![Download Phaser](https://phaser.io/images/github/div-download.png "Download Phaser")
<a name="download"></a>
Phaser 3 is available via GitHub, npm and CDNs:
* Clone the git repository via [https][clone-http], [ssh][clone-ssh] or with the GitHub [Windows][clone-ghwin] or [Mac][clone-ghmac] clients.
* Download as [zip](https://github.com/photonstorm/phaser/archive/master.zip)
* Download the build files: [phaser.js][get-js] and [phaser.min.js][get-minjs]
### NPM
Install via [npm](https://www.npmjs.com):
```bash
npm install phaser
```
### CDN
[![](https://data.jsdelivr.com/v1/package/gh/photonstorm/phaser/badge)](https://www.jsdelivr.com/package/gh/photonstorm/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.24.0/dist/phaser.js"></script>
```
or the minified version:
```html
<script src="//cdn.jsdelivr.net/npm/phaser@3.24.0/dist/phaser.min.js"></script>
```
### API Documentation
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 namespaces, 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.
### TypeScript Definitions
The [TypeScript definitions](https://github.com/photonstorm/phaser/tree/master/types) can be found inside the `types` folder. They are also referenced in the types entry in `package.json`.
Depending on your project, you may need to add the following to your `tsconfig.json` file:
```json
"typeRoots": [
"./node_modules/phaser/types"
],
"types": [
"Phaser"
]
```
We recently published a new [Phaser 3 TypeScript Project Template](https://github.com/photonstorm/phaser3-typescript-project-template), which you can use to get started with if you like.
The TS defs are automatically generated from the JSDoc comments found in the Phaser source code. If you wish to help refine them then you must edit the Phaser JSDoc blocks directly, not the defs file. You can find more details about the parser we built in the `scripts/tsgen` folder.
### 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 use any other packager, like Parcel, without any config changes.
### License
Phaser is released under the [MIT License](https://opensource.org/licenses/MIT).
![Getting Started](https://phaser.io/images/github/div-getting-started.png "Getting Started")
<a name="getting-started"></a>
<img src="https://phaser.io/images/github/learn.jpg" align="right">
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)
* 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.
We've 3 tutorials related specifically to creating **Facebook Instant Games** with 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)
### Source Code Examples
During our development of Phaser 3, we created hundreds of examples with the full source code and assets ready available. These examples are now fully integrated into the [Phaser website](https://phaser.io/examples). You can also browse them on [Phaser 3 Labs](https://labs.phaser.io) via a more advanced interface, or clone the [examples repo][examples]. We are constantly adding to and refining these examples.
### Huge list of Phaser 3 Plugins
Super community member RexRainbow has been publishing Phaser 3 content for years, building up an impressive catalogue in that time. You'll find [loads of plugins](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/index.html#list-of-my-plugins), from UI controls such as text input boxes, to Firebase support, Finite State Machines and lots more. As well as the plugins there is also a comprehensive set of 'Notes' about Phaser 3, going into great detail about how the various systems work. It's an invaluable resource and well worth checking out at [https://rexrainbow.github.io](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/index.html)
### Create Your First Phaser 3 Example
Create an `index.html` page locally and paste the following code into it:
```html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.24.0/dist/phaser-arcade-physics.min.js"></script>
</head>
<body>
<script></script>
</body>
</html>
```
This is a standard empty webpage. You'll notice there's a script tag that is pulling in a build of Phaser 3, but otherwise this webpage doesn't do anything yet. Now let's set-up the game config. Paste the following between the `<script></script>` tags:
```javascript
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 200 }
}
},
scene: {
preload: preload,
create: create
}
};
```
`config` is a pretty standard Phaser 3 Game Configuration object. We tell `config` to use the WebGL renderer if it can, set the canvas to a size of 800x600 pixels, enable Arcade Physics, and finally call the `preload` and `create` functions. `preload` and `create` have not been implemented yet, so if you run this JavaScript code, you will have an error. Add the following after `config`:
```javascript
var game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('http://labs.phaser.io');
this.load.image('sky', 'assets/skies/space3.png');
this.load.image('logo', 'assets/sprites/phaser3-logo.png');
this.load.image('red', 'assets/particles/red.png');
}
function create ()
{
}
```
`game` is a Phaser Game instance that uses our configuration object `config`. We also add function definitions for `preload` and `create`. The `preload` function helps you easily load assets into your game. In `preload`, we set the Base URL to be the Phaser server and load 3 PNG files.
The `create` function is empty, so it's time to fill it in:
```javascript
function create ()
{
this.add.image(400, 300, 'sky');
var particles = this.add.particles('red');
var emitter = particles.createEmitter({
speed: 100,
scale: { start: 1, end: 0 },
blendMode: 'ADD'
});
var logo = this.physics.add.image(400, 100, 'logo');
logo.setVelocity(100, 200);
logo.setBounce(1, 1);
logo.setCollideWorldBounds(true);
emitter.startFollow(logo);
}
```
Here we add a sky image into the game and create a Particle Emitter. The `scale` value means that the particles will initially be large and will shrink to nothing as their lifespan progresses.
After creating the `emitter`, we add a logo image called `logo`. Since `logo` is a Physics Image, `logo` is given a physics body by default. We set some properties for `logo`: velocity, bounce (or restitution), and collision with the world bounds. These properties will make our logo bounce around the screen. Finally, we tell the particle emitter to follow the logo - so as the logo moves, the particles will flow from it.
Run it in your browser and you'll see the following:
![Phaser 3 Demo](https://phaser.io/images/github/300/sample1.png "Phaser 3 Demo")
(Got an error? Here's the [full code](https://gist.github.com/photonstorm/46cb8fb4b19fc7717dcad514cdcec064))
This is a tiny example, and there are hundreds more for you to explore, but hopefully it shows how expressive and quick Phaser is to use. With just a few easily readable lines of code, we've got something pretty impressive up on screen!
![Ourcade](https://phaser.io/images/github/ourcade.jpg "Ourcade")
Ourcade have published [two great Phaser 3 books](https://blog.ourcade.co/). They'll take you from getting set-up, through to finishing your first game using modern JavaScript or TypeScript and they're both completely free! They also publish a huge range of quality tutorials and videos, so be sure to check out their site every week.
![Building Phaser](https://phaser.io/images/github/div-building-phaser.png "Building Phaser")
There are both plain and minified compiled versions of Phaser in the `dist` folder of the repository. The plain version is for use during development, and the minified version is for production use. You can also create your own builds.
### 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 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` 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`.
![Change Log](https://phaser.io/images/github/div-change-log.png "Change Log")
<a name="changelog"></a>
# Change Log
## Version 3.24 - Rem - 13th July 2020
### Arcade Physics New Features, Updates and Fixes
* When colliding physics groups with the search tree enabled, there was an unnecessary intersection test for each body returned by the search (thanks @samme)
* When doing an overlap collision, there was an unnecessary intersection test for each pair of overlapping bodies (thanks @samme)
* Sprite vs. Static Group collision tests now always use the static tree (thanks @samme)
* Fixed a bug where if you added a static body to a sprite with scale ≠ 1, the body position was incorrect (thanks @samme)
* If you passed in an array of `children` when creating a Physics Group, they didn't receive bodies. Fix #5152 (thanks @samme)
* New types allow for better docs / TypeScript defs especially in the Factory functions: `ArcadePhysicsCallback`, `GameObjectWithBody`, `GameObjectWithDynamicBody`, `GameObjectWithStaticBody`, `ImageWithDynamicBody`, `ImageWithStaticBody`, `SpriteWithDynamicBody` and `SpriteWithStaticBody`. Fix #4994 (thanks @samme @gnesher)
* `Body.updateFromGameObject` is a new method that extracts the relevant code from `preUpdate`, allowing you to read the body's new position and center immediately, before the next physics step. It also lets `refreshBody` work for dynamic bodies, where previously it would error (thanks @samme)
* Momentum exchange wasn't working correctly vs. immovable bodies. The movable body tended to stop. Fix #4770 (thanks @samme)
* The Body mass was decreasing the inertia instead of increasing it. Fix #4770 (thanks @samme)
* The separation vector seemed to be incorrect, causing the slip / slide collisions. The separation is now correct for circlecircle collisions (although not fully for circlerectangle collisions), part fix #4770 (thanks @samme)
* The Arcade Body delta was incorrectly calculated on bodies created during the `update` step, causing the position to be off. Fix #5204 (thanks @zackexplosion @samme)
* `Arcade.Components.Size.setBodySize` is a new method available on Arcade Physics Game Objects that allows you to set the body size. This replaces `setSize` which is now deprecated. Fix #4786 (thanks @wingyplus)
### New Features
* The Animation component has a new property `nextAnimsQueue` which allows you to sequence Sprite animations to play in order, i.e: `this.mole.anims.play('digging').anims.chain('lifting').anims.chain('looking').anims.chain('lowering');` (thanks @tgroborsch)
* `Group.setActive` is a new method that will set the active state of a Group, just like it does on other Game Objects (thanks @samme)
* `Group.setName` is a new method that will set the name property of a Group, just like it does on other Game Objects (thanks @samme)
* `TWEEN_STOP` is a new event dispatched by a Tween when it stops playback (thanks @samme @RollinSafary)
* You can now specify an `onStop` callback when creating a Tween as part of the tween config, which is invoked when a Tween stops playback (thanks @samme @RollinSafary)
* Previously, if you created a timeline and passed no tweens in the config, the timeline would be created but all config properties were ignored. Now the timeline's own properties (completeDelay, loop, loopDelay, useFrames, onStart, onUpdate, onLoop, onYoyo, onComplete, etc.) are set from the config properly (thanks @samme)
* `TextStyle.wordWrapWidth` lets you set the maximum width of a line of text (thanks @mikewesthad)
* `TextStyle.wordWrapCallback` is a custom function that will is responsible for wrapping the text (thanks @mikewesthad)
* `TextStyle.wordWrapCallbackScope` is the scope that will be applied when the `wordWrapCallback` is invoked (thanks @mikewesthad)
* `TextStyle.wordWrapUseAdvanced` controls whether or not to use the advanced wrapping algorithm (thanks @mikewesthad)
* `KeyboardPlugin.removeAllKeys` is a new method that allows you to automatically remove all Key instances that the plugin has created, making house-keeping a little easier (thanks @samme)
* `Math.RotateTo` is a new function that will position a point at the given angle and distance (thanks @samme)
* `Display.Bounds.GetBounds` is a new function that will return the un-transformed bounds of the given Game Object as a Rectangle (thanks @samme)
### Updates
* The `Pointer.dragStartX/YGlobal` and `Pointer.dragX/Y` values are now populated from the `worldX/Y`, which means using those values directly in Input Drag callbacks will now work when the Camera is zoomed. Fix #4755 (thanks @braindx)
* The `browser` field has been added to the Phaser `package.json` pointing to the `dist/phaser.js` umd build (thanks @FredKSchott)
* Calling `TimeStep.wake()` while the loop is running will now cause nothing to happen, rather than sleeping and then waking again (thanks @samme)
* `Container.getBounds` will no longer set the temp rect bounds to the first child of the Container by default (which would error if the child had no bounds, like a Graphics object) and instead sets it as it iterates the children (thanks @blopa)
* `File.state` will now be set to the `FILE_LOADING` state while loading and `FILE_LOADED` after loading (thanks @samme)
* `BaseCamera.cull` now moves some of its calculations outside of the cull loop to speed it up (thanks @samme)
* `SceneManager.createSceneFromInstance` had a small refactor to avoid a pointless condition (thanks @samme)
### Bug Fixes
* Fixed a TypeError warning when importing JSON objects directly to the `url` argument of any of the Loader filetypes. Fix #5189 (thanks @awweather @samme)
* The `NOOP` function was incorrectly imported by the Mouse and Keyboard Manager. Fix #5170 (thanks @samme @gregolai)
* When Audio files failed to decode on loading, they would always show 'undefined' as the key in the error log, now they show the actual key (thanks @samme)
* When the Sprite Sheet parser results in zero frames, the warning will now tell you the texture name that caused it (thanks @samme)
* `KeyboardPlugin.checkDown` didn't set the `duration` to zero if the parameter was omitted, causing it to always return false. Fix #5146 (thanks @lozzajp)
* If you passed in an array of `children` when creating a Group, they were not added and removed correctly. Fix #5151 (thanks @samme)
* When using HTML5 Audio with `pauseOnBlur` (the default), if you play a sound, schedule stopping the sound (e.g., timer, tween complete callback), leave the page, and return to the page, the sound `stop()` will error (thanks @samme)
* Using a Render Texture when you're also using the headless renderer would cause an error (thanks @samme)
* `Ellipse.setWidth` would incorrectly set the `xRadius` to the diameter (thanks @rexrainbow)
* `Ellipse.setHeight` would incorrectly set the `yRadius` to the diameter (thanks @rexrainbow)
* When specifically setting the `parent` property in the Game Config to `null` the canvas was appended to the document body, when it should have been ignored (allowing you to add it to the dom directly). Fix #5191 (thanks @MerganThePirate)
* Containers will now apply nested masks correctly when using the Canvas Renderer specifically (thanks @scott20145)
* Calling `Scale.startFullScreen` would fail in Safari on Mac OS, throwing a `fullscreenfailed` error. It now triggers fullscreen mode correctly, as on other browsers. Fix #5143 (thanks @samme @novaknole)
* Calling `setCrop` on a Matter Physics Sprite would throw a TypeError, but will now crop correctly. Not that it only crops the texture, the body is unaffected. Fix #5211 (thanks @MatthewRorke @samme)
* The Static Tilemap Layer would ignore the layer rotation and parent transform when using WebGL (but worked in Canvas). Both modes now work in the same manner (thanks @cruzdanilo)
* Calling `getTextBounds` on a BitmapText object would return the incorrect values if the origin had been changed, but the text itself had not, as it was using out of date dimensions. Changing the origin now automatically triggers BitmapText to be dirty, forcing the bounds to be refreshed. Fix #5121 (thanks @thenonamezz)
* The ISO Triangle shape would skip rendering the left side of the first triangle in the batch. It now renders all ISO Triangles correctly. Fix #5164 (thanks @mattjennings)
### 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:
@samme @SanderVanhove @SirJosh3917 @mooreInteractive @A-312 @lozzajp @mikewesthad @j-waters @futuremarc
Please see the complete [Change Log](https://github.com/photonstorm/phaser/blob/master/CHANGELOG.md) for previous releases.
![Contributing](https://phaser.io/images/github/div-contributing.png "Contributing")
<a name="contributing"></a>
The [Contributors Guide][contribute] contains full details on how to help with Phaser development. The main points are:
- Found a bug? Report it on [GitHub Issues][issues] and include a code sample. Please state which version of Phaser you are using! This is vitally important.
- Before submitting a Pull Request run your code through [ES Lint](https://eslint.org/) using our [config](https://github.com/photonstorm/phaser/blob/master/.eslintrc.json) and respect our [Editor Config](https://github.com/photonstorm/phaser/blob/master/.editorconfig).
- Before contributing read the [code of conduct](https://github.com/photonstorm/phaser/blob/master/.github/CODE_OF_CONDUCT.md).
Written something cool in Phaser? Please tell us about it in the [forum][forum], or email support@phaser.io
![Created by](https://phaser.io/images/github/div-created-by.png "Created by")
Phaser is a [Photon Storm](http://www.photonstorm.com) production.
![storm](https://www.phaser.io/images/github/photonstorm-x2.png)
Created by [Richard Davey](mailto:rich@photonstorm.com). Powered by coffee, anime, pixels and love.
The Phaser logo and characters are &copy; 2020 Photon Storm Limited.
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.24.0/phaser.js
[get-minjs]: https://github.com/photonstorm/phaser/releases/download/v3.24.0/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
[clone-ghmac]: github-mac://openRepo/https://github.com/photonstorm/phaser
[phaser]: https://github.com/photonstorm/phaser
[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]: https://phaser.discourse.group/
# Phaser - HTML5 Game Framework
![Phaser Header](https://phaser.io/images/github/300/phaser-header.png "Phaser 3 Header Banner")
[![Discord chat](https://img.shields.io/discord/244245946873937922?style=for-the-badge)](https://discord.gg/phaser)
[![Twitter Follow](https://img.shields.io/twitter/follow/phaser_?style=for-the-badge)](https://twitter.com/phaser_)
![GitHub All Releases](https://img.shields.io/github/downloads/photonstorm/phaser/total?style=for-the-badge)
![npm](https://img.shields.io/npm/dy/phaser?label=npm&style=for-the-badge)
Phaser is a fast, free, and fun open source HTML5 game framework that offers WebGL and Canvas rendering across desktop and mobile web browsers. Games can be compiled to iOS, Android and native apps by using 3rd party tools. You can use JavaScript or TypeScript for development.
Along with the fantastic open source community, Phaser is actively developed and maintained by [Photon Storm](http://www.photonstorm.com). As a result of rapid support, and a developer friendly API, Phaser is currently one of the [most starred](https://github.com/collections/javascript-game-engines) game frameworks on GitHub.
Thousands of developers from indie and multi-national digital agencies, and universities worldwide use Phaser. You can take a look at their incredible [games](https://phaser.io/games/).
**Visit:** The [Phaser website](https://phaser.io) and follow on [Twitter](https://twitter.com/phaser_) (#phaserjs)<br />
**Learn:** [API Docs](https://photonstorm.github.io/phaser3-docs/index.html), [Support Forum][forum] and [StackOverflow](https://stackoverflow.com/questions/tagged/phaser-framework)<br />
**Code:** 1700+ [Examples](https://phaser.io/examples) (source available in this [repo][examples])<br />
**Read:** The [Phaser World](#newsletter) Newsletter<br />
**Discord:** Join us on [Discord](https://phaser.io/community/discord)<br />
**Extend:** With [Phaser Plugins](https://phaser.io/shop/plugins)<br />
**Be awesome:** [Support](#support) the future of Phaser<br />
Grab the source and join the fun!
![What's New](https://phaser.io/images/github/div-whats-new.png "What's New")
<div align="center"><img src="https://phaser.io/images/github/news.jpg"></div>
> 13th July 2020
I'm pleased to announce the immediate availability of Phaser 3.24. This release is primarily a maintenance release, with the focus mostly on bug fixes and updates. Even so, there are over 70 updates in this version alone. From improvements to the Arcade Physics system, to new Tween events and the ability to chain multiple animations, to some important fixes. If you're currently using 3.23 then we recommend this upgrade. As usual, I'd like to send my thanks to the Phaser community for their help in both reporting issues and submitting pull requests to fix them.
So, please do spend some time digging through the [Change Log](#changelog). I assure you, it's worth while :)
I'd like to send a massive thank-you to everyone who supports [Phaser on Patreon](https://www.patreon.com/photonstorm) (and now even GitHub Sponsors, too!) Your continued backing keeps allowing me to work on Phaser full-time and this great new releases is the very real result of that. If you've ever considered becoming a backer, now is the perfect time!
As well as all of these updates, development has been progressing rapidly on Phaser 4. If you'd like to stay abreast of developments then I'm now publishing them to the [Phaser Patreon](https://www.patreon.com/photonstorm). Here you can find details about the latest developments and concepts behind Phaser 4.
You can also follow Phaser on [Twitter](https://twitter.com/phaser_) and chat with fellow Phaser devs in our [Discord](https://phaser.io/community/discord).
Phaser 3 wouldn't have been possible without the fantastic support of the community and Patreon. Thank you to everyone who supports our work, who shares our belief in the future of HTML5 gaming, and Phaser's role in that.
Happy coding everyone!
Cheers,
Rich - [@photonstorm](https://twitter.com/photonstorm)
![boogie](https://www.phaser.io/images/spacedancer.gif)
![Support Phaser](https://phaser.io/images/github/div-support-phaser.png "Support Phaser")
Because Phaser is an open source project, we cannot charge for it in the same way as traditional retail software. What's more, we don't ever want to. After all, it's built on, and was born from, open web standards. It's part of our manifesto that the core framework will always be free, even if you use it commercially, as many of you do.
**You may not realize it, but because of this, we rely 100% on community backing to fund development.**
Those funds allow Phaser to improve, and when it improves, everyone involved benefits. Your support helps secure a constant cycle of updates, fixes, new features and planning for the future.
There are other benefits to [backing Phaser](https://www.patreon.com/join/photonstorm), too:
![Backers Perks](https://phaser.io/images/github/patreon-perk-chart.png)
We use [Patreon](https://www.patreon.com/photonstorm) to manage the backing and you can [support Phaser](https://www.patreon.com/join/photonstorm?) from $1 per month. The amount you pledge is entirely up to you and can be changed as often as you like. Patreon renews monthly, just like Netflix. You can, of course, cancel at any point. Tears will be shed on this end, but that's not your concern.
Extra special thanks to the following companies who's support makes Phaser possible:
* [Cerebral Fix](https://cerebralfix.com)
* [CrossInstall](https://crossinstall.com)
* [Facebook](https://www.facebook.com)
* [Game Distribution](https://gamedistribution.com)
* [GameCommerce](https://www.gamecommerce.com)
* [Mozilla](https://www.mozilla.org)
* [Texture Packer](https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3?utm_source=ad&utm_medium=banner&utm_campaign=phaser-2018-10-16)
* [Twilio](https://www.twilio.com)
* [Poki](https://developers.poki.com/)
* [CrazyGames](https://www.crazygames.com)
* [Lagged](https://www.lagged.com)
![Sponsors](https://phaser.io/images/github/sponsors-2020-06.png "Our Awesome Sponsors")
![Download Phaser](https://phaser.io/images/github/div-download.png "Download Phaser")
<a name="download"></a>
Phaser 3 is available via GitHub, npm and CDNs:
* Clone the git repository via [https][clone-http], [ssh][clone-ssh] or with the GitHub [Windows][clone-ghwin] or [Mac][clone-ghmac] clients.
* Download as [zip](https://github.com/photonstorm/phaser/archive/master.zip)
* Download the build files: [phaser.js][get-js] and [phaser.min.js][get-minjs]
### NPM
Install via [npm](https://www.npmjs.com):
```bash
npm install phaser
```
### CDN
[![](https://data.jsdelivr.com/v1/package/gh/photonstorm/phaser/badge)](https://www.jsdelivr.com/package/gh/photonstorm/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.24.0/dist/phaser.js"></script>
```
or the minified version:
```html
<script src="//cdn.jsdelivr.net/npm/phaser@3.24.0/dist/phaser.min.js"></script>
```
### API Documentation
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 namespaces, 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.
### TypeScript Definitions
The [TypeScript definitions](https://github.com/photonstorm/phaser/tree/master/types) can be found inside the `types` folder. They are also referenced in the types entry in `package.json`.
Depending on your project, you may need to add the following to your `tsconfig.json` file:
```json
"typeRoots": [
"./node_modules/phaser/types"
],
"types": [
"Phaser"
]
```
We recently published a new [Phaser 3 TypeScript Project Template](https://github.com/photonstorm/phaser3-typescript-project-template), which you can use to get started with if you like.
The TS defs are automatically generated from the JSDoc comments found in the Phaser source code. If you wish to help refine them then you must edit the Phaser JSDoc blocks directly, not the defs file. You can find more details about the parser we built in the `scripts/tsgen` folder.
### 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 use any other packager, like Parcel, without any config changes.
### License
Phaser is released under the [MIT License](https://opensource.org/licenses/MIT).
![Getting Started](https://phaser.io/images/github/div-getting-started.png "Getting Started")
<a name="getting-started"></a>
<img src="https://phaser.io/images/github/learn.jpg" align="right">
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)
* 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.
We've 3 tutorials related specifically to creating **Facebook Instant Games** with 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)
### Source Code Examples
During our development of Phaser 3, we created hundreds of examples with the full source code and assets ready available. These examples are now fully integrated into the [Phaser website](https://phaser.io/examples). You can also browse them on [Phaser 3 Labs](https://labs.phaser.io) via a more advanced interface, or clone the [examples repo][examples]. We are constantly adding to and refining these examples.
### Huge list of Phaser 3 Plugins
Super community member RexRainbow has been publishing Phaser 3 content for years, building up an impressive catalogue in that time. You'll find [loads of plugins](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/index.html#list-of-my-plugins), from UI controls such as text input boxes, to Firebase support, Finite State Machines and lots more. As well as the plugins there is also a comprehensive set of 'Notes' about Phaser 3, going into great detail about how the various systems work. It's an invaluable resource and well worth checking out at [https://rexrainbow.github.io](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/index.html)
### Create Your First Phaser 3 Example
Create an `index.html` page locally and paste the following code into it:
```html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/phaser@3.24.0/dist/phaser-arcade-physics.min.js"></script>
</head>
<body>
<script></script>
</body>
</html>
```
This is a standard empty webpage. You'll notice there's a script tag that is pulling in a build of Phaser 3, but otherwise this webpage doesn't do anything yet. Now let's set-up the game config. Paste the following between the `<script></script>` tags:
```javascript
var config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 200 }
}
},
scene: {
preload: preload,
create: create
}
};
```
`config` is a pretty standard Phaser 3 Game Configuration object. We tell `config` to use the WebGL renderer if it can, set the canvas to a size of 800x600 pixels, enable Arcade Physics, and finally call the `preload` and `create` functions. `preload` and `create` have not been implemented yet, so if you run this JavaScript code, you will have an error. Add the following after `config`:
```javascript
var game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('http://labs.phaser.io');
this.load.image('sky', 'assets/skies/space3.png');
this.load.image('logo', 'assets/sprites/phaser3-logo.png');
this.load.image('red', 'assets/particles/red.png');
}
function create ()
{
}
```
`game` is a Phaser Game instance that uses our configuration object `config`. We also add function definitions for `preload` and `create`. The `preload` function helps you easily load assets into your game. In `preload`, we set the Base URL to be the Phaser server and load 3 PNG files.
The `create` function is empty, so it's time to fill it in:
```javascript
function create ()
{
this.add.image(400, 300, 'sky');
var particles = this.add.particles('red');
var emitter = particles.createEmitter({
speed: 100,
scale: { start: 1, end: 0 },
blendMode: 'ADD'
});
var logo = this.physics.add.image(400, 100, 'logo');
logo.setVelocity(100, 200);
logo.setBounce(1, 1);
logo.setCollideWorldBounds(true);
emitter.startFollow(logo);
}
```
Here we add a sky image into the game and create a Particle Emitter. The `scale` value means that the particles will initially be large and will shrink to nothing as their lifespan progresses.
After creating the `emitter`, we add a logo image called `logo`. Since `logo` is a Physics Image, `logo` is given a physics body by default. We set some properties for `logo`: velocity, bounce (or restitution), and collision with the world bounds. These properties will make our logo bounce around the screen. Finally, we tell the particle emitter to follow the logo - so as the logo moves, the particles will flow from it.
Run it in your browser and you'll see the following:
![Phaser 3 Demo](https://phaser.io/images/github/300/sample1.png "Phaser 3 Demo")
(Got an error? Here's the [full code](https://gist.github.com/photonstorm/46cb8fb4b19fc7717dcad514cdcec064))
This is a tiny example, and there are hundreds more for you to explore, but hopefully it shows how expressive and quick Phaser is to use. With just a few easily readable lines of code, we've got something pretty impressive up on screen!
![Ourcade](https://phaser.io/images/github/ourcade.jpg "Ourcade")
Ourcade have published [two great Phaser 3 books](https://blog.ourcade.co/). They'll take you from getting set-up, through to finishing your first game using modern JavaScript or TypeScript and they're both completely free! They also publish a huge range of quality tutorials and videos, so be sure to check out their site every week.
![Building Phaser](https://phaser.io/images/github/div-building-phaser.png "Building Phaser")
There are both plain and minified compiled versions of Phaser in the `dist` folder of the repository. The plain version is for use during development, and the minified version is for production use. You can also create your own builds.
### 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 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` 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`.
![Change Log](https://phaser.io/images/github/div-change-log.png "Change Log")
<a name="changelog"></a>
# Change Log
## Version 3.24 - Rem - 13th July 2020
### Arcade Physics New Features, Updates and Fixes
* When colliding physics groups with the search tree enabled, there was an unnecessary intersection test for each body returned by the search (thanks @samme)
* When doing an overlap collision, there was an unnecessary intersection test for each pair of overlapping bodies (thanks @samme)
* Sprite vs. Static Group collision tests now always use the static tree (thanks @samme)
* Fixed a bug where if you added a static body to a sprite with scale ≠ 1, the body position was incorrect (thanks @samme)
* If you passed in an array of `children` when creating a Physics Group, they didn't receive bodies. Fix #5152 (thanks @samme)
* New types allow for better docs / TypeScript defs especially in the Factory functions: `ArcadePhysicsCallback`, `GameObjectWithBody`, `GameObjectWithDynamicBody`, `GameObjectWithStaticBody`, `ImageWithDynamicBody`, `ImageWithStaticBody`, `SpriteWithDynamicBody` and `SpriteWithStaticBody`. Fix #4994 (thanks @samme @gnesher)
* `Body.updateFromGameObject` is a new method that extracts the relevant code from `preUpdate`, allowing you to read the body's new position and center immediately, before the next physics step. It also lets `refreshBody` work for dynamic bodies, where previously it would error (thanks @samme)
* Momentum exchange wasn't working correctly vs. immovable bodies. The movable body tended to stop. Fix #4770 (thanks @samme)
* The Body mass was decreasing the inertia instead of increasing it. Fix #4770 (thanks @samme)
* The separation vector seemed to be incorrect, causing the slip / slide collisions. The separation is now correct for circlecircle collisions (although not fully for circlerectangle collisions), part fix #4770 (thanks @samme)
* The Arcade Body delta was incorrectly calculated on bodies created during the `update` step, causing the position to be off. Fix #5204 (thanks @zackexplosion @samme)
* `Arcade.Components.Size.setBodySize` is a new method available on Arcade Physics Game Objects that allows you to set the body size. This replaces `setSize` which is now deprecated. Fix #4786 (thanks @wingyplus)
### New Features
* The Animation component has a new property `nextAnimsQueue` which allows you to sequence Sprite animations to play in order, i.e: `this.mole.anims.play('digging').anims.chain('lifting').anims.chain('looking').anims.chain('lowering');` (thanks @tgroborsch)
* `Group.setActive` is a new method that will set the active state of a Group, just like it does on other Game Objects (thanks @samme)
* `Group.setName` is a new method that will set the name property of a Group, just like it does on other Game Objects (thanks @samme)
* `TWEEN_STOP` is a new event dispatched by a Tween when it stops playback (thanks @samme @RollinSafary)
* You can now specify an `onStop` callback when creating a Tween as part of the tween config, which is invoked when a Tween stops playback (thanks @samme @RollinSafary)
* Previously, if you created a timeline and passed no tweens in the config, the timeline would be created but all config properties were ignored. Now the timeline's own properties (completeDelay, loop, loopDelay, useFrames, onStart, onUpdate, onLoop, onYoyo, onComplete, etc.) are set from the config properly (thanks @samme)
* `TextStyle.wordWrapWidth` lets you set the maximum width of a line of text (thanks @mikewesthad)
* `TextStyle.wordWrapCallback` is a custom function that will is responsible for wrapping the text (thanks @mikewesthad)
* `TextStyle.wordWrapCallbackScope` is the scope that will be applied when the `wordWrapCallback` is invoked (thanks @mikewesthad)
* `TextStyle.wordWrapUseAdvanced` controls whether or not to use the advanced wrapping algorithm (thanks @mikewesthad)
* `KeyboardPlugin.removeAllKeys` is a new method that allows you to automatically remove all Key instances that the plugin has created, making house-keeping a little easier (thanks @samme)
* `Math.RotateTo` is a new function that will position a point at the given angle and distance (thanks @samme)
* `Display.Bounds.GetBounds` is a new function that will return the un-transformed bounds of the given Game Object as a Rectangle (thanks @samme)
### Updates
* The `Pointer.dragStartX/YGlobal` and `Pointer.dragX/Y` values are now populated from the `worldX/Y`, which means using those values directly in Input Drag callbacks will now work when the Camera is zoomed. Fix #4755 (thanks @braindx)
* The `browser` field has been added to the Phaser `package.json` pointing to the `dist/phaser.js` umd build (thanks @FredKSchott)
* Calling `TimeStep.wake()` while the loop is running will now cause nothing to happen, rather than sleeping and then waking again (thanks @samme)
* `Container.getBounds` will no longer set the temp rect bounds to the first child of the Container by default (which would error if the child had no bounds, like a Graphics object) and instead sets it as it iterates the children (thanks @blopa)
* `File.state` will now be set to the `FILE_LOADING` state while loading and `FILE_LOADED` after loading (thanks @samme)
* `BaseCamera.cull` now moves some of its calculations outside of the cull loop to speed it up (thanks @samme)
* `SceneManager.createSceneFromInstance` had a small refactor to avoid a pointless condition (thanks @samme)
### Bug Fixes
* Fixed a TypeError warning when importing JSON objects directly to the `url` argument of any of the Loader filetypes. Fix #5189 (thanks @awweather @samme)
* The `NOOP` function was incorrectly imported by the Mouse and Keyboard Manager. Fix #5170 (thanks @samme @gregolai)
* When Audio files failed to decode on loading, they would always show 'undefined' as the key in the error log, now they show the actual key (thanks @samme)
* When the Sprite Sheet parser results in zero frames, the warning will now tell you the texture name that caused it (thanks @samme)
* `KeyboardPlugin.checkDown` didn't set the `duration` to zero if the parameter was omitted, causing it to always return false. Fix #5146 (thanks @lozzajp)
* If you passed in an array of `children` when creating a Group, they were not added and removed correctly. Fix #5151 (thanks @samme)
* When using HTML5 Audio with `pauseOnBlur` (the default), if you play a sound, schedule stopping the sound (e.g., timer, tween complete callback), leave the page, and return to the page, the sound `stop()` will error (thanks @samme)
* Using a Render Texture when you're also using the headless renderer would cause an error (thanks @samme)
* `Ellipse.setWidth` would incorrectly set the `xRadius` to the diameter (thanks @rexrainbow)
* `Ellipse.setHeight` would incorrectly set the `yRadius` to the diameter (thanks @rexrainbow)
* When specifically setting the `parent` property in the Game Config to `null` the canvas was appended to the document body, when it should have been ignored (allowing you to add it to the dom directly). Fix #5191 (thanks @MerganThePirate)
* Containers will now apply nested masks correctly when using the Canvas Renderer specifically (thanks @scott20145)
* Calling `Scale.startFullScreen` would fail in Safari on Mac OS, throwing a `fullscreenfailed` error. It now triggers fullscreen mode correctly, as on other browsers. Fix #5143 (thanks @samme @novaknole)
* Calling `setCrop` on a Matter Physics Sprite would throw a TypeError, but will now crop correctly. Not that it only crops the texture, the body is unaffected. Fix #5211 (thanks @MatthewRorke @samme)
* The Static Tilemap Layer would ignore the layer rotation and parent transform when using WebGL (but worked in Canvas). Both modes now work in the same manner (thanks @cruzdanilo)
* Calling `getTextBounds` on a BitmapText object would return the incorrect values if the origin had been changed, but the text itself had not, as it was using out of date dimensions. Changing the origin now automatically triggers BitmapText to be dirty, forcing the bounds to be refreshed. Fix #5121 (thanks @thenonamezz)
* The ISO Triangle shape would skip rendering the left side of the first triangle in the batch. It now renders all ISO Triangles correctly. Fix #5164 (thanks @mattjennings)
### 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:
@samme @SanderVanhove @SirJosh3917 @mooreInteractive @A-312 @lozzajp @mikewesthad @j-waters @futuremarc
Please see the complete [Change Log](https://github.com/photonstorm/phaser/blob/master/CHANGELOG.md) for previous releases.
![Contributing](https://phaser.io/images/github/div-contributing.png "Contributing")
<a name="contributing"></a>
The [Contributors Guide][contribute] contains full details on how to help with Phaser development. The main points are:
- Found a bug? Report it on [GitHub Issues][issues] and include a code sample. Please state which version of Phaser you are using! This is vitally important.
- Before submitting a Pull Request run your code through [ES Lint](https://eslint.org/) using our [config](https://github.com/photonstorm/phaser/blob/master/.eslintrc.json) and respect our [Editor Config](https://github.com/photonstorm/phaser/blob/master/.editorconfig).
- Before contributing read the [code of conduct](https://github.com/photonstorm/phaser/blob/master/.github/CODE_OF_CONDUCT.md).
Written something cool in Phaser? Please tell us about it in the [forum][forum], or email support@phaser.io
![Created by](https://phaser.io/images/github/div-created-by.png "Created by")
Phaser is a [Photon Storm](http://www.photonstorm.com) production.
![storm](https://www.phaser.io/images/github/photonstorm-x2.png)
Created by [Richard Davey](mailto:rich@photonstorm.com). Powered by coffee, anime, pixels and love.
The Phaser logo and characters are &copy; 2020 Photon Storm Limited.
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.24.0/phaser.js
[get-minjs]: https://github.com/photonstorm/phaser/releases/download/v3.24.0/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
[clone-ghmac]: github-mac://openRepo/https://github.com/photonstorm/phaser
[phaser]: https://github.com/photonstorm/phaser
[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]: https://phaser.discourse.group/

View file

@ -1,59 +1,59 @@
'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: {
phaser: './phaser.js',
'phaser.min': './phaser.js',
'phaser-arcade-physics': './phaser-arcade-physics.js',
'phaser-arcade-physics.min': './phaser-arcade-physics.js'
},
output: {
path: `${__dirname}/../dist/`,
filename: '[name].js',
library: 'Phaser',
libraryTarget: 'umd',
umdNamedDefine: true
},
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 webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(true),
"typeof EXPERIMENTAL": JSON.stringify(false),
"typeof PLUGIN_CAMERA3D": JSON.stringify(false),
"typeof PLUGIN_FBINSTANT": JSON.stringify(false),
"typeof FEATURE_SOUND": JSON.stringify(true)
}),
new CleanWebpackPlugin()
]
};
'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: {
phaser: './phaser.js',
'phaser.min': './phaser.js',
'phaser-arcade-physics': './phaser-arcade-physics.js',
'phaser-arcade-physics.min': './phaser-arcade-physics.js'
},
output: {
path: `${__dirname}/../dist/`,
filename: '[name].js',
library: 'Phaser',
libraryTarget: 'umd',
umdNamedDefine: true
},
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 webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(true),
"typeof EXPERIMENTAL": JSON.stringify(false),
"typeof PLUGIN_CAMERA3D": JSON.stringify(false),
"typeof PLUGIN_FBINSTANT": JSON.stringify(false),
"typeof FEATURE_SOUND": JSON.stringify(true)
}),
new CleanWebpackPlugin()
]
};

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

226016
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

10975
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,89 +1,87 @@
{
"name": "phaser",
"version": "3.50.0-beta.4",
"release": "Subaru",
"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)",
"homepage": "http://phaser.io",
"bugs": "https://github.com/photonstorm/phaser/issues",
"license": "MIT",
"licenseUrl": "http://www.opensource.org/licenses/mit-license.php",
"main": "./src/phaser.js",
"types": "./types/phaser.d.ts",
"browser": "./dist/phaser.js",
"repository": {
"type": "git",
"url": "https://photonstorm@github.com/photonstorm/phaser.git"
},
"scripts": {
"beta": "npm publish --tag beta",
"help": "node scripts/help.js",
"build": "webpack --config config/webpack.config.js",
"watch": "webpack --watch --config config/webpack.config.js",
"buildfb": "webpack --config config/webpack.fb.config.js",
"watchfb": "webpack --config config/webpack.fb.config.js --watch",
"dist": "webpack --config config/webpack.dist.config.js",
"distfb": "webpack --config config/webpack.fb.dist.config.js",
"distfull": "npm run dist && npm run distfb",
"distT": " npm run dist && npm run toT",
"toT": "cp ./dist/phaser.min.js ../phasertest/phaser.min.js",
"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.dev": "webpack --config plugins/spine/webpack.auto.config.js",
"plugin.spine.runtimes": "cd plugins/spine && tsc -p tsconfig.both.json && tsc -p tsconfig.canvas.json && tsc -p tsconfig.webgl.json",
"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.canvas.dev": "webpack --config plugins/spine/webpack.canvas.config.js",
"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 --display-modules",
"plugin.spine.webgl.dev": "webpack --config plugins/spine/webpack.webgl.config.js",
"plugin.spine.full": "npm run plugin.spine.dev && npm run plugin.spine.canvas.dev && npm run plugin.spine.webgl.dev",
"plugin.spine.full.dist": "npm run plugin.spine.dist && npm run plugin.spine.canvas.dist && npm run plugin.spine.webgl.dist",
"lint": "eslint --config .eslintrc.json \"src/**/*.js\"",
"lintfix": "eslint --config .eslintrc.json \"src/**/*.js\" --fix",
"sloc": "node-sloc \"./src\" --include-extensions \"js\"",
"bundleshaders": "node scripts/bundle-shaders.js",
"build-tsgen": "cd scripts/tsgen && tsc",
"tsgen": "cd scripts/tsgen && jsdoc -c jsdoc-tsd.conf.json",
"test-ts": "cd scripts/tsgen/test && tsc --build tsconfig.json > output.txt",
"ts": "npm run tsgen && npm run test-ts",
"tsdev": "npm run build-tsgen && npm run tsgen && npm run test-ts"
},
"keywords": [
"2d",
"HTML5",
"WebGL",
"canvas",
"game",
"javascript",
"physics",
"tweens",
"typescript",
"web audio"
],
"devDependencies": {
"@types/source-map": "^0.5.7",
"clean-webpack-plugin": "^3.0.0",
"dts-dom": "^3.6.0",
"eslint": "^7.8.1",
"eslint-plugin-es5": "^1.5.0",
"fs-extra": "^9.0.1",
"jsdoc": "^3.6.5",
"node-sloc": "^0.1.12",
"remove-files-webpack-plugin": "^1.4.3",
"typescript": "^4.0.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"vivid-cli": "^1.1.2",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-shell-plugin": "^0.5.0"
},
"dependencies": {
"eventemitter3": "^4.0.7",
"exports-loader": "^1.1.0",
"imports-loader": "^1.1.0",
"path": "^0.12.7"
}
}
{
"name": "phaser",
"version": "3.50.0-beta.7",
"release": "Subaru",
"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)",
"homepage": "http://phaser.io",
"bugs": "https://github.com/photonstorm/phaser/issues",
"license": "MIT",
"licenseUrl": "http://www.opensource.org/licenses/mit-license.php",
"main": "./src/phaser.js",
"types": "./types/phaser.d.ts",
"browser": "./dist/phaser.js",
"repository": {
"type": "git",
"url": "https://photonstorm@github.com/photonstorm/phaser.git"
},
"scripts": {
"beta": "npm publish --tag beta",
"help": "node scripts/help.js",
"build": "webpack --config config/webpack.config.js",
"watch": "webpack --watch --config config/webpack.config.js",
"buildfb": "webpack --config config/webpack.fb.config.js",
"watchfb": "webpack --config config/webpack.fb.config.js --watch",
"dist": "webpack --config config/webpack.dist.config.js",
"distfb": "webpack --config 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.dev": "webpack --config plugins/spine/webpack.auto.config.js",
"plugin.spine.runtimes": "cd plugins/spine && tsc -p tsconfig.both.json && tsc -p tsconfig.canvas.json && tsc -p tsconfig.webgl.json",
"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.canvas.dev": "webpack --config plugins/spine/webpack.canvas.config.js",
"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 --display-modules",
"plugin.spine.webgl.dev": "webpack --config plugins/spine/webpack.webgl.config.js",
"plugin.spine.full": "npm run plugin.spine.dev && npm run plugin.spine.canvas.dev && npm run plugin.spine.webgl.dev",
"plugin.spine.full.dist": "npm run plugin.spine.dist && npm run plugin.spine.canvas.dist && npm run plugin.spine.webgl.dist",
"lint": "eslint --config .eslintrc.json \"src/**/*.js\"",
"lintfix": "eslint --config .eslintrc.json \"src/**/*.js\" --fix",
"sloc": "node-sloc \"./src\" --include-extensions \"js\"",
"bundleshaders": "node scripts/bundle-shaders.js",
"build-tsgen": "cd scripts/tsgen && tsc",
"tsgen": "cd scripts/tsgen && jsdoc -c jsdoc-tsd.conf.json",
"test-ts": "cd scripts/tsgen/test && tsc --build tsconfig.json > output.txt",
"ts": "npm run tsgen && npm run test-ts",
"tsdev": "npm run build-tsgen && npm run tsgen && npm run test-ts"
},
"keywords": [
"2d",
"HTML5",
"WebGL",
"canvas",
"game",
"javascript",
"physics",
"tweens",
"typescript",
"web audio"
],
"devDependencies": {
"@types/source-map": "^0.5.7",
"clean-webpack-plugin": "^3.0.0",
"dts-dom": "^3.6.0",
"eslint": "^7.9.0",
"eslint-plugin-es5": "^1.5.0",
"fs-extra": "^9.0.1",
"jsdoc": "^3.6.5",
"node-sloc": "^0.1.12",
"remove-files-webpack-plugin": "^1.4.4",
"typescript": "^4.0.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"vivid-cli": "^1.1.2",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-shell-plugin": "^0.5.0"
},
"dependencies": {
"eventemitter3": "^4.0.7",
"exports-loader": "^1.1.0",
"imports-loader": "^1.1.0",
"path": "^0.12.7"
}
}

View file

@ -1,13 +1,13 @@
var fs = require('fs-extra');
var source = './plugins/camera3d/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');
}
var fs = require('fs-extra');
var source = './plugins/camera3d/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');
}

File diff suppressed because it is too large Load diff

View file

@ -1,93 +1,93 @@
Phaser 3 Camera 3D Plugin
=========================
Note: As of 26th August 2020 this plugin is now considered deprecated and will not be supported any further. It has been fixed to work with the Phaser 3.50 release, but will not be updated beyond this. You're free to use it as you see fit, but please do not open issues about it on GitHub, thank you.
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.
Phaser 3 Camera 3D Plugin
=========================
Note: As of 26th August 2020 this plugin is now considered deprecated and will not be supported any further. It has been fixed to work with the Phaser 3.50 release, but will not be updated beyond this. You're free to use it as you see fit, but please do not open issues about it on GitHub, thank you.
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

@ -1,260 +1,260 @@
/**
* @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 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
* A Sprite 3D Game Object.
*
* The Sprite 3D object is an encapsulation of a standard Sprite object, with additional methods to allow
* it to be rendered by a 3D Camera. The Sprite can be positioned anywhere within 3D space.
*
* @class Sprite3D
* @extends Phaser.GameObjects.Sprite
* @memberOf Phaser.GameObjects
* @constructor
* @since 3.0.0
*
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
* @param {number} x - The x position of this Game Object.
* @param {number} y - The y 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.
*/
var Sprite3D = new Class({
Extends: GameObject,
initialize:
function Sprite3D (scene, x, y, z, texture, frame)
{
GameObject.call(this, scene, 'Sprite3D');
/**
* The encapsulated Sprite.
*
* @name Phaser.GameObjects.Sprite3D#gameObject
* @type {Phaser.GameObjects.GameObject}
* @since 3.0.0
*/
this.gameObject = new Sprite(scene, 0, 0, texture, frame);
/**
* The position of the Sprite.
*
* @name Phaser.GameObjects.Sprite3D#position
* @type {Phaser.Math.Vector4}
* @since 3.0.0
*/
this.position = new Vector4(x, y, z);
/**
* The 2D size of the Sprite.
*
* @name Phaser.GameObjects.Sprite3D#size
* @type {Phaser.Math.Vector2}
* @since 3.0.0
*/
this.size = new Vector2(this.gameObject.width, this.gameObject.height);
/**
* The 2D scale of the Sprite.
*
* @name Phaser.GameObjects.Sprite3D#scale
* @type {Phaser.Math.Vector2}
* @since 3.0.0
*/
this.scale = new Vector2(1, 1);
/**
* Whether to automatically set the horizontal scale of the encapsulated Sprite.
*
* @name Phaser.GameObjects.Sprite3D#adjustScaleX
* @type {boolean}
* @default true
* @since 3.0.0
*/
this.adjustScaleX = true;
/**
* Whether to automatically set the vertical scale of the encapsulated Sprite.
*
* @name Phaser.GameObjects.Sprite3D#adjustScaleY
* @type {boolean}
* @default true
* @since 3.0.0
*/
this.adjustScaleY = true;
/**
* The visible state of the Game Object.
*
* @name Phaser.GameObjects.Sprite3D#_visible
* @type {boolean}
* @default true
* @private
* @since 3.0.0
*/
this._visible = true;
},
/**
* Project this Sprite onto the given 3D Camera.
*
* @method Phaser.GameObjects.Sprite3D#project
* @since 3.0.0
*
* @param {Phaser.Cameras.Sprite3D.Camera} camera - The 3D Camera onto which to project this Sprite.
*/
project: function (camera)
{
var pos = this.position;
var gameObject = this.gameObject;
camera.project(pos, gameObject);
camera.getPointSize(pos, this.size, this.scale);
if (this.scale.x <= 0 || this.scale.y <= 0)
{
gameObject.setVisible(false);
}
else
{
if (!gameObject.visible)
{
gameObject.setVisible(true);
}
if (this.adjustScaleX)
{
gameObject.scaleX = this.scale.x;
}
if (this.adjustScaleY)
{
gameObject.scaleY = this.scale.y;
}
gameObject.setDepth(gameObject.z * -1);
}
},
/**
* Set the visible state of the Game Object.
*
* @method Phaser.GameObjects.Sprite3D#setVisible
* @since 3.0.0
*
* @param {boolean} value - The visible state of the Game Object.
*
* @return {Phaser.GameObjects.Sprite3D} This Sprite3D Object.
*/
setVisible: function (value)
{
this.visible = value;
return this;
},
/**
* The visible state of the Game Object.
*
* An invisible Game Object will skip rendering, but will still process update logic.
*
* @name Phaser.GameObjects.Sprite3D#visible
* @type {boolean}
* @since 3.0.0
*/
visible: {
get: function ()
{
return this._visible;
},
set: function (value)
{
this._visible = value;
this.gameObject.visible = value;
}
},
/**
* The x position of this Game Object.
*
* @name Phaser.GameObjects.Sprite3D#x
* @type {number}
* @since 3.0.0
*/
x: {
get: function ()
{
return this.position.x;
},
set: function (value)
{
this.position.x = value;
}
},
/**
* The y position of this Game Object.
*
* @name Phaser.GameObjects.Sprite3D#y
* @type {number}
* @since 3.0.0
*/
y: {
get: function ()
{
return this.position.y;
},
set: function (value)
{
this.position.y = value;
}
},
/**
* The z position of this Game Object.
*
* @name Phaser.GameObjects.Sprite3D#z
* @type {number}
* @since 3.0.0
*/
z: {
get: function ()
{
return this.position.z;
},
set: function (value)
{
this.position.z = value;
}
}
});
module.exports = Sprite3D;
/**
* @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 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
* A Sprite 3D Game Object.
*
* The Sprite 3D object is an encapsulation of a standard Sprite object, with additional methods to allow
* it to be rendered by a 3D Camera. The Sprite can be positioned anywhere within 3D space.
*
* @class Sprite3D
* @extends Phaser.GameObjects.Sprite
* @memberOf Phaser.GameObjects
* @constructor
* @since 3.0.0
*
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
* @param {number} x - The x position of this Game Object.
* @param {number} y - The y 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.
*/
var Sprite3D = new Class({
Extends: GameObject,
initialize:
function Sprite3D (scene, x, y, z, texture, frame)
{
GameObject.call(this, scene, 'Sprite3D');
/**
* The encapsulated Sprite.
*
* @name Phaser.GameObjects.Sprite3D#gameObject
* @type {Phaser.GameObjects.GameObject}
* @since 3.0.0
*/
this.gameObject = new Sprite(scene, 0, 0, texture, frame);
/**
* The position of the Sprite.
*
* @name Phaser.GameObjects.Sprite3D#position
* @type {Phaser.Math.Vector4}
* @since 3.0.0
*/
this.position = new Vector4(x, y, z);
/**
* The 2D size of the Sprite.
*
* @name Phaser.GameObjects.Sprite3D#size
* @type {Phaser.Math.Vector2}
* @since 3.0.0
*/
this.size = new Vector2(this.gameObject.width, this.gameObject.height);
/**
* The 2D scale of the Sprite.
*
* @name Phaser.GameObjects.Sprite3D#scale
* @type {Phaser.Math.Vector2}
* @since 3.0.0
*/
this.scale = new Vector2(1, 1);
/**
* Whether to automatically set the horizontal scale of the encapsulated Sprite.
*
* @name Phaser.GameObjects.Sprite3D#adjustScaleX
* @type {boolean}
* @default true
* @since 3.0.0
*/
this.adjustScaleX = true;
/**
* Whether to automatically set the vertical scale of the encapsulated Sprite.
*
* @name Phaser.GameObjects.Sprite3D#adjustScaleY
* @type {boolean}
* @default true
* @since 3.0.0
*/
this.adjustScaleY = true;
/**
* The visible state of the Game Object.
*
* @name Phaser.GameObjects.Sprite3D#_visible
* @type {boolean}
* @default true
* @private
* @since 3.0.0
*/
this._visible = true;
},
/**
* Project this Sprite onto the given 3D Camera.
*
* @method Phaser.GameObjects.Sprite3D#project
* @since 3.0.0
*
* @param {Phaser.Cameras.Sprite3D.Camera} camera - The 3D Camera onto which to project this Sprite.
*/
project: function (camera)
{
var pos = this.position;
var gameObject = this.gameObject;
camera.project(pos, gameObject);
camera.getPointSize(pos, this.size, this.scale);
if (this.scale.x <= 0 || this.scale.y <= 0)
{
gameObject.setVisible(false);
}
else
{
if (!gameObject.visible)
{
gameObject.setVisible(true);
}
if (this.adjustScaleX)
{
gameObject.scaleX = this.scale.x;
}
if (this.adjustScaleY)
{
gameObject.scaleY = this.scale.y;
}
gameObject.setDepth(gameObject.z * -1);
}
},
/**
* Set the visible state of the Game Object.
*
* @method Phaser.GameObjects.Sprite3D#setVisible
* @since 3.0.0
*
* @param {boolean} value - The visible state of the Game Object.
*
* @return {Phaser.GameObjects.Sprite3D} This Sprite3D Object.
*/
setVisible: function (value)
{
this.visible = value;
return this;
},
/**
* The visible state of the Game Object.
*
* An invisible Game Object will skip rendering, but will still process update logic.
*
* @name Phaser.GameObjects.Sprite3D#visible
* @type {boolean}
* @since 3.0.0
*/
visible: {
get: function ()
{
return this._visible;
},
set: function (value)
{
this._visible = value;
this.gameObject.visible = value;
}
},
/**
* The x position of this Game Object.
*
* @name Phaser.GameObjects.Sprite3D#x
* @type {number}
* @since 3.0.0
*/
x: {
get: function ()
{
return this.position.x;
},
set: function (value)
{
this.position.x = value;
}
},
/**
* The y position of this Game Object.
*
* @name Phaser.GameObjects.Sprite3D#y
* @type {number}
* @since 3.0.0
*/
y: {
get: function ()
{
return this.position.y;
},
set: function (value)
{
this.position.y = value;
}
},
/**
* The z position of this Game Object.
*
* @name Phaser.GameObjects.Sprite3D#z
* @type {number}
* @since 3.0.0
*/
z: {
get: function ()
{
return this.position.z;
},
set: function (value)
{
this.position.z = value;
}
}
});
module.exports = Sprite3D;

View file

@ -1,63 +1,63 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-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 RemovePlugin({
before: {
root: './plugins/camera3d/dist/',
include: [ 'camera3d.js', 'camera3d.min.js' ]
}
}),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/camera3d/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
]
};
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-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 RemovePlugin({
before: {
root: './plugins/camera3d/dist/',
include: [ 'camera3d.js', 'camera3d.min.js' ]
}
}),
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node plugins/camera3d/copy-to-examples.js', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
]
};

View file

@ -1,20 +1,20 @@
var fs = require('fs-extra');
var source = './plugins/spine/dist/';
var dest = '../phaser3-examples/public/plugins/3.8.95/';
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');
}
dest = '../100-phaser3-snippets/public/libs/';
if (fs.existsSync(dest))
{
fs.copySync(source, dest, { overwrite: true });
}
var fs = require('fs-extra');
var source = './plugins/spine/dist/';
var dest = '../phaser3-examples/public/plugins/3.8.95/';
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');
}
dest = '../100-phaser3-snippets/public/libs/';
if (fs.existsSync(dest))
{
fs.copySync(source, dest, { overwrite: true });
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1,251 +1,251 @@
/**
* @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|string[]} [jsonURL] - The absolute or relative URL to load the JSON file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
* @property {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".
* @property {boolean} [preMultipliedAlpha=false] - Do the textures contain pre-multiplied alpha or not?
* @property {XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json file. Used in replacement of the Loaders default XHR Settings.
* @property {XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings.
*/
/**
* @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.SpineFileConfig)} key - The key to use for this file, or a file configuration object.
* @param {string|string[]} [jsonURL] - The absolute or relative URL to load the JSON file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
* @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 {boolean} [preMultipliedAlpha=false] - Do the textures contain pre-multiplied alpha or not?
* @param {XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json 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, preMultipliedAlpha, jsonXhrSettings, atlasXhrSettings)
{
var i;
var json;
var atlas;
var files = [];
var cache = loader.cacheManager.custom.spine;
// atlas can be an array of atlas files, not just a single one
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')
});
atlasURL = GetFastValue(config, 'atlasURL');
preMultipliedAlpha = GetFastValue(config, 'preMultipliedAlpha');
if (!Array.isArray(atlasURL))
{
atlasURL = [ atlasURL ];
}
for (i = 0; i < atlasURL.length; i++)
{
atlas = new TextFile(loader, {
key: key + '_' + i,
url: atlasURL[i],
extension: GetFastValue(config, 'atlasExtension', 'atlas'),
xhrSettings: GetFastValue(config, 'atlasXhrSettings')
});
atlas.cache = cache;
files.push(atlas);
}
}
else
{
json = new JSONFile(loader, key, jsonURL, jsonXhrSettings);
if (!Array.isArray(atlasURL))
{
atlasURL = [ atlasURL ];
}
for (i = 0; i < atlasURL.length; i++)
{
atlas = new TextFile(loader, key + '_' + i, atlasURL[i], atlasXhrSettings);
atlas.cache = cache;
files.push(atlas);
}
}
files.unshift(json);
MultiFile.call(this, loader, 'spine', key, files);
this.config.preMultipliedAlpha = preMultipliedAlpha;
},
/**
* Called by each File when it finishes loading.
*
* @method Phaser.Loader.FileTypes.SpineFile#onFileComplete
* @since 3.19.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', this.baseURL);
var path = GetFastValue(config, 'path', file.src.match(/^.*\//))[0];
var prefix = GetFastValue(config, 'prefix', this.prefix);
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 = this.prefix + 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.19.0
*/
addToCache: function ()
{
if (this.isReadyToProcess())
{
var fileJSON = this.files[0];
fileJSON.addToCache();
var atlasCache;
var atlasKey = '';
var combinedAtlasData = '';
var preMultipliedAlpha = (this.config.preMultipliedAlpha) ? true : false;
var textureManager = this.loader.textureManager;
for (var i = 1; i < this.files.length; i++)
{
var file = this.files[i];
if (file.type === 'text')
{
atlasKey = file.key.replace(/_[\d]$/, '');
atlasCache = file.cache;
combinedAtlasData = combinedAtlasData.concat(file.data);
}
else
{
var src = file.key.trim();
var pos = src.indexOf('_');
var key = src.substr(pos + 1);
if (!textureManager.exists(key))
{
textureManager.addImage(key, file.data);
}
}
file.pendingDestroy();
}
atlasCache.add(atlasKey, { preMultipliedAlpha: preMultipliedAlpha, data: combinedAtlasData, prefix: this.prefix });
this.complete = true;
}
}
});
module.exports = SpineFile;
/**
* @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|string[]} [jsonURL] - The absolute or relative URL to load the JSON file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
* @property {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".
* @property {boolean} [preMultipliedAlpha=false] - Do the textures contain pre-multiplied alpha or not?
* @property {XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json file. Used in replacement of the Loaders default XHR Settings.
* @property {XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings.
*/
/**
* @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.SpineFileConfig)} key - The key to use for this file, or a file configuration object.
* @param {string|string[]} [jsonURL] - The absolute or relative URL to load the JSON file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
* @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 {boolean} [preMultipliedAlpha=false] - Do the textures contain pre-multiplied alpha or not?
* @param {XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json 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, preMultipliedAlpha, jsonXhrSettings, atlasXhrSettings)
{
var i;
var json;
var atlas;
var files = [];
var cache = loader.cacheManager.custom.spine;
// atlas can be an array of atlas files, not just a single one
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')
});
atlasURL = GetFastValue(config, 'atlasURL');
preMultipliedAlpha = GetFastValue(config, 'preMultipliedAlpha');
if (!Array.isArray(atlasURL))
{
atlasURL = [ atlasURL ];
}
for (i = 0; i < atlasURL.length; i++)
{
atlas = new TextFile(loader, {
key: key + '_' + i,
url: atlasURL[i],
extension: GetFastValue(config, 'atlasExtension', 'atlas'),
xhrSettings: GetFastValue(config, 'atlasXhrSettings')
});
atlas.cache = cache;
files.push(atlas);
}
}
else
{
json = new JSONFile(loader, key, jsonURL, jsonXhrSettings);
if (!Array.isArray(atlasURL))
{
atlasURL = [ atlasURL ];
}
for (i = 0; i < atlasURL.length; i++)
{
atlas = new TextFile(loader, key + '_' + i, atlasURL[i], atlasXhrSettings);
atlas.cache = cache;
files.push(atlas);
}
}
files.unshift(json);
MultiFile.call(this, loader, 'spine', key, files);
this.config.preMultipliedAlpha = preMultipliedAlpha;
},
/**
* Called by each File when it finishes loading.
*
* @method Phaser.Loader.FileTypes.SpineFile#onFileComplete
* @since 3.19.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', this.baseURL);
var path = GetFastValue(config, 'path', file.src.match(/^.*\//))[0];
var prefix = GetFastValue(config, 'prefix', this.prefix);
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 = this.prefix + 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.19.0
*/
addToCache: function ()
{
if (this.isReadyToProcess())
{
var fileJSON = this.files[0];
fileJSON.addToCache();
var atlasCache;
var atlasKey = '';
var combinedAtlasData = '';
var preMultipliedAlpha = (this.config.preMultipliedAlpha) ? true : false;
var textureManager = this.loader.textureManager;
for (var i = 1; i < this.files.length; i++)
{
var file = this.files[i];
if (file.type === 'text')
{
atlasKey = file.key.replace(/_[\d]$/, '');
atlasCache = file.cache;
combinedAtlasData = combinedAtlasData.concat(file.data);
}
else
{
var src = file.key.trim();
var pos = src.indexOf('_');
var key = src.substr(pos + 1);
if (!textureManager.exists(key))
{
textureManager.addImage(key, file.data);
}
}
file.pendingDestroy();
}
atlasCache.add(atlasKey, { preMultipliedAlpha: preMultipliedAlpha, data: combinedAtlasData, prefix: this.prefix });
this.complete = true;
}
}
});
module.exports = SpineFile;

File diff suppressed because it is too large Load diff

View file

@ -1,92 +1,92 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../../src/utils/Class');
var Container = require('../../../../src/gameobjects/container/Container');
var SpineContainerRender = require('./SpineContainerRender');
/**
* @classdesc
* A Spine Container is a special kind of Container created specifically for Spine Game Objects.
*
* You have all of the same features of a standard Container, but the rendering functions are optimized specifically
* for Spine Game Objects. You must only add ever Spine Game Objects to this type of Container. Although Phaser will
* not prevent you from adding other types, they will not render and are likely to throw runtime errors.
*
* To create one in a Scene, use the factory methods:
*
* ```javascript
* this.add.spinecontainer();
* ```
*
* or
*
* ```javascript
* this.make.spinecontainer();
* ```
*
* See the Container documentation for further details about what Containers can do.
*
* @class SpineContainer
* @extends Phaser.GameObjects.Container
* @constructor
* @since 3.50.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that this Game Object belongs to.
* @param {SpinePlugin} pluginManager - A reference to the Phaser Spine Plugin.
* @param {number} x - The horizontal position of this Game Object in the world.
* @param {number} y - The vertical position of this Game Object in the world.
* @param {SpineGameObject[]} [children] - An optional array of Spine Game Objects to add to this Container.
*/
var SpineContainer = new Class({
Extends: Container,
Mixins: [
SpineContainerRender
],
initialize:
function SpineContainer (scene, plugin, x, y, children)
{
Container.call(this, scene, x, y, children);
// Same as SpineGameObject, to prevent the renderer from mis-typing it when batching
this.type = 'Spine';
/**
* A reference to the Spine Plugin.
*
* @name SpineContainer#plugin
* @type {SpinePlugin}
* @since 3.50.0
*/
this.plugin = plugin;
},
/**
* Internal destroy handler, called as part of the destroy process.
*
* @method SpineContainer#preDestroy
* @protected
* @since 3.50.0
*/
preDestroy: function ()
{
this.removeAll(!!this.exclusive);
this.localTransform.destroy();
this.tempTransformMatrix.destroy();
this.list = [];
this._displayList = null;
this.plugin = null;
}
});
module.exports = SpineContainer;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../../../../src/utils/Class');
var Container = require('../../../../src/gameobjects/container/Container');
var SpineContainerRender = require('./SpineContainerRender');
/**
* @classdesc
* A Spine Container is a special kind of Container created specifically for Spine Game Objects.
*
* You have all of the same features of a standard Container, but the rendering functions are optimized specifically
* for Spine Game Objects. You must only add ever Spine Game Objects to this type of Container. Although Phaser will
* not prevent you from adding other types, they will not render and are likely to throw runtime errors.
*
* To create one in a Scene, use the factory methods:
*
* ```javascript
* this.add.spinecontainer();
* ```
*
* or
*
* ```javascript
* this.make.spinecontainer();
* ```
*
* See the Container documentation for further details about what Containers can do.
*
* @class SpineContainer
* @extends Phaser.GameObjects.Container
* @constructor
* @since 3.50.0
*
* @param {Phaser.Scene} scene - A reference to the Scene that this Game Object belongs to.
* @param {SpinePlugin} pluginManager - A reference to the Phaser Spine Plugin.
* @param {number} x - The horizontal position of this Game Object in the world.
* @param {number} y - The vertical position of this Game Object in the world.
* @param {SpineGameObject[]} [children] - An optional array of Spine Game Objects to add to this Container.
*/
var SpineContainer = new Class({
Extends: Container,
Mixins: [
SpineContainerRender
],
initialize:
function SpineContainer (scene, plugin, x, y, children)
{
Container.call(this, scene, x, y, children);
// Same as SpineGameObject, to prevent the renderer from mis-typing it when batching
this.type = 'Spine';
/**
* A reference to the Spine Plugin.
*
* @name SpineContainer#plugin
* @type {SpinePlugin}
* @since 3.50.0
*/
this.plugin = plugin;
},
/**
* Internal destroy handler, called as part of the destroy process.
*
* @method SpineContainer#preDestroy
* @protected
* @since 3.50.0
*/
preDestroy: function ()
{
this.removeAll(!!this.exclusive);
this.localTransform.destroy();
this.tempTransformMatrix.destroy();
this.list = [];
this._displayList = null;
this.plugin = null;
}
});
module.exports = SpineContainer;

View file

@ -1,100 +1,100 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* 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.Container#renderCanvas
* @since 3.4.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.Container} container - 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 SpineContainerCanvasRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var children = container.list;
if (children.length === 0)
{
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var containerHasBlendMode = (container.blendMode !== -1);
if (!containerHasBlendMode)
{
// If Container is SKIP_TEST then set blend mode to be Normal
renderer.setBlendMode(0);
}
var alpha = container._alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
if (container.mask)
{
container.mask.preRenderCanvas(renderer, null, camera);
}
for (var i = 0; i < children.length; i++)
{
var child = children[i];
if (!child.willRender(camera))
{
continue;
}
var childAlpha = child.alpha;
var childScrollFactorX = child.scrollFactorX;
var childScrollFactorY = child.scrollFactorY;
if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
{
// If Container doesn't have its own blend mode, then a child can have one
renderer.setBlendMode(child.blendMode);
}
// Set parent values
child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY);
child.setAlpha(childAlpha * alpha);
// Render
child.renderCanvas(renderer, child, interpolationPercentage, camera, transformMatrix);
// Restore original values
child.setAlpha(childAlpha);
child.setScrollFactor(childScrollFactorX, childScrollFactorY);
}
if (container.mask)
{
container.mask.postRenderCanvas(renderer);
}
};
module.exports = SpineContainerCanvasRenderer;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* 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.Container#renderCanvas
* @since 3.4.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {Phaser.GameObjects.Container} container - 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 SpineContainerCanvasRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var children = container.list;
if (children.length === 0)
{
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var containerHasBlendMode = (container.blendMode !== -1);
if (!containerHasBlendMode)
{
// If Container is SKIP_TEST then set blend mode to be Normal
renderer.setBlendMode(0);
}
var alpha = container._alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
if (container.mask)
{
container.mask.preRenderCanvas(renderer, null, camera);
}
for (var i = 0; i < children.length; i++)
{
var child = children[i];
if (!child.willRender(camera))
{
continue;
}
var childAlpha = child.alpha;
var childScrollFactorX = child.scrollFactorX;
var childScrollFactorY = child.scrollFactorY;
if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
{
// If Container doesn't have its own blend mode, then a child can have one
renderer.setBlendMode(child.blendMode);
}
// Set parent values
child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY);
child.setAlpha(childAlpha * alpha);
// Render
child.renderCanvas(renderer, child, interpolationPercentage, camera, transformMatrix);
// Restore original values
child.setAlpha(childAlpha);
child.setScrollFactor(childScrollFactorX, childScrollFactorY);
}
if (container.mask)
{
container.mask.postRenderCanvas(renderer);
}
};
module.exports = SpineContainerCanvasRenderer;

View file

@ -1,25 +1,25 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var renderWebGL = require('../../../../src/utils/NOOP');
var renderCanvas = require('../../../../src/utils/NOOP');
if (typeof WEBGL_RENDERER)
{
renderWebGL = require('./SpineContainerWebGLRenderer');
}
if (typeof CANVAS_RENDERER)
{
renderCanvas = require('./SpineContainerCanvasRenderer');
}
module.exports = {
renderWebGL: renderWebGL,
renderCanvas: renderCanvas
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var renderWebGL = require('../../../../src/utils/NOOP');
var renderCanvas = require('../../../../src/utils/NOOP');
if (typeof WEBGL_RENDERER)
{
renderWebGL = require('./SpineContainerWebGLRenderer');
}
if (typeof CANVAS_RENDERER)
{
renderCanvas = require('./SpineContainerCanvasRenderer');
}
module.exports = {
renderWebGL: renderWebGL,
renderCanvas: renderCanvas
};

View file

@ -1,168 +1,339 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var Clamp = require('../../../../src/math/Clamp');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* Renders this Game Object with the WebGL 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 SpineContainerWebGLRenderer#renderWebGL
* @since 3.50.0
* @private
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
* @param {Phaser.GameObjects.Container} container - 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 SpineContainerWebGLRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var plugin = container.plugin;
var sceneRenderer = plugin.sceneRenderer;
var children = container.list;
if (children.length === 0)
{
if (sceneRenderer.batcher.isDrawing && renderer.finalType)
{
sceneRenderer.end();
renderer.rebindPipeline();
}
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var alpha = container.alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
var GameObjectRenderMask = 15;
if (renderer.newType)
{
// flush + clear if this is a new type
renderer.clearPipeline();
sceneRenderer.begin();
}
for (var i = 0; i < children.length; i++)
{
var src = children[i];
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
continue;
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(src.scaleY));
camMatrix.copyFrom(camera.matrix);
// Multiply the camera by the parent matrix
camMatrix.multiplyWithOffset(transformMatrix, -camera.scrollX * scrollFactorX, -camera.scrollY * 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);
var viewportHeight = renderer.height;
skeleton.x = calcMatrix.tx;
skeleton.y = viewportHeight - calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
skeleton.scaleY = calcMatrix.scaleY;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
skeleton.color.a = Clamp(childAlpha * alpha, 0, 1);
// Draw the current skeleton
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
// Restore alpha
skeleton.color.a = childAlpha;
}
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
// And rebind the previous pipeline
renderer.rebindPipeline();
}
};
module.exports = SpineContainerWebGLRenderer;
<<<<<<< HEAD
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var Clamp = require('../../../../src/math/Clamp');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* Renders this Game Object with the WebGL 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 SpineContainerWebGLRenderer#renderWebGL
* @since 3.50.0
* @private
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
* @param {Phaser.GameObjects.Container} container - 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 SpineContainerWebGLRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var plugin = container.plugin;
var sceneRenderer = plugin.sceneRenderer;
var children = container.list;
if (children.length === 0)
{
if (sceneRenderer.batcher.isDrawing && renderer.finalType)
{
sceneRenderer.end();
renderer.rebindPipeline();
}
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var alpha = container.alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
var GameObjectRenderMask = 15;
if (renderer.newType)
{
// flush + clear if this is a new type
renderer.clearPipeline();
sceneRenderer.begin();
}
for (var i = 0; i < children.length; i++)
{
var src = children[i];
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
continue;
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(src.scaleY));
camMatrix.copyFrom(camera.matrix);
// Multiply the camera by the parent matrix
camMatrix.multiplyWithOffset(transformMatrix, -camera.scrollX * scrollFactorX, -camera.scrollY * 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);
var viewportHeight = renderer.height;
skeleton.x = calcMatrix.tx;
skeleton.y = viewportHeight - calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
skeleton.scaleY = calcMatrix.scaleY;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
skeleton.color.a = Clamp(childAlpha * alpha, 0, 1);
// Draw the current skeleton
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
// Restore alpha
skeleton.color.a = childAlpha;
}
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
// And rebind the previous pipeline
renderer.rebindPipeline();
}
};
module.exports = SpineContainerWebGLRenderer;
=======
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var Clamp = require('../../../../src/math/Clamp');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* Renders this Game Object with the WebGL 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 SpineContainerWebGLRenderer#renderWebGL
* @since 3.50.0
* @private
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
* @param {Phaser.GameObjects.Container} container - 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 SpineContainerWebGLRenderer = function (renderer, container, interpolationPercentage, camera, parentMatrix)
{
var plugin = container.plugin;
var sceneRenderer = plugin.sceneRenderer;
var children = container.list;
if (children.length === 0)
{
if (sceneRenderer.batcher.isDrawing && renderer.finalType)
{
sceneRenderer.end();
renderer.pipelines.rebind();
}
return;
}
var transformMatrix = container.localTransform;
if (parentMatrix)
{
transformMatrix.loadIdentity();
transformMatrix.multiply(parentMatrix);
transformMatrix.translate(container.x, container.y);
transformMatrix.rotate(container.rotation);
transformMatrix.scale(container.scaleX, container.scaleY);
}
else
{
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
}
var alpha = container.alpha;
var scrollFactorX = container.scrollFactorX;
var scrollFactorY = container.scrollFactorY;
var GameObjectRenderMask = 15;
if (renderer.newType)
{
// flush + clear if this is a new type
renderer.pipelines.clear();
sceneRenderer.begin();
}
for (var i = 0; i < children.length; i++)
{
var src = children[i];
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
continue;
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(src.scaleY));
camMatrix.copyFrom(camera.matrix);
// Multiply the camera by the parent matrix
camMatrix.multiplyWithOffset(transformMatrix, -camera.scrollX * scrollFactorX, -camera.scrollY * 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);
var viewportHeight = renderer.height;
skeleton.x = calcMatrix.tx;
skeleton.y = viewportHeight - calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
skeleton.scaleY = calcMatrix.scaleY;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
skeleton.color.a = Clamp(childAlpha * alpha, 0, 1);
// Draw the current skeleton
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
// Restore alpha
skeleton.color.a = childAlpha;
}
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
// And rebind the previous pipeline
renderer.pipelines.rebind();
}
};
module.exports = SpineContainerWebGLRenderer;
>>>>>>> af272842021308c7ba8519c30ff2737b8130f96e

View file

@ -1,13 +1,13 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Complete Event.
*
* @event SpinePluginEvents#COMPLETE
* @since 3.19.0
*/
module.exports = 'complete';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Complete Event.
*
* @event SpinePluginEvents#COMPLETE
* @since 3.19.0
*/
module.exports = 'complete';

View file

@ -1,13 +1,13 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Dispose Event.
*
* @event SpinePluginEvents#DISPOSE
* @since 3.19.0
*/
module.exports = 'dispose';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Dispose Event.
*
* @event SpinePluginEvents#DISPOSE
* @since 3.19.0
*/
module.exports = 'dispose';

View file

@ -1,13 +1,13 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The End Event.
*
* @event SpinePluginEvents#END
* @since 3.19.0
*/
module.exports = 'end';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The End Event.
*
* @event SpinePluginEvents#END
* @since 3.19.0
*/
module.exports = 'end';

View file

@ -1,13 +1,13 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Custom Event Event.
*
* @event SpinePluginEvents#EVENT
* @since 3.19.0
*/
module.exports = 'event';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Custom Event Event.
*
* @event SpinePluginEvents#EVENT
* @since 3.19.0
*/
module.exports = 'event';

View file

@ -1,13 +1,13 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Interrupted Event.
*
* @event SpinePluginEvents#INTERRUPTED
* @since 3.19.0
*/
module.exports = 'interrupted';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Interrupted Event.
*
* @event SpinePluginEvents#INTERRUPTED
* @since 3.19.0
*/
module.exports = 'interrupted';

View file

@ -1,13 +1,13 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Start Event.
*
* @event SpinePluginEvents#START
* @since 3.19.0
*/
module.exports = 'start';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Start Event.
*
* @event SpinePluginEvents#START
* @since 3.19.0
*/
module.exports = 'start';

View file

@ -1,20 +1,20 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace SpinePluginEvents
*/
module.exports = {
COMPLETE: require('./COMPLETE_EVENT'),
DISPOSE: require('./DISPOSE_EVENT'),
END: require('./END_EVENT'),
EVENT: require('./EVENT_EVENT'),
INTERRUPTED: require('./INTERRUPTED_EVENT'),
START: require('./START_EVENT')
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace SpinePluginEvents
*/
module.exports = {
COMPLETE: require('./COMPLETE_EVENT'),
DISPOSE: require('./DISPOSE_EVENT'),
END: require('./END_EVENT'),
EVENT: require('./EVENT_EVENT'),
INTERRUPTED: require('./INTERRUPTED_EVENT'),
START: require('./START_EVENT')
};

File diff suppressed because it is too large Load diff

View file

@ -1,125 +1,125 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* 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 SpineGameObject#renderCanvas
* @since 3.19.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {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;
var GameObjectRenderMask = 15;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)));
if (!skeleton || !willRender)
{
return;
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(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);
}
skeleton.x = calcMatrix.tx;
skeleton.y = calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
// Inverse or we get upside-down skeletons
skeleton.scaleY = calcMatrix.scaleY * -1;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
skeletonRenderer.ctx = context;
skeletonRenderer.debugRendering = (plugin.drawDebug || src.drawDebug);
context.save();
skeletonRenderer.draw(skeleton);
context.restore();
};
module.exports = SpineGameObjectCanvasRenderer;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* 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 SpineGameObject#renderCanvas
* @since 3.19.0
* @private
*
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
* @param {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;
var GameObjectRenderMask = 15;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)));
if (!skeleton || !willRender)
{
return;
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(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);
}
skeleton.x = calcMatrix.tx;
skeleton.y = calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
// Inverse or we get upside-down skeletons
skeleton.scaleY = calcMatrix.scaleY * -1;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
skeletonRenderer.ctx = context;
skeletonRenderer.debugRendering = (plugin.drawDebug || src.drawDebug);
context.save();
skeletonRenderer.draw(skeleton);
context.restore();
};
module.exports = SpineGameObjectCanvasRenderer;

View file

@ -1,25 +1,25 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 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
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 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

@ -1,169 +1,169 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* Renders this Game Object with the WebGL 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 SpineGameObject#renderWebGL
* @since 3.19.0
* @private
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
* @param {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 plugin = src.plugin;
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var sceneRenderer = plugin.sceneRenderer;
var GameObjectRenderMask = 15;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
// If there is already a batch running, and the next type isn't a Spine object, or this is the end, we need to close it
if (sceneRenderer.batcher.isDrawing && (!renderer.nextTypeMatch || renderer.finalType))
{
// The next object in the display list is not a Spine object, so we end the batch
sceneRenderer.end();
renderer.rebindPipeline();
}
if (!renderer.finalType)
{
// Reset the current type
renderer.currentType = '';
}
return;
}
if (renderer.newType)
{
// flush + clear previous pipeline if this is a new type
renderer.clearPipeline();
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(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 viewportHeight = renderer.height;
skeleton.x = calcMatrix.tx;
skeleton.y = viewportHeight - calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
skeleton.scaleY = calcMatrix.scaleY;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
if (renderer.newType)
{
sceneRenderer.begin();
}
// Draw the current skeleton
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
if (plugin.drawDebug || src.drawDebug)
{
// Because if we don't, the bones render positions are completely wrong (*sigh*)
var oldX = skeleton.x;
var oldY = skeleton.y;
skeleton.x = 0;
skeleton.y = 0;
sceneRenderer.drawSkeletonDebug(skeleton, src.preMultipliedAlpha);
skeleton.x = oldX;
skeleton.y = oldY;
}
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
// And rebind the previous pipeline
renderer.rebindPipeline();
}
};
module.exports = SpineGameObjectWebGLRenderer;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var CounterClockwise = require('../../../../src/math/angle/CounterClockwise');
var RadToDeg = require('../../../../src/math/RadToDeg');
var Wrap = require('../../../../src/math/Wrap');
/**
* Renders this Game Object with the WebGL 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 SpineGameObject#renderWebGL
* @since 3.19.0
* @private
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
* @param {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 plugin = src.plugin;
var skeleton = src.skeleton;
var childAlpha = skeleton.color.a;
var sceneRenderer = plugin.sceneRenderer;
var GameObjectRenderMask = 15;
var willRender = !(GameObjectRenderMask !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || childAlpha === 0);
if (!skeleton || !willRender)
{
// If there is already a batch running, and the next type isn't a Spine object, or this is the end, we need to close it
if (sceneRenderer.batcher.isDrawing && (!renderer.nextTypeMatch || renderer.finalType))
{
// The next object in the display list is not a Spine object, so we end the batch
sceneRenderer.end();
renderer.pipelines.rebind();
}
if (!renderer.finalType)
{
// Reset the current type
renderer.currentType = '';
}
return;
}
if (renderer.newType)
{
// flush + clear previous pipeline if this is a new type
renderer.pipelines.clear();
}
var camMatrix = renderer._tempMatrix1;
var spriteMatrix = renderer._tempMatrix2;
var calcMatrix = renderer._tempMatrix3;
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(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 viewportHeight = renderer.height;
skeleton.x = calcMatrix.tx;
skeleton.y = viewportHeight - calcMatrix.ty;
skeleton.scaleX = calcMatrix.scaleX;
skeleton.scaleY = calcMatrix.scaleY;
if (src.scaleX < 0)
{
skeleton.scaleX *= -1;
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
}
else
{
// +90 degrees to account for the difference in Spine vs. Phaser rotation
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
}
if (src.scaleY < 0)
{
skeleton.scaleY *= -1;
if (src.scaleX < 0)
{
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
else
{
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
}
}
if (camera.renderToTexture || renderer.currentFramebuffer !== null)
{
skeleton.y = calcMatrix.ty;
skeleton.scaleY *= -1;
}
// Add autoUpdate option
skeleton.updateWorldTransform();
if (renderer.newType)
{
sceneRenderer.begin();
}
// Draw the current skeleton
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
if (plugin.drawDebug || src.drawDebug)
{
// Because if we don't, the bones render positions are completely wrong (*sigh*)
var oldX = skeleton.x;
var oldY = skeleton.y;
skeleton.x = 0;
skeleton.y = 0;
sceneRenderer.drawSkeletonDebug(skeleton, src.preMultipliedAlpha);
skeleton.x = oldX;
skeleton.y = oldY;
}
if (!renderer.nextTypeMatch)
{
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
sceneRenderer.end();
// And rebind the previous pipeline
renderer.pipelines.rebind();
}
};
module.exports = SpineGameObjectWebGLRenderer;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,80 +1,80 @@
'use strict';
const webpack = require('webpack');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpinePluginDebug': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window',
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-both.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-both.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-both.js'
}
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new RemovePlugin({
before: {
root: './plugins/spine/dist/',
include: [ 'SpinePluginDebug.js', 'SpinePluginDebug.js.map' ]
}
}),
{
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'
};
'use strict';
const webpack = require('webpack');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpinePluginDebug': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window',
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-both.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-both.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-both.js'
}
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new RemovePlugin({
before: {
root: './plugins/spine/dist/',
include: [ 'SpinePluginDebug.js', 'SpinePluginDebug.js.map' ]
}
}),
{
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

@ -1,94 +1,94 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpinePlugin': './SpinePlugin.js',
'SpinePlugin.min': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window'
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-both.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-both.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-both.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 RemovePlugin({
before: {
root: './plugins/spine/dist/',
include: [ 'SpinePlugin.js', 'SpinePlugin.min.js' ]
}
}),
{
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);
});
});
}
}
]
};
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpinePlugin': './SpinePlugin.js',
'SpinePlugin.min': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window'
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-both.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-both.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-both.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 RemovePlugin({
before: {
root: './plugins/spine/dist/',
include: [ 'SpinePlugin.js', 'SpinePlugin.min.js' ]
}
}),
{
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

@ -1,82 +1,82 @@
'use strict';
const webpack = require('webpack');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpineCanvasPluginDebug': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window',
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'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-canvas.js'
}
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(false)
}),
new RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineCanvasPluginDebug.js', 'SpineCanvasPluginDebug.js.map' ]
}
}
}),
{
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'
};
'use strict';
const webpack = require('webpack');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpineCanvasPluginDebug': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window',
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'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-canvas.js'
}
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(true),
"typeof WEBGL_RENDERER": JSON.stringify(false)
}),
new RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineCanvasPluginDebug.js', 'SpineCanvasPluginDebug.js.map' ]
}
}
}),
{
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

@ -1,96 +1,96 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpineCanvasPlugin': './SpinePlugin.js',
'SpineCanvasPlugin.min': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window'
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-canvas.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 RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineCanvasPlugin.js', 'SpineCanvasPlugin.min.js' ]
}
}
}),
{
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);
});
});
}
}
]
};
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpineCanvasPlugin': './SpinePlugin.js',
'SpineCanvasPlugin.min': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window'
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-canvas.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-canvas.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 RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineCanvasPlugin.js', 'SpineCanvasPlugin.min.js' ]
}
}
}),
{
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

@ -1,82 +1,82 @@
'use strict';
const webpack = require('webpack');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpineWebGLPluginDebug': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window',
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-webgl.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-webgl.js'
},
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(false),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineWebGLPluginDebug.js', 'SpineWebGLPluginDebug.js.map' ]
}
}
}),
{
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'
};
'use strict';
const webpack = require('webpack');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'development',
context: `${__dirname}/src/`,
entry: {
'SpineWebGLPluginDebug': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window',
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-webgl.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './runtimes/spine-webgl.js'
},
},
plugins: [
new webpack.DefinePlugin({
"typeof CANVAS_RENDERER": JSON.stringify(false),
"typeof WEBGL_RENDERER": JSON.stringify(true)
}),
new RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineWebGLPluginDebug.js', 'SpineWebGLPluginDebug.js.map' ]
}
}
}),
{
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

@ -1,96 +1,96 @@
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpineWebGLPlugin': './SpinePlugin.js',
'SpineWebGLPlugin.min': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window'
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './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 RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineWebGLPlugin.js', 'SpineWebGLPlugin.min.js' ]
}
}
}),
{
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);
});
});
}
}
]
};
'use strict';
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const exec = require('child_process').exec;
const RemovePlugin = require('remove-files-webpack-plugin');
module.exports = {
mode: 'production',
context: `${__dirname}/src/`,
entry: {
'SpineWebGLPlugin': './SpinePlugin.js',
'SpineWebGLPlugin.min': './SpinePlugin.js'
},
output: {
path: `${__dirname}/dist/`,
filename: '[name].js',
library: 'SpinePlugin',
libraryTarget: 'window'
},
performance: { hints: false },
module: {
rules: [
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
loader: 'imports-loader',
options: {
type: 'commonjs',
wrapper: 'window'
}
},
{
test: require.resolve('./src/runtimes/spine-webgl.js'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single spine'
}
}
]
},
resolve: {
alias: {
'Spine': './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 RemovePlugin({
before: {
before: {
root: './plugins/spine/dist/',
include: [ 'SpineWebGLPlugin.js', 'SpineWebGLPlugin.min.js' ]
}
}
}),
{
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

@ -1,57 +1,57 @@
let fs = require('fs-extra');
/*
BitmapMask.frag
BitmapMask.vert
Light.frag
Single.frag
Single.vert
Multi.frag
Multi.vert
*/
let srcdir = './src/renderer/webgl/shaders/src/';
let destdir = './src/renderer/webgl/shaders/';
let files = fs.readdirSync(srcdir);
files.forEach(function (file) {
let shaderSource = fs.readFileSync(srcdir + file, 'utf8');
let type = file.substr(-4);
let shaderFilename = file.substr(0, file.lastIndexOf('.')) + '-' + type + '.js';
let outputSource = 'module.exports = [\n';
let lines = shaderSource.split('\n');
for (var i = 0; i < lines.length; i++)
{
let line = lines[i].trimRight();
if (i < lines.length - 1)
{
outputSource = outputSource.concat(" '" + line + "',\n");
}
else
{
outputSource = outputSource.concat(" '" + line + "'\n");
}
}
outputSource = outputSource.concat('].join(\'\\n\');\n');
fs.writeFile(destdir + shaderFilename, outputSource, function (error) {
if (error)
{
throw error;
}
else
{
console.log('Saved', shaderFilename);
}
});
});
let fs = require('fs-extra');
/*
BitmapMask.frag
BitmapMask.vert
Light.frag
Single.frag
Single.vert
Multi.frag
Multi.vert
*/
let srcdir = './src/renderer/webgl/shaders/src/';
let destdir = './src/renderer/webgl/shaders/';
let files = fs.readdirSync(srcdir);
files.forEach(function (file) {
let shaderSource = fs.readFileSync(srcdir + file, 'utf8');
let type = file.substr(-4);
let shaderFilename = file.substr(0, file.lastIndexOf('.')) + '-' + type + '.js';
let outputSource = 'module.exports = [\n';
let lines = shaderSource.split('\n');
for (var i = 0; i < lines.length; i++)
{
let line = lines[i].trimRight();
if (i < lines.length - 1)
{
outputSource = outputSource.concat(" '" + line + "',\n");
}
else
{
outputSource = outputSource.concat(" '" + line + "'\n");
}
}
outputSource = outputSource.concat('].join(\'\\n\');\n');
fs.writeFile(destdir + shaderFilename, outputSource, function (error) {
if (error)
{
throw error;
}
else
{
console.log('Saved', shaderFilename);
}
});
});

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.publish = void 0;
const fs = require("fs-extra");
const path = require("path");
const Parser_1 = require("./Parser");
function publish(data, opts) {
// remove undocumented stuff.
data({ undocumented: true }).remove();
// remove package data
data({ kind: 'package' }).remove();
// remove header comments
data({ copyright: { isString: true } }).remove();
// remove private members
data({ access: 'private' }).remove();
// remove ignored doclets
data({ ignore: true }).remove();
if (!fs.existsSync(opts.destination)) {
fs.mkdirSync(opts.destination);
}
var out = new Parser_1.Parser(data().get()).emit();
fs.writeFileSync(path.join(opts.destination, 'phaser.d.ts'), out);
}
exports.publish = publish;
;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.publish = void 0;
const fs = require("fs-extra");
const path = require("path");
const Parser_1 = require("./Parser");
function publish(data, opts) {
// remove undocumented stuff.
data({ undocumented: true }).remove();
// remove package data
data({ kind: 'package' }).remove();
// remove header comments
data({ copyright: { isString: true } }).remove();
// remove private members
data({ access: 'private' }).remove();
// remove ignored doclets
data({ ignore: true }).remove();
if (!fs.existsSync(opts.destination)) {
fs.mkdirSync(opts.destination);
}
var out = new Parser_1.Parser(data().get()).emit();
fs.writeFileSync(path.join(opts.destination, 'phaser.d.ts'), out);
}
exports.publish = publish;
;
//# sourceMappingURL=publish.js.map

View file

@ -1,35 +1,35 @@
let scene:Phaser.Scene = new Phaser.Scene("");
let blitter = new Phaser.GameObjects.Blitter(scene, 10, 10);
let conf:GameConfig = {
type:Phaser.AUTO,
width: 100,
height: 100,
zoom: 1,
resolution: 1
}
let tex:Phaser.Textures.Texture = <any>null;
tex.source[0].setFilter(Phaser.Textures.FilterMode.LINEAR);
tex.setFilter(Phaser.Textures.FilterMode.LINEAR);
tex.setFilter(Phaser.Textures.NEAREST);
let sprite = new Phaser.GameObjects.Sprite(scene, 0, 0, "test");
class MyVec extends Phaser.Geom.Rectangle {
public extra() {
}
}
let p = new MyVec();
sprite.getBounds(p).extra();
let container = scene.add.container(0, 0);
container.getWorldTransformMatrix();
let scene:Phaser.Scene = new Phaser.Scene("");
let blitter = new Phaser.GameObjects.Blitter(scene, 10, 10);
let conf:GameConfig = {
type:Phaser.AUTO,
width: 100,
height: 100,
zoom: 1,
resolution: 1
}
let tex:Phaser.Textures.Texture = <any>null;
tex.source[0].setFilter(Phaser.Textures.FilterMode.LINEAR);
tex.setFilter(Phaser.Textures.FilterMode.LINEAR);
tex.setFilter(Phaser.Textures.NEAREST);
let sprite = new Phaser.GameObjects.Sprite(scene, 0, 0, "test");
class MyVec extends Phaser.Geom.Rectangle {
public extra() {
}
}
let p = new MyVec();
sprite.getBounds(p).extra();
let container = scene.add.container(0, 0);
container.getWorldTransformMatrix();

View file

@ -1,26 +1,26 @@
{
"compilerOptions": {
"module": "system",
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"preserveConstEnums": true,
"outFile": "./bin/game.js",
"sourceMap": true,
"moduleResolution": "node",
"lib": [
"dom",
"scripthost",
"es5"
]
},
"include": [
"src/game.ts",
"../../../types/phaser.d.ts"
],
"exclude": [
"node_modules",
"../../../node_modules/@types"
]
}
{
"compilerOptions": {
"module": "system",
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"preserveConstEnums": true,
"outFile": "./bin/game.js",
"sourceMap": true,
"moduleResolution": "node",
"lib": [
"dom",
"scripthost",
"es5"
]
},
"include": [
"src/game.ts",
"../../../types/phaser.d.ts"
],
"exclude": [
"node_modules",
"../../../node_modules/@types"
]
}

View file

@ -1,113 +1,113 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var AlignIn = require('../display/align/in/QuickSet');
var CONST = require('../display/align/const');
var GetFastValue = require('../utils/object/GetFastValue');
var NOOP = require('../utils/NOOP');
var Zone = require('../gameobjects/zone/Zone');
var tempZone = new Zone({ sys: { queueDepthSort: NOOP, events: { once: NOOP } } }, 0, 0, 1, 1);
/**
* Takes an array of Game Objects, or any objects that have public `x` and `y` properties,
* and then aligns them based on the grid configuration given to this action.
*
* @function Phaser.Actions.GridAlign
* @since 3.0.0
*
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action.
* @param {Phaser.Types.Actions.GridAlignConfig} options - The GridAlign Configuration object.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action.
*/
var GridAlign = function (items, options)
{
if (options === undefined) { options = {}; }
var widthSet = options.hasOwnProperty('width');
var heightSet = options.hasOwnProperty('height');
var width = GetFastValue(options, 'width', -1);
var height = GetFastValue(options, 'height', -1);
var cellWidth = GetFastValue(options, 'cellWidth', 1);
var cellHeight = GetFastValue(options, 'cellHeight', cellWidth);
var position = GetFastValue(options, 'position', CONST.TOP_LEFT);
var x = GetFastValue(options, 'x', 0);
var y = GetFastValue(options, 'y', 0);
var cx = 0;
var cy = 0;
var w = (width * cellWidth);
var h = (height * cellHeight);
tempZone.setPosition(x, y);
tempZone.setSize(cellWidth, cellHeight);
for (var i = 0; i < items.length; i++)
{
AlignIn(items[i], tempZone, position);
if (widthSet && width === -1)
{
// We keep laying them out horizontally until we've done them all
tempZone.x += cellWidth;
}
else if (heightSet && height === -1)
{
// We keep laying them out vertically until we've done them all
tempZone.y += cellHeight;
}
else if (heightSet && !widthSet)
{
// We keep laying them out until we hit the column limit
cy += cellHeight;
tempZone.y += cellHeight;
if (cy === h)
{
cy = 0;
cx += cellWidth;
tempZone.y = y;
tempZone.x += cellWidth;
if (cx === w)
{
// We've hit the column limit, so return, even if there are items left
break;
}
}
}
else
{
// We keep laying them out until we hit the column limit
cx += cellWidth;
tempZone.x += cellWidth;
if (cx === w)
{
cx = 0;
cy += cellHeight;
tempZone.x = x;
tempZone.y += cellHeight;
if (cy === h)
{
// We've hit the column limit, so return, even if there are items left
break;
}
}
}
}
return items;
};
module.exports = GridAlign;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var AlignIn = require('../display/align/in/QuickSet');
var CONST = require('../display/align/const');
var GetFastValue = require('../utils/object/GetFastValue');
var NOOP = require('../utils/NOOP');
var Zone = require('../gameobjects/zone/Zone');
var tempZone = new Zone({ sys: { queueDepthSort: NOOP, events: { once: NOOP } } }, 0, 0, 1, 1);
/**
* Takes an array of Game Objects, or any objects that have public `x` and `y` properties,
* and then aligns them based on the grid configuration given to this action.
*
* @function Phaser.Actions.GridAlign
* @since 3.0.0
*
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action.
* @param {Phaser.Types.Actions.GridAlignConfig} options - The GridAlign Configuration object.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action.
*/
var GridAlign = function (items, options)
{
if (options === undefined) { options = {}; }
var widthSet = options.hasOwnProperty('width');
var heightSet = options.hasOwnProperty('height');
var width = GetFastValue(options, 'width', -1);
var height = GetFastValue(options, 'height', -1);
var cellWidth = GetFastValue(options, 'cellWidth', 1);
var cellHeight = GetFastValue(options, 'cellHeight', cellWidth);
var position = GetFastValue(options, 'position', CONST.TOP_LEFT);
var x = GetFastValue(options, 'x', 0);
var y = GetFastValue(options, 'y', 0);
var cx = 0;
var cy = 0;
var w = (width * cellWidth);
var h = (height * cellHeight);
tempZone.setPosition(x, y);
tempZone.setSize(cellWidth, cellHeight);
for (var i = 0; i < items.length; i++)
{
AlignIn(items[i], tempZone, position);
if (widthSet && width === -1)
{
// We keep laying them out horizontally until we've done them all
tempZone.x += cellWidth;
}
else if (heightSet && height === -1)
{
// We keep laying them out vertically until we've done them all
tempZone.y += cellHeight;
}
else if (heightSet && !widthSet)
{
// We keep laying them out until we hit the column limit
cy += cellHeight;
tempZone.y += cellHeight;
if (cy === h)
{
cy = 0;
cx += cellWidth;
tempZone.y = y;
tempZone.x += cellWidth;
if (cx === w)
{
// We've hit the column limit, so return, even if there are items left
break;
}
}
}
else
{
// We keep laying them out until we hit the column limit
cx += cellWidth;
tempZone.x += cellWidth;
if (cx === w)
{
cx = 0;
cy += cellHeight;
tempZone.x = x;
tempZone.y += cellHeight;
if (cy === h)
{
// We've hit the column limit, so return, even if there are items left
break;
}
}
}
}
return items;
};
module.exports = GridAlign;

View file

@ -1,47 +1,47 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var PropertyValueSet = require('./PropertyValueSet');
/**
* Takes an array of Game Objects, or any objects that have the public properties `originX` and `originY`
* and then sets them to the given values.
*
* The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array.
*
* To use this with a Group: `SetOrigin(group.getChildren(), originX, originY, stepX, stepY)`
*
* @function Phaser.Actions.SetOrigin
* @since 3.0.0
*
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action.
* @param {number} originX - The amount to set the `originX` property to.
* @param {number} [originY] - The amount to set the `originY` property to. If `undefined` or `null` it uses the `originX` value.
* @param {number} [stepX=0] - This is added to the `originX` amount, multiplied by the iteration counter.
* @param {number} [stepY=0] - This is added to the `originY` amount, multiplied by the iteration counter.
* @param {integer} [index=0] - An optional offset to start searching from within the items array.
* @param {integer} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action.
*/
var SetOrigin = function (items, originX, originY, stepX, stepY, index, direction)
{
if (originY === undefined || originY === null) { originY = originX; }
PropertyValueSet(items, 'originX', originX, stepX, index, direction);
PropertyValueSet(items, 'originY', originY, stepY, index, direction);
items.forEach(function (item)
{
item.updateDisplayOrigin();
});
return items;
};
module.exports = SetOrigin;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var PropertyValueSet = require('./PropertyValueSet');
/**
* Takes an array of Game Objects, or any objects that have the public properties `originX` and `originY`
* and then sets them to the given values.
*
* The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array.
*
* To use this with a Group: `SetOrigin(group.getChildren(), originX, originY, stepX, stepY)`
*
* @function Phaser.Actions.SetOrigin
* @since 3.0.0
*
* @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
*
* @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action.
* @param {number} originX - The amount to set the `originX` property to.
* @param {number} [originY] - The amount to set the `originY` property to. If `undefined` or `null` it uses the `originX` value.
* @param {number} [stepX=0] - This is added to the `originX` amount, multiplied by the iteration counter.
* @param {number} [stepY=0] - This is added to the `originY` amount, multiplied by the iteration counter.
* @param {integer} [index=0] - An optional offset to start searching from within the items array.
* @param {integer} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning.
*
* @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action.
*/
var SetOrigin = function (items, originX, originY, stepX, stepY, index, direction)
{
if (originY === undefined || originY === null) { originY = originX; }
PropertyValueSet(items, 'originX', originX, stepX, index, direction);
PropertyValueSet(items, 'originY', originY, stepY, index, direction);
items.forEach(function (item)
{
item.updateDisplayOrigin();
});
return items;
};
module.exports = SetOrigin;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,39 +1,40 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Complete Event.
*
* This event is dispatched by a Sprite when an animation playing on it completes playback.
* This happens when the animation gets to the end of its sequence, factoring in any delays
* or repeats it may have to process.
*
* An animation that is set to loop, or repeat forever, will never fire this event, because
* it never actually completes. If you need to handle this, listen for the `ANIMATION_STOP`
* event instead, as this is emitted when the animation is stopped directly.
*
* Listen for it on the Sprite using `sprite.on('animationcomplete', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_COMPLETE
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationcomplete';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Complete Event.
*
* This event is dispatched by a Sprite when an animation playing on it completes playback.
* This happens when the animation gets to the end of its sequence, factoring in any delays
* or repeats it may have to process.
*
* An animation that is set to loop, or repeat forever, will never fire this event, because
* it never actually completes. If you need to handle this, listen for the `ANIMATION_STOP`
* event instead, as this is emitted when the animation is stopped directly.
*
* Listen for it on the Sprite using `sprite.on('animationcomplete', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_COMPLETE
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationcomplete';

View file

@ -0,0 +1,44 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Complete Dynamic Key Event.
*
* This event is dispatched by a Sprite when an animation playing on it completes playback.
* This happens when the animation gets to the end of its sequence, factoring in any delays
* or repeats it may have to process.
*
* An animation that is set to loop, or repeat forever, will never fire this event, because
* it never actually completes. If you need to handle this, listen for the `ANIMATION_STOP`
* event instead, as this is emitted when the animation is stopped directly.
*
* The difference between this and the `ANIMATION_COMPLETE` event is that this one has a
* dynamic event name that contains the name of the animation within it. For example,
* if you had an animation called `explode` you could listen for the completion of that
* specific animation by using: `sprite.on('animationcomplete-explode', listener)`. Or, if you
* wish to use types: `sprite.on(Phaser.Animations.Events.ANIMATION_COMPLETE_KEY + 'explode', listener)`.
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_COMPLETE_KEY
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationcomplete-';

View file

@ -1,36 +1,37 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Repeat Event.
*
* This event is dispatched by a Sprite when an animation repeats playing on it.
* This happens if the animation was created, or played, with a `repeat` value specified.
*
* An animation will repeat when it reaches the end of its sequence.
*
* Listen for it on the Sprite using `sprite.on('animationrepeat', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_REPEAT
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has repeated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation repeated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationrepeat';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Repeat Event.
*
* This event is dispatched by a Sprite when an animation repeats playing on it.
* This happens if the animation was created, or played, with a `repeat` value specified.
*
* An animation will repeat when it reaches the end of its sequence.
*
* Listen for it on the Sprite using `sprite.on('animationrepeat', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_REPEAT
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has repeated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation repeated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationrepeat';

View file

@ -1,34 +1,35 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Restart Event.
*
* This event is dispatched by a Sprite when an animation restarts playing on it.
* This only happens when the `Sprite.anims.restart` method is called.
*
* Listen for it on the Sprite using `sprite.on('animationrestart', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_RESTART
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has restarted.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationrestart';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Restart Event.
*
* This event is dispatched by a Sprite when an animation restarts playing on it.
* This only happens when the `Sprite.anims.restart` method is called.
*
* Listen for it on the Sprite using `sprite.on('animationrestart', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_RESTART
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has restarted.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationrestart';

View file

@ -1,35 +1,36 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Start Event.
*
* This event is dispatched by a Sprite when an animation starts playing on it.
* This happens when the animation is played, factoring in any delay that may have been specified.
* This event happens after the delay has expired and prior to the first update event.
*
* Listen for it on the Sprite using `sprite.on('animationstart', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_START
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has started.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationstart';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Start Event.
*
* This event is dispatched by a Sprite when an animation starts playing on it.
* This happens when the animation is played, factoring in any delay that may have been specified.
* This event happens after the delay has expired and prior to the first update event.
*
* Listen for it on the Sprite using `sprite.on('animationstart', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_START
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has started.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationstart';

View file

@ -1,35 +1,36 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Stop Event.
*
* This event is dispatched by a Sprite when an animation is stopped on it. An animation
* will only be stopeed if a method such as `Sprite.stop` or `Sprite.anims.stopAfterDelay`
* is called. It can also be emitted if a new animation is started before the current one completes.
*
* Listen for it on the Sprite using `sprite.on('animationstop', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_STOP
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has stopped.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation stopped.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationstop';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Stop Event.
*
* This event is dispatched by a Sprite when an animation is stopped on it. An animation
* will only be stopeed if a method such as `Sprite.stop` or `Sprite.anims.stopAfterDelay`
* is called. It can also be emitted if a new animation is started before the current one completes.
*
* Listen for it on the Sprite using `sprite.on('animationstop', listener)`
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_STOP
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has stopped.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation stopped.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationstop';

View file

@ -1,39 +1,40 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Update Event.
*
* This event is dispatched by a Sprite when an animation playing on it updates. This happens when the animation changes frame.
* An animation will change frame based on the frme rate and other factors like `timeScale` and `delay`. It can also change
* frame when stopped or restarted.
*
* Listen for it on the Sprite using `sprite.on('animationupdate', listener)`
*
* If an animation is playing faster than the game frame-rate can handle, it's entirely possible for it to emit several
* update events in a single game frame, so please be aware of this in your code. The **final** event received that frame
* is the one that is rendered to the game.
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_UPDATE
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has updated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationupdate';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Animation Update Event.
*
* This event is dispatched by a Sprite when an animation playing on it updates. This happens when the animation changes frame.
* An animation will change frame based on the frme rate and other factors like `timeScale` and `delay`. It can also change
* frame when stopped or restarted.
*
* Listen for it on the Sprite using `sprite.on('animationupdate', listener)`
*
* If an animation is playing faster than the game frame-rate can handle, it's entirely possible for it to emit several
* update events in a single game frame, so please be aware of this in your code. The **final** event received that frame
* is the one that is rendered to the game.
*
* The animation event flow is as follows:
*
* 1. `ANIMATION_START`
* 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has)
* 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this)
* 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count)
* 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count)
*
* If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`.
*
* If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted.
*
* @event Phaser.Animations.Events#ANIMATION_UPDATE
* @since 3.50.0
*
* @param {Phaser.Animations.Animation} animation - A reference to the Animation that has updated.
* @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation.
* @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated.
* @param {string} frameKey - The unique key of the Animation Frame within the Animation.
*/
module.exports = 'animationupdate';

View file

@ -1,24 +1,25 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Animations.Events
*/
module.exports = {
ADD_ANIMATION: require('./ADD_ANIMATION_EVENT'),
ANIMATION_COMPLETE: require('./ANIMATION_COMPLETE_EVENT'),
ANIMATION_REPEAT: require('./ANIMATION_REPEAT_EVENT'),
ANIMATION_RESTART: require('./ANIMATION_RESTART_EVENT'),
ANIMATION_START: require('./ANIMATION_START_EVENT'),
ANIMATION_STOP: require('./ANIMATION_STOP_EVENT'),
ANIMATION_UPDATE: require('./ANIMATION_UPDATE_EVENT'),
PAUSE_ALL: require('./PAUSE_ALL_EVENT'),
REMOVE_ANIMATION: require('./REMOVE_ANIMATION_EVENT'),
RESUME_ALL: require('./RESUME_ALL_EVENT')
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Animations.Events
*/
module.exports = {
ADD_ANIMATION: require('./ADD_ANIMATION_EVENT'),
ANIMATION_COMPLETE: require('./ANIMATION_COMPLETE_EVENT'),
ANIMATION_COMPLETE_KEY: require('./ANIMATION_COMPLETE_KEY_EVENT'),
ANIMATION_REPEAT: require('./ANIMATION_REPEAT_EVENT'),
ANIMATION_RESTART: require('./ANIMATION_RESTART_EVENT'),
ANIMATION_START: require('./ANIMATION_START_EVENT'),
ANIMATION_STOP: require('./ANIMATION_STOP_EVENT'),
ANIMATION_UPDATE: require('./ANIMATION_UPDATE_EVENT'),
PAUSE_ALL: require('./PAUSE_ALL_EVENT'),
REMOVE_ANIMATION: require('./REMOVE_ANIMATION_EVENT'),
RESUME_ALL: require('./RESUME_ALL_EVENT')
};

View file

@ -1,19 +1,19 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Animations
*/
module.exports = {
Animation: require('./Animation'),
AnimationFrame: require('./AnimationFrame'),
AnimationManager: require('./AnimationManager'),
AnimationState: require('./AnimationState'),
Events: require('./events')
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Animations
*/
module.exports = {
Animation: require('./Animation'),
AnimationFrame: require('./AnimationFrame'),
AnimationManager: require('./AnimationManager'),
AnimationState: require('./AnimationState'),
Events: require('./events')
};

View file

@ -1,18 +1,18 @@
/**
* @typedef {object} Phaser.Types.Animations.Animation
* @since 3.0.0
*
* @property {string} [key] - The key that the animation will be associated with. i.e. sprite.animations.play(key)
* @property {string|Phaser.Types.Animations.AnimationFrame[]} [frames] - Either a string, in which case it will use all frames from a texture with the matching key, or an array of Animation Frame configuration objects.
* @property {boolean} [sortFrames=true] - If you provide a string for `frames` you can optionally have the frame names numerically sorted.
* @property {string} [defaultTextureKey=null] - The key of the texture all frames of the animation will use. Can be overridden on a per frame basis.
* @property {integer} [frameRate] - The frame rate of playback in frames per second (default 24 if duration is null)
* @property {integer} [duration] - How long the animation should play for in milliseconds. If not given its derived from frameRate.
* @property {boolean} [skipMissedFrames=true] - Skip frames if the time lags, or always advanced anyway?
* @property {integer} [delay=0] - Delay before starting playback. Value given in milliseconds.
* @property {integer} [repeat=0] - Number of times to repeat the animation (-1 for infinity)
* @property {integer} [repeatDelay=0] - Delay before the animation repeats. Value given in milliseconds.
* @property {boolean} [yoyo=false] - Should the animation yoyo? (reverse back down to the start) before repeating?
* @property {boolean} [showOnStart=false] - Should sprite.visible = true when the animation starts to play?
* @property {boolean} [hideOnComplete=false] - Should sprite.visible = false when the animation finishes?
*/
/**
* @typedef {object} Phaser.Types.Animations.Animation
* @since 3.0.0
*
* @property {string} [key] - The key that the animation will be associated with. i.e. sprite.animations.play(key)
* @property {string|Phaser.Types.Animations.AnimationFrame[]} [frames] - Either a string, in which case it will use all frames from a texture with the matching key, or an array of Animation Frame configuration objects.
* @property {boolean} [sortFrames=true] - If you provide a string for `frames` you can optionally have the frame names numerically sorted.
* @property {string} [defaultTextureKey=null] - The key of the texture all frames of the animation will use. Can be overridden on a per frame basis.
* @property {integer} [frameRate] - The frame rate of playback in frames per second (default 24 if duration is null)
* @property {integer} [duration] - How long the animation should play for in milliseconds. If not given its derived from frameRate.
* @property {boolean} [skipMissedFrames=true] - Skip frames if the time lags, or always advanced anyway?
* @property {integer} [delay=0] - Delay before starting playback. Value given in milliseconds.
* @property {integer} [repeat=0] - Number of times to repeat the animation (-1 for infinity)
* @property {integer} [repeatDelay=0] - Delay before the animation repeats. Value given in milliseconds.
* @property {boolean} [yoyo=false] - Should the animation yoyo? (reverse back down to the start) before repeating?
* @property {boolean} [showOnStart=false] - Should sprite.visible = true when the animation starts to play?
* @property {boolean} [hideOnComplete=false] - Should sprite.visible = false when the animation finishes?
*/

View file

@ -1,9 +1,9 @@
/**
* @typedef {object} Phaser.Types.Animations.AnimationFrame
* @since 3.0.0
*
* @property {string} key - The key of the texture within the Texture Manager to use for this Animation Frame.
* @property {(string|number)} [frame] - The key, or index number, of the frame within the texture to use for this Animation Frame.
* @property {number} [duration=0] - The duration, in ms, of this frame of the animation.
* @property {boolean} [visible] - Should the parent Game Object be visible during this frame of the animation?
*/
/**
* @typedef {object} Phaser.Types.Animations.AnimationFrame
* @since 3.0.0
*
* @property {string} key - The key of the texture within the Texture Manager to use for this Animation Frame.
* @property {(string|number)} [frame] - The key, or index number, of the frame within the texture to use for this Animation Frame.
* @property {number} [duration=0] - The duration, in ms, of this frame of the animation.
* @property {boolean} [visible] - Should the parent Game Object be visible during this frame of the animation?
*/

View file

@ -1,16 +1,16 @@
/**
* @typedef {object} Phaser.Types.Animations.PlayAnimationConfig
* @since 3.50.0
*
* @property {(string|Phaser.Animations.Animation)} key - The string-based key of the animation to play, or an Animation instance.
* @property {integer} [frameRate] - The frame rate of playback in frames per second (default 24 if duration is null)
* @property {integer} [duration] - How long the animation should play for in milliseconds. If not given its derived from frameRate.
* @property {integer} [delay] - Delay before starting playback. Value given in milliseconds.
* @property {integer} [repeat] - Number of times to repeat the animation (-1 for infinity)
* @property {integer} [repeatDelay] - Delay before the animation repeats. Value given in milliseconds.
* @property {boolean} [yoyo] - Should the animation yoyo? (reverse back down to the start) before repeating?
* @property {boolean} [showOnStart] - Should sprite.visible = true when the animation starts to play?
* @property {boolean} [hideOnComplete] - Should sprite.visible = false when the animation finishes?
* @property {integer} [startFrame] - The frame of the animation to start playback from.
* @property {number} [timeScale] - The time scale to be applied to playback of this animation.
*/
/**
* @typedef {object} Phaser.Types.Animations.PlayAnimationConfig
* @since 3.50.0
*
* @property {(string|Phaser.Animations.Animation)} key - The string-based key of the animation to play, or an Animation instance.
* @property {integer} [frameRate] - The frame rate of playback in frames per second (default 24 if duration is null)
* @property {integer} [duration] - How long the animation should play for in milliseconds. If not given its derived from frameRate.
* @property {integer} [delay] - Delay before starting playback. Value given in milliseconds.
* @property {integer} [repeat] - Number of times to repeat the animation (-1 for infinity)
* @property {integer} [repeatDelay] - Delay before the animation repeats. Value given in milliseconds.
* @property {boolean} [yoyo] - Should the animation yoyo? (reverse back down to the start) before repeating?
* @property {boolean} [showOnStart] - Should sprite.visible = true when the animation starts to play?
* @property {boolean} [hideOnComplete] - Should sprite.visible = false when the animation finishes?
* @property {integer} [startFrame] - The frame of the animation to start playback from.
* @property {number} [timeScale] - The time scale to be applied to playback of this animation.
*/

360
src/cache/BaseCache.js vendored
View file

@ -1,180 +1,180 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../utils/Class');
var CustomMap = require('../structs/Map');
var EventEmitter = require('eventemitter3');
var Events = require('./events');
/**
* @classdesc
* The BaseCache is a base Cache class that can be used for storing references to any kind of data.
*
* Data can be added, retrieved and removed based on the given keys.
*
* Keys are string-based.
*
* @class BaseCache
* @memberof Phaser.Cache
* @constructor
* @since 3.0.0
*/
var BaseCache = new Class({
initialize:
function BaseCache ()
{
/**
* The Map in which the cache objects are stored.
*
* You can query the Map directly or use the BaseCache methods.
*
* @name Phaser.Cache.BaseCache#entries
* @type {Phaser.Structs.Map.<String, *>}
* @since 3.0.0
*/
this.entries = new CustomMap();
/**
* An instance of EventEmitter used by the cache to emit related events.
*
* @name Phaser.Cache.BaseCache#events
* @type {Phaser.Events.EventEmitter}
* @since 3.0.0
*/
this.events = new EventEmitter();
},
/**
* Adds an item to this cache. The item is referenced by a unique string, which you are responsible
* for setting and keeping track of. The item can only be retrieved by using this string.
*
* @method Phaser.Cache.BaseCache#add
* @fires Phaser.Cache.Events#ADD
* @since 3.0.0
*
* @param {string} key - The unique key by which the data added to the cache will be referenced.
* @param {*} data - The data to be stored in the cache.
*
* @return {this} This BaseCache object.
*/
add: function (key, data)
{
this.entries.set(key, data);
this.events.emit(Events.ADD, this, key, data);
return this;
},
/**
* Checks if this cache contains an item matching the given key.
* This performs the same action as `BaseCache.exists`.
*
* @method Phaser.Cache.BaseCache#has
* @since 3.0.0
*
* @param {string} key - The unique key of the item to be checked in this cache.
*
* @return {boolean} Returns `true` if the cache contains an item matching the given key, otherwise `false`.
*/
has: function (key)
{
return this.entries.has(key);
},
/**
* Checks if this cache contains an item matching the given key.
* This performs the same action as `BaseCache.has` and is called directly by the Loader.
*
* @method Phaser.Cache.BaseCache#exists
* @since 3.7.0
*
* @param {string} key - The unique key of the item to be checked in this cache.
*
* @return {boolean} Returns `true` if the cache contains an item matching the given key, otherwise `false`.
*/
exists: function (key)
{
return this.entries.has(key);
},
/**
* Gets an item from this cache based on the given key.
*
* @method Phaser.Cache.BaseCache#get
* @since 3.0.0
*
* @param {string} key - The unique key of the item to be retrieved from this cache.
*
* @return {*} The item in the cache, or `null` if no item matching the given key was found.
*/
get: function (key)
{
return this.entries.get(key);
},
/**
* Removes and item from this cache based on the given key.
*
* If an entry matching the key is found it is removed from the cache and a `remove` event emitted.
* No additional checks are done on the item removed. If other systems or parts of your game code
* are relying on this item, it is up to you to sever those relationships prior to removing the item.
*
* @method Phaser.Cache.BaseCache#remove
* @fires Phaser.Cache.Events#REMOVE
* @since 3.0.0
*
* @param {string} key - The unique key of the item to remove from the cache.
*
* @return {this} This BaseCache object.
*/
remove: function (key)
{
var entry = this.get(key);
if (entry)
{
this.entries.delete(key);
this.events.emit(Events.REMOVE, this, key, entry.data);
}
return this;
},
/**
* Returns all keys in use in this cache.
*
* @method Phaser.Cache.BaseCache#getKeys
* @since 3.17.0
*
* @return {string[]} Array containing all the keys.
*/
getKeys: function ()
{
return this.entries.keys();
},
/**
* Destroys this cache and all items within it.
*
* @method Phaser.Cache.BaseCache#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.entries.clear();
this.events.removeAllListeners();
this.entries = null;
this.events = null;
}
});
module.exports = BaseCache;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../utils/Class');
var CustomMap = require('../structs/Map');
var EventEmitter = require('eventemitter3');
var Events = require('./events');
/**
* @classdesc
* The BaseCache is a base Cache class that can be used for storing references to any kind of data.
*
* Data can be added, retrieved and removed based on the given keys.
*
* Keys are string-based.
*
* @class BaseCache
* @memberof Phaser.Cache
* @constructor
* @since 3.0.0
*/
var BaseCache = new Class({
initialize:
function BaseCache ()
{
/**
* The Map in which the cache objects are stored.
*
* You can query the Map directly or use the BaseCache methods.
*
* @name Phaser.Cache.BaseCache#entries
* @type {Phaser.Structs.Map.<String, *>}
* @since 3.0.0
*/
this.entries = new CustomMap();
/**
* An instance of EventEmitter used by the cache to emit related events.
*
* @name Phaser.Cache.BaseCache#events
* @type {Phaser.Events.EventEmitter}
* @since 3.0.0
*/
this.events = new EventEmitter();
},
/**
* Adds an item to this cache. The item is referenced by a unique string, which you are responsible
* for setting and keeping track of. The item can only be retrieved by using this string.
*
* @method Phaser.Cache.BaseCache#add
* @fires Phaser.Cache.Events#ADD
* @since 3.0.0
*
* @param {string} key - The unique key by which the data added to the cache will be referenced.
* @param {*} data - The data to be stored in the cache.
*
* @return {this} This BaseCache object.
*/
add: function (key, data)
{
this.entries.set(key, data);
this.events.emit(Events.ADD, this, key, data);
return this;
},
/**
* Checks if this cache contains an item matching the given key.
* This performs the same action as `BaseCache.exists`.
*
* @method Phaser.Cache.BaseCache#has
* @since 3.0.0
*
* @param {string} key - The unique key of the item to be checked in this cache.
*
* @return {boolean} Returns `true` if the cache contains an item matching the given key, otherwise `false`.
*/
has: function (key)
{
return this.entries.has(key);
},
/**
* Checks if this cache contains an item matching the given key.
* This performs the same action as `BaseCache.has` and is called directly by the Loader.
*
* @method Phaser.Cache.BaseCache#exists
* @since 3.7.0
*
* @param {string} key - The unique key of the item to be checked in this cache.
*
* @return {boolean} Returns `true` if the cache contains an item matching the given key, otherwise `false`.
*/
exists: function (key)
{
return this.entries.has(key);
},
/**
* Gets an item from this cache based on the given key.
*
* @method Phaser.Cache.BaseCache#get
* @since 3.0.0
*
* @param {string} key - The unique key of the item to be retrieved from this cache.
*
* @return {*} The item in the cache, or `null` if no item matching the given key was found.
*/
get: function (key)
{
return this.entries.get(key);
},
/**
* Removes and item from this cache based on the given key.
*
* If an entry matching the key is found it is removed from the cache and a `remove` event emitted.
* No additional checks are done on the item removed. If other systems or parts of your game code
* are relying on this item, it is up to you to sever those relationships prior to removing the item.
*
* @method Phaser.Cache.BaseCache#remove
* @fires Phaser.Cache.Events#REMOVE
* @since 3.0.0
*
* @param {string} key - The unique key of the item to remove from the cache.
*
* @return {this} This BaseCache object.
*/
remove: function (key)
{
var entry = this.get(key);
if (entry)
{
this.entries.delete(key);
this.events.emit(Events.REMOVE, this, key, entry.data);
}
return this;
},
/**
* Returns all keys in use in this cache.
*
* @method Phaser.Cache.BaseCache#getKeys
* @since 3.17.0
*
* @return {string[]} Array containing all the keys.
*/
getKeys: function ()
{
return this.entries.keys();
},
/**
* Destroys this cache and all items within it.
*
* @method Phaser.Cache.BaseCache#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.entries.clear();
this.events.removeAllListeners();
this.entries = null;
this.events = null;
}
});
module.exports = BaseCache;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,382 +1,382 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Clamp = require('../../../math/Clamp');
var Class = require('../../../utils/Class');
var Events = require('../events');
/**
* @classdesc
* A Camera Fade effect.
*
* This effect will fade the camera viewport to the given color, over the duration specified.
*
* Only the camera viewport is faded. None of the objects it is displaying are impacted, i.e. their colors do
* not change.
*
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
* which is invoked each frame for the duration of the effect, if required.
*
* @class Fade
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.5.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
*/
var Fade = new Class({
initialize:
function Fade (camera)
{
/**
* The Camera this effect belongs to.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readonly
* @since 3.5.0
*/
this.camera = camera;
/**
* Is this effect actively running?
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#isRunning
* @type {boolean}
* @readonly
* @default false
* @since 3.5.0
*/
this.isRunning = false;
/**
* Has this effect finished running?
*
* This is different from `isRunning` because it remains set to `true` when the effect is over,
* until the effect is either reset or started again.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#isComplete
* @type {boolean}
* @readonly
* @default false
* @since 3.5.0
*/
this.isComplete = false;
/**
* The direction of the fade.
* `true` = fade out (transparent to color), `false` = fade in (color to transparent)
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#direction
* @type {boolean}
* @readonly
* @since 3.5.0
*/
this.direction = true;
/**
* The duration of the effect, in milliseconds.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#duration
* @type {integer}
* @readonly
* @default 0
* @since 3.5.0
*/
this.duration = 0;
/**
* The value of the red color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#red
* @type {integer}
* @private
* @since 3.5.0
*/
this.red = 0;
/**
* The value of the green color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#green
* @type {integer}
* @private
* @since 3.5.0
*/
this.green = 0;
/**
* The value of the blue color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#blue
* @type {integer}
* @private
* @since 3.5.0
*/
this.blue = 0;
/**
* The value of the alpha channel used during the fade effect.
* A value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#alpha
* @type {number}
* @private
* @since 3.5.0
*/
this.alpha = 0;
/**
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#progress
* @type {number}
* @since 3.5.0
*/
this.progress = 0;
/**
* Effect elapsed timer.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#_elapsed
* @type {number}
* @private
* @since 3.5.0
*/
this._elapsed = 0;
/**
* This callback is invoked every frame for the duration of the effect.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#_onUpdate
* @type {?Phaser.Types.Cameras.Scene2D.CameraFadeCallback}
* @private
* @default null
* @since 3.5.0
*/
this._onUpdate;
/**
* On Complete callback scope.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#_onUpdateScope
* @type {any}
* @private
* @since 3.5.0
*/
this._onUpdateScope;
},
/**
* Fades the Camera to or from the given color over the duration specified.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#start
* @fires Phaser.Cameras.Scene2D.Events#FADE_IN_START
* @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_START
* @since 3.5.0
*
* @param {boolean} [direction=true] - The direction of the fade. `true` = fade out (transparent to color), `false` = fade in (color to transparent)
* @param {integer} [duration=1000] - The duration of the effect in milliseconds.
* @param {integer} [red=0] - The amount to fade the red channel towards. A value between 0 and 255.
* @param {integer} [green=0] - The amount to fade the green channel towards. A value between 0 and 255.
* @param {integer} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255.
* @param {boolean} [force=false] - Force the effect to start immediately, even if already running.
* @param {Phaser.Types.Cameras.Scene2D.CameraFadeCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
* It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is.
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
*
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
*/
start: function (direction, duration, red, green, blue, force, callback, context)
{
if (direction === undefined) { direction = true; }
if (duration === undefined) { duration = 1000; }
if (red === undefined) { red = 0; }
if (green === undefined) { green = 0; }
if (blue === undefined) { blue = 0; }
if (force === undefined) { force = false; }
if (callback === undefined) { callback = null; }
if (context === undefined) { context = this.camera.scene; }
if (!force && this.isRunning)
{
return this.camera;
}
this.isRunning = true;
this.isComplete = false;
this.duration = duration;
this.direction = direction;
this.progress = 0;
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = (direction) ? Number.MIN_VALUE : 1;
this._elapsed = 0;
this._onUpdate = callback;
this._onUpdateScope = context;
var eventName = (direction) ? Events.FADE_OUT_START : Events.FADE_IN_START;
this.camera.emit(eventName, this.camera, this, duration, red, green, blue);
return this.camera;
},
/**
* The main update loop for this effect. Called automatically by the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#update
* @since 3.5.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.
*/
update: function (time, delta)
{
if (!this.isRunning)
{
return;
}
this._elapsed += delta;
this.progress = Clamp(this._elapsed / this.duration, 0, 1);
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, this.camera, this.progress);
}
if (this._elapsed < this.duration)
{
this.alpha = (this.direction) ? this.progress : 1 - this.progress;
}
else
{
this.alpha = (this.direction) ? 1 : 0;
this.effectComplete();
}
},
/**
* Called internally by the Canvas Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderCanvas
* @since 3.5.0
*
* @param {CanvasRenderingContext2D} ctx - The Canvas context to render to.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.
*/
postRenderCanvas: function (ctx)
{
if (!this.isRunning && !this.isComplete)
{
return false;
}
var camera = this.camera;
ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')';
ctx.fillRect(camera._cx, camera._cy, camera._cw, camera._ch);
return true;
},
/**
* Called internally by the WebGL Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.MultiPipeline} pipeline - The WebGL Pipeline to render to. Must provide the `drawFillRect` method.
* @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`.
*/
postRenderWebGL: function (pipeline, getTintFunction)
{
if (!this.isRunning && !this.isComplete)
{
return false;
}
var camera = this.camera;
var red = this.red / 255;
var blue = this.blue / 255;
var green = this.green / 255;
pipeline.drawFillRect(
camera._cx, camera._cy, camera._cw, camera._ch,
getTintFunction(red, green, blue, 1),
this.alpha
);
return true;
},
/**
* Called internally when the effect completes.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#effectComplete
* @fires Phaser.Cameras.Scene2D.Events#FADE_IN_COMPLETE
* @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_COMPLETE
* @since 3.5.0
*/
effectComplete: function ()
{
this._onUpdate = null;
this._onUpdateScope = null;
this.isRunning = false;
this.isComplete = true;
var eventName = (this.direction) ? Events.FADE_OUT_COMPLETE : Events.FADE_IN_COMPLETE;
this.camera.emit(eventName, this.camera, this);
},
/**
* Resets this camera effect.
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#reset
* @since 3.5.0
*/
reset: function ()
{
this.isRunning = false;
this.isComplete = false;
this._onUpdate = null;
this._onUpdateScope = null;
},
/**
* Destroys this effect, releasing it from the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#destroy
* @since 3.5.0
*/
destroy: function ()
{
this.reset();
this.camera = null;
}
});
module.exports = Fade;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Clamp = require('../../../math/Clamp');
var Class = require('../../../utils/Class');
var Events = require('../events');
/**
* @classdesc
* A Camera Fade effect.
*
* This effect will fade the camera viewport to the given color, over the duration specified.
*
* Only the camera viewport is faded. None of the objects it is displaying are impacted, i.e. their colors do
* not change.
*
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
* which is invoked each frame for the duration of the effect, if required.
*
* @class Fade
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.5.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
*/
var Fade = new Class({
initialize:
function Fade (camera)
{
/**
* The Camera this effect belongs to.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readonly
* @since 3.5.0
*/
this.camera = camera;
/**
* Is this effect actively running?
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#isRunning
* @type {boolean}
* @readonly
* @default false
* @since 3.5.0
*/
this.isRunning = false;
/**
* Has this effect finished running?
*
* This is different from `isRunning` because it remains set to `true` when the effect is over,
* until the effect is either reset or started again.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#isComplete
* @type {boolean}
* @readonly
* @default false
* @since 3.5.0
*/
this.isComplete = false;
/**
* The direction of the fade.
* `true` = fade out (transparent to color), `false` = fade in (color to transparent)
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#direction
* @type {boolean}
* @readonly
* @since 3.5.0
*/
this.direction = true;
/**
* The duration of the effect, in milliseconds.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#duration
* @type {integer}
* @readonly
* @default 0
* @since 3.5.0
*/
this.duration = 0;
/**
* The value of the red color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#red
* @type {integer}
* @private
* @since 3.5.0
*/
this.red = 0;
/**
* The value of the green color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#green
* @type {integer}
* @private
* @since 3.5.0
*/
this.green = 0;
/**
* The value of the blue color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#blue
* @type {integer}
* @private
* @since 3.5.0
*/
this.blue = 0;
/**
* The value of the alpha channel used during the fade effect.
* A value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#alpha
* @type {number}
* @private
* @since 3.5.0
*/
this.alpha = 0;
/**
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#progress
* @type {number}
* @since 3.5.0
*/
this.progress = 0;
/**
* Effect elapsed timer.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#_elapsed
* @type {number}
* @private
* @since 3.5.0
*/
this._elapsed = 0;
/**
* This callback is invoked every frame for the duration of the effect.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#_onUpdate
* @type {?Phaser.Types.Cameras.Scene2D.CameraFadeCallback}
* @private
* @default null
* @since 3.5.0
*/
this._onUpdate;
/**
* On Complete callback scope.
*
* @name Phaser.Cameras.Scene2D.Effects.Fade#_onUpdateScope
* @type {any}
* @private
* @since 3.5.0
*/
this._onUpdateScope;
},
/**
* Fades the Camera to or from the given color over the duration specified.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#start
* @fires Phaser.Cameras.Scene2D.Events#FADE_IN_START
* @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_START
* @since 3.5.0
*
* @param {boolean} [direction=true] - The direction of the fade. `true` = fade out (transparent to color), `false` = fade in (color to transparent)
* @param {integer} [duration=1000] - The duration of the effect in milliseconds.
* @param {integer} [red=0] - The amount to fade the red channel towards. A value between 0 and 255.
* @param {integer} [green=0] - The amount to fade the green channel towards. A value between 0 and 255.
* @param {integer} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255.
* @param {boolean} [force=false] - Force the effect to start immediately, even if already running.
* @param {Phaser.Types.Cameras.Scene2D.CameraFadeCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
* It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is.
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
*
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
*/
start: function (direction, duration, red, green, blue, force, callback, context)
{
if (direction === undefined) { direction = true; }
if (duration === undefined) { duration = 1000; }
if (red === undefined) { red = 0; }
if (green === undefined) { green = 0; }
if (blue === undefined) { blue = 0; }
if (force === undefined) { force = false; }
if (callback === undefined) { callback = null; }
if (context === undefined) { context = this.camera.scene; }
if (!force && this.isRunning)
{
return this.camera;
}
this.isRunning = true;
this.isComplete = false;
this.duration = duration;
this.direction = direction;
this.progress = 0;
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = (direction) ? Number.MIN_VALUE : 1;
this._elapsed = 0;
this._onUpdate = callback;
this._onUpdateScope = context;
var eventName = (direction) ? Events.FADE_OUT_START : Events.FADE_IN_START;
this.camera.emit(eventName, this.camera, this, duration, red, green, blue);
return this.camera;
},
/**
* The main update loop for this effect. Called automatically by the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#update
* @since 3.5.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.
*/
update: function (time, delta)
{
if (!this.isRunning)
{
return;
}
this._elapsed += delta;
this.progress = Clamp(this._elapsed / this.duration, 0, 1);
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, this.camera, this.progress);
}
if (this._elapsed < this.duration)
{
this.alpha = (this.direction) ? this.progress : 1 - this.progress;
}
else
{
this.alpha = (this.direction) ? 1 : 0;
this.effectComplete();
}
},
/**
* Called internally by the Canvas Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderCanvas
* @since 3.5.0
*
* @param {CanvasRenderingContext2D} ctx - The Canvas context to render to.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.
*/
postRenderCanvas: function (ctx)
{
if (!this.isRunning && !this.isComplete)
{
return false;
}
var camera = this.camera;
ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')';
ctx.fillRect(camera._cx, camera._cy, camera._cw, camera._ch);
return true;
},
/**
* Called internally by the WebGL Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.MultiPipeline} pipeline - The WebGL Pipeline to render to. Must provide the `drawFillRect` method.
* @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`.
*/
postRenderWebGL: function (pipeline, getTintFunction)
{
if (!this.isRunning && !this.isComplete)
{
return false;
}
var camera = this.camera;
var red = this.red / 255;
var blue = this.blue / 255;
var green = this.green / 255;
pipeline.drawFillRect(
camera._cx, camera._cy, camera._cw, camera._ch,
getTintFunction(red, green, blue, 1),
this.alpha
);
return true;
},
/**
* Called internally when the effect completes.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#effectComplete
* @fires Phaser.Cameras.Scene2D.Events#FADE_IN_COMPLETE
* @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_COMPLETE
* @since 3.5.0
*/
effectComplete: function ()
{
this._onUpdate = null;
this._onUpdateScope = null;
this.isRunning = false;
this.isComplete = true;
var eventName = (this.direction) ? Events.FADE_OUT_COMPLETE : Events.FADE_IN_COMPLETE;
this.camera.emit(eventName, this.camera, this);
},
/**
* Resets this camera effect.
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#reset
* @since 3.5.0
*/
reset: function ()
{
this.isRunning = false;
this.isComplete = false;
this._onUpdate = null;
this._onUpdateScope = null;
},
/**
* Destroys this effect, releasing it from the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Fade#destroy
* @since 3.5.0
*/
destroy: function ()
{
this.reset();
this.camera = null;
}
});
module.exports = Fade;

View file

@ -1,345 +1,345 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Clamp = require('../../../math/Clamp');
var Class = require('../../../utils/Class');
var Events = require('../events');
/**
* @classdesc
* A Camera Flash effect.
*
* This effect will flash the camera viewport to the given color, over the duration specified.
*
* Only the camera viewport is flashed. None of the objects it is displaying are impacted, i.e. their colors do
* not change.
*
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
* which is invoked each frame for the duration of the effect, if required.
*
* @class Flash
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.5.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
*/
var Flash = new Class({
initialize:
function Flash (camera)
{
/**
* The Camera this effect belongs to.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readonly
* @since 3.5.0
*/
this.camera = camera;
/**
* Is this effect actively running?
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#isRunning
* @type {boolean}
* @readonly
* @default false
* @since 3.5.0
*/
this.isRunning = false;
/**
* The duration of the effect, in milliseconds.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#duration
* @type {integer}
* @readonly
* @default 0
* @since 3.5.0
*/
this.duration = 0;
/**
* The value of the red color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#red
* @type {integer}
* @private
* @since 3.5.0
*/
this.red = 0;
/**
* The value of the green color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#green
* @type {integer}
* @private
* @since 3.5.0
*/
this.green = 0;
/**
* The value of the blue color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#blue
* @type {integer}
* @private
* @since 3.5.0
*/
this.blue = 0;
/**
* The value of the alpha channel used during the fade effect.
* A value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#alpha
* @type {number}
* @private
* @since 3.5.0
*/
this.alpha = 0;
/**
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#progress
* @type {number}
* @since 3.5.0
*/
this.progress = 0;
/**
* Effect elapsed timer.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#_elapsed
* @type {number}
* @private
* @since 3.5.0
*/
this._elapsed = 0;
/**
* This callback is invoked every frame for the duration of the effect.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#_onUpdate
* @type {?Phaser.Types.Cameras.Scene2D.CameraFlashCallback}
* @private
* @default null
* @since 3.5.0
*/
this._onUpdate;
/**
* On Complete callback scope.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#_onUpdateScope
* @type {any}
* @private
* @since 3.5.0
*/
this._onUpdateScope;
},
/**
* Flashes the Camera to or from the given color over the duration specified.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#start
* @fires Phaser.Cameras.Scene2D.Events#FLASH_START
* @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE
* @since 3.5.0
*
* @param {integer} [duration=250] - The duration of the effect in milliseconds.
* @param {integer} [red=255] - The amount to fade the red channel towards. A value between 0 and 255.
* @param {integer} [green=255] - The amount to fade the green channel towards. A value between 0 and 255.
* @param {integer} [blue=255] - The amount to fade the blue channel towards. A value between 0 and 255.
* @param {boolean} [force=false] - Force the effect to start immediately, even if already running.
* @param {Phaser.Types.Cameras.Scene2D.CameraFlashCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
* It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is.
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
*
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
*/
start: function (duration, red, green, blue, force, callback, context)
{
if (duration === undefined) { duration = 250; }
if (red === undefined) { red = 255; }
if (green === undefined) { green = 255; }
if (blue === undefined) { blue = 255; }
if (force === undefined) { force = false; }
if (callback === undefined) { callback = null; }
if (context === undefined) { context = this.camera.scene; }
if (!force && this.isRunning)
{
return this.camera;
}
this.isRunning = true;
this.duration = duration;
this.progress = 0;
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = 1;
this._elapsed = 0;
this._onUpdate = callback;
this._onUpdateScope = context;
this.camera.emit(Events.FLASH_START, this.camera, this, duration, red, green, blue);
return this.camera;
},
/**
* The main update loop for this effect. Called automatically by the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#update
* @since 3.5.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.
*/
update: function (time, delta)
{
if (!this.isRunning)
{
return;
}
this._elapsed += delta;
this.progress = Clamp(this._elapsed / this.duration, 0, 1);
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, this.camera, this.progress);
}
if (this._elapsed < this.duration)
{
this.alpha = 1 - this.progress;
}
else
{
this.effectComplete();
}
},
/**
* Called internally by the Canvas Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderCanvas
* @since 3.5.0
*
* @param {CanvasRenderingContext2D} ctx - The Canvas context to render to.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.
*/
postRenderCanvas: function (ctx)
{
if (!this.isRunning)
{
return false;
}
var camera = this.camera;
ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')';
ctx.fillRect(camera._cx, camera._cy, camera._cw, camera._ch);
return true;
},
/**
* Called internally by the WebGL Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.MultiPipeline} pipeline - The WebGL Pipeline to render to. Must provide the `drawFillRect` method.
* @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`.
*/
postRenderWebGL: function (pipeline, getTintFunction)
{
if (!this.isRunning)
{
return false;
}
var camera = this.camera;
var red = this.red / 255;
var blue = this.blue / 255;
var green = this.green / 255;
pipeline.drawFillRect(
camera._cx, camera._cy, camera._cw, camera._ch,
getTintFunction(red, green, blue, 1),
this.alpha
);
return true;
},
/**
* Called internally when the effect completes.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#effectComplete
* @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE
* @since 3.5.0
*/
effectComplete: function ()
{
this._onUpdate = null;
this._onUpdateScope = null;
this.isRunning = false;
this.camera.emit(Events.FLASH_COMPLETE, this.camera, this);
},
/**
* Resets this camera effect.
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#reset
* @since 3.5.0
*/
reset: function ()
{
this.isRunning = false;
this._onUpdate = null;
this._onUpdateScope = null;
},
/**
* Destroys this effect, releasing it from the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#destroy
* @since 3.5.0
*/
destroy: function ()
{
this.reset();
this.camera = null;
}
});
module.exports = Flash;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Clamp = require('../../../math/Clamp');
var Class = require('../../../utils/Class');
var Events = require('../events');
/**
* @classdesc
* A Camera Flash effect.
*
* This effect will flash the camera viewport to the given color, over the duration specified.
*
* Only the camera viewport is flashed. None of the objects it is displaying are impacted, i.e. their colors do
* not change.
*
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
* which is invoked each frame for the duration of the effect, if required.
*
* @class Flash
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.5.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
*/
var Flash = new Class({
initialize:
function Flash (camera)
{
/**
* The Camera this effect belongs to.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readonly
* @since 3.5.0
*/
this.camera = camera;
/**
* Is this effect actively running?
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#isRunning
* @type {boolean}
* @readonly
* @default false
* @since 3.5.0
*/
this.isRunning = false;
/**
* The duration of the effect, in milliseconds.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#duration
* @type {integer}
* @readonly
* @default 0
* @since 3.5.0
*/
this.duration = 0;
/**
* The value of the red color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#red
* @type {integer}
* @private
* @since 3.5.0
*/
this.red = 0;
/**
* The value of the green color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#green
* @type {integer}
* @private
* @since 3.5.0
*/
this.green = 0;
/**
* The value of the blue color channel the camera will use for the fade effect.
* A value between 0 and 255.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#blue
* @type {integer}
* @private
* @since 3.5.0
*/
this.blue = 0;
/**
* The value of the alpha channel used during the fade effect.
* A value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#alpha
* @type {number}
* @private
* @since 3.5.0
*/
this.alpha = 0;
/**
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#progress
* @type {number}
* @since 3.5.0
*/
this.progress = 0;
/**
* Effect elapsed timer.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#_elapsed
* @type {number}
* @private
* @since 3.5.0
*/
this._elapsed = 0;
/**
* This callback is invoked every frame for the duration of the effect.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#_onUpdate
* @type {?Phaser.Types.Cameras.Scene2D.CameraFlashCallback}
* @private
* @default null
* @since 3.5.0
*/
this._onUpdate;
/**
* On Complete callback scope.
*
* @name Phaser.Cameras.Scene2D.Effects.Flash#_onUpdateScope
* @type {any}
* @private
* @since 3.5.0
*/
this._onUpdateScope;
},
/**
* Flashes the Camera to or from the given color over the duration specified.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#start
* @fires Phaser.Cameras.Scene2D.Events#FLASH_START
* @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE
* @since 3.5.0
*
* @param {integer} [duration=250] - The duration of the effect in milliseconds.
* @param {integer} [red=255] - The amount to fade the red channel towards. A value between 0 and 255.
* @param {integer} [green=255] - The amount to fade the green channel towards. A value between 0 and 255.
* @param {integer} [blue=255] - The amount to fade the blue channel towards. A value between 0 and 255.
* @param {boolean} [force=false] - Force the effect to start immediately, even if already running.
* @param {Phaser.Types.Cameras.Scene2D.CameraFlashCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
* It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is.
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
*
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
*/
start: function (duration, red, green, blue, force, callback, context)
{
if (duration === undefined) { duration = 250; }
if (red === undefined) { red = 255; }
if (green === undefined) { green = 255; }
if (blue === undefined) { blue = 255; }
if (force === undefined) { force = false; }
if (callback === undefined) { callback = null; }
if (context === undefined) { context = this.camera.scene; }
if (!force && this.isRunning)
{
return this.camera;
}
this.isRunning = true;
this.duration = duration;
this.progress = 0;
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = 1;
this._elapsed = 0;
this._onUpdate = callback;
this._onUpdateScope = context;
this.camera.emit(Events.FLASH_START, this.camera, this, duration, red, green, blue);
return this.camera;
},
/**
* The main update loop for this effect. Called automatically by the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#update
* @since 3.5.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.
*/
update: function (time, delta)
{
if (!this.isRunning)
{
return;
}
this._elapsed += delta;
this.progress = Clamp(this._elapsed / this.duration, 0, 1);
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, this.camera, this.progress);
}
if (this._elapsed < this.duration)
{
this.alpha = 1 - this.progress;
}
else
{
this.effectComplete();
}
},
/**
* Called internally by the Canvas Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderCanvas
* @since 3.5.0
*
* @param {CanvasRenderingContext2D} ctx - The Canvas context to render to.
*
* @return {boolean} `true` if the effect drew to the renderer, otherwise `false`.
*/
postRenderCanvas: function (ctx)
{
if (!this.isRunning)
{
return false;
}
var camera = this.camera;
ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')';
ctx.fillRect(camera._cx, camera._cy, camera._cw, camera._ch);
return true;
},
/**
* Called internally by the WebGL Renderer.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderWebGL
* @since 3.5.0
*
* @param {Phaser.Renderer.WebGL.Pipelines.MultiPipeline} pipeline - The WebGL Pipeline to render to. Must provide the `drawFillRect` method.
* @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`.
*/
postRenderWebGL: function (pipeline, getTintFunction)
{
if (!this.isRunning)
{
return false;
}
var camera = this.camera;
var red = this.red / 255;
var blue = this.blue / 255;
var green = this.green / 255;
pipeline.drawFillRect(
camera._cx, camera._cy, camera._cw, camera._ch,
getTintFunction(red, green, blue, 1),
this.alpha
);
return true;
},
/**
* Called internally when the effect completes.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#effectComplete
* @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE
* @since 3.5.0
*/
effectComplete: function ()
{
this._onUpdate = null;
this._onUpdateScope = null;
this.isRunning = false;
this.camera.emit(Events.FLASH_COMPLETE, this.camera, this);
},
/**
* Resets this camera effect.
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#reset
* @since 3.5.0
*/
reset: function ()
{
this.isRunning = false;
this._onUpdate = null;
this._onUpdateScope = null;
},
/**
* Destroys this effect, releasing it from the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.Flash#destroy
* @since 3.5.0
*/
destroy: function ()
{
this.reset();
this.camera = null;
}
});
module.exports = Flash;

View file

@ -1,427 +1,427 @@
/**
* @author Jason Nicholls <nicholls.jason@gmail.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Clamp = require('../../../math/Clamp');
var Class = require('../../../utils/Class');
var Events = require('../events');
var EaseMap = require('../../../math/easing/EaseMap');
/**
* @classdesc
* A Camera Rotate effect.
*
* This effect will rotate the Camera so that the its viewport finishes at the given angle in radians,
* over the duration and with the ease specified.
*
* Camera rotation always takes place based on the Camera viewport. By default, rotation happens
* in the center of the viewport. You can adjust this with the `originX` and `originY` properties.
*
* Rotation influences the rendering of _all_ Game Objects visible by this Camera. However, it does not
* rotate the Camera viewport itself, which always remains an axis-aligned rectangle.
*
* Only the camera is rotates. None of the objects it is displaying are impacted, i.e. their positions do
* not change.
*
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
* which is invoked each frame for the duration of the effect if required.
*
* @class RotateTo
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.23.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
*/
var RotateTo = new Class({
initialize:
function RotateTo (camera)
{
/**
* The Camera this effect belongs to.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readonly
* @since 3.23.0
*/
this.camera = camera;
/**
* Is this effect actively running?
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#isRunning
* @type {boolean}
* @readonly
* @default false
* @since 3.23.0
*/
this.isRunning = false;
/**
* The duration of the effect, in milliseconds.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#duration
* @type {integer}
* @readonly
* @default 0
* @since 3.23.0
*/
this.duration = 0;
/**
* The starting angle to rotate the camera from.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#source
* @type {number}
* @since 3.23.0
*/
this.source = 0;
/**
* The constantly updated value based on the force.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#current
* @type {number}
* @since 3.23.0
*/
this.current = 0;
/**
* The destination angle in radians to rotate the camera to.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#destination
* @type {number}
* @since 3.23.0
*/
this.destination = 0;
/**
* The ease function to use during the Rotate.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#ease
* @type {function}
* @since 3.23.0
*/
this.ease;
/**
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#progress
* @type {number}
* @since 3.23.0
*/
this.progress = 0;
/**
* Effect elapsed timer.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_elapsed
* @type {number}
* @private
* @since 3.23.0
*/
this._elapsed = 0;
/**
* @callback CameraRotateCallback
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera on which the effect is running.
* @param {number} progress - The progress of the effect. A value between 0 and 1.
* @param {number} angle - The Camera's new angle in radians.
*/
/**
* This callback is invoked every frame for the duration of the effect.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdate
* @type {?CameraRotateCallback}
* @private
* @default null
* @since 3.23.0
*/
this._onUpdate;
/**
* On Complete callback scope.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdateScope
* @type {any}
* @private
* @since 3.23.0
*/
this._onUpdateScope;
/**
* The direction of the rotation.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#clockwise
* @type {boolean}
* @since 3.23.0
*/
this.clockwise = true;
/**
* The shortest direction to the target rotation.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#shortestPath
* @type {boolean}
* @since 3.23.0
*/
this.shortestPath = false;
},
/**
* This effect will scroll the Camera so that the center of its viewport finishes at the given angle,
* over the duration and with the ease specified.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#start
* @fires Phaser.Cameras.Scene2D.Events#ROTATE_START
* @fires Phaser.Cameras.Scene2D.Events#ROTATE_COMPLETE
* @since 3.23.0
*
* @param {number} radians - The destination angle in radians to rotate the Camera viewport to. If the angle is positive then the rotation is clockwise else anticlockwise
* @param {boolean} [shortestPath=false] - If shortest path is set to true the camera will rotate in the quickest direction clockwise or anti-clockwise.
* @param {integer} [duration=1000] - The duration of the effect in milliseconds.
* @param {(string|function)} [ease='Linear'] - The ease to use for the Rotate. Can be any of the Phaser Easing constants or a custom function.
* @param {boolean} [force=false] - Force the rotation effect to start immediately, even if already running.
* @param {CameraRotateCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
* It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is,
* the current camera scroll x coordinate and the current camera scroll y coordinate.
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
*
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
*/
start: function (radians, shortestPath, duration, ease, force, callback, context)
{
if (duration === undefined) { duration = 1000; }
if (ease === undefined) { ease = EaseMap.Linear; }
if (force === undefined) { force = false; }
if (callback === undefined) { callback = null; }
if (context === undefined) { context = this.camera.scene; }
if (shortestPath === undefined) { shortestPath = false; }
this.shortestPath = shortestPath;
var tmpDestination = radians;
if (radians < 0)
{
tmpDestination = -1 * radians;
this.clockwise = false;
}
else
{
this.clockwise = true;
}
var maxRad = (360 * Math.PI) / 180;
tmpDestination = tmpDestination - (Math.floor(tmpDestination / maxRad) * maxRad);
var cam = this.camera;
if (!force && this.isRunning)
{
return cam;
}
this.isRunning = true;
this.duration = duration;
this.progress = 0;
// Starting from
this.source = cam.rotation;
// Destination
this.destination = tmpDestination;
// Using this ease
if (typeof ease === 'string' && EaseMap.hasOwnProperty(ease))
{
this.ease = EaseMap[ease];
}
else if (typeof ease === 'function')
{
this.ease = ease;
}
this._elapsed = 0;
this._onUpdate = callback;
this._onUpdateScope = context;
if (this.shortestPath)
{
// The shortest path is true so calculate the quickest direction
var cwDist = 0;
var acwDist = 0;
if (this.destination > this.source)
{
cwDist = Math.abs(this.destination - this.source);
}
else
{
cwDist = (Math.abs(this.destination + maxRad) - this.source);
}
if (this.source > this.destination)
{
acwDist = Math.abs(this.source - this.destination);
}
else
{
acwDist = (Math.abs(this.source + maxRad) - this.destination);
}
if (cwDist < acwDist)
{
this.clockwise = true;
}
else if (cwDist > acwDist)
{
this.clockwise = false;
}
}
this.camera.emit(Events.ROTATE_START, this.camera, this, duration, tmpDestination);
return cam;
},
/**
* The main update loop for this effect. Called automatically by the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#update
* @since 3.23.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.
*/
update: function (time, delta)
{
if (!this.isRunning)
{
return;
}
this._elapsed += delta;
var progress = Clamp(this._elapsed / this.duration, 0, 1);
this.progress = progress;
var cam = this.camera;
if (this._elapsed < this.duration)
{
var v = this.ease(progress);
this.current = cam.rotation;
var distance = 0;
var maxRad = (360 * Math.PI) / 180;
var target = this.destination;
var current = this.current;
if (this.clockwise === false)
{
target = this.current;
current = this.destination;
}
if (target >= current)
{
distance = Math.abs(target - current);
}
else
{
distance = (Math.abs(target + maxRad) - current);
}
var r = 0;
if (this.clockwise)
{
r = (cam.rotation + (distance * v));
}
else
{
r = (cam.rotation - (distance * v));
}
cam.rotation = r;
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, cam, progress, r);
}
}
else
{
cam.rotation = this.destination;
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, cam, progress, this.destination);
}
this.effectComplete();
}
},
/**
* Called internally when the effect completes.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#effectComplete
* @since 3.23.0
*/
effectComplete: function ()
{
this._onUpdate = null;
this._onUpdateScope = null;
this.isRunning = false;
this.camera.emit(Events.ROTATE_COMPLETE, this.camera, this);
},
/**
* Resets this camera effect.
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#reset
* @since 3.23.0
*/
reset: function ()
{
this.isRunning = false;
this._onUpdate = null;
this._onUpdateScope = null;
},
/**
* Destroys this effect, releasing it from the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#destroy
* @since 3.23.0
*/
destroy: function ()
{
this.reset();
this.camera = null;
this.source = null;
this.destination = null;
}
});
module.exports = RotateTo;
/**
* @author Jason Nicholls <nicholls.jason@gmail.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Clamp = require('../../../math/Clamp');
var Class = require('../../../utils/Class');
var Events = require('../events');
var EaseMap = require('../../../math/easing/EaseMap');
/**
* @classdesc
* A Camera Rotate effect.
*
* This effect will rotate the Camera so that the its viewport finishes at the given angle in radians,
* over the duration and with the ease specified.
*
* Camera rotation always takes place based on the Camera viewport. By default, rotation happens
* in the center of the viewport. You can adjust this with the `originX` and `originY` properties.
*
* Rotation influences the rendering of _all_ Game Objects visible by this Camera. However, it does not
* rotate the Camera viewport itself, which always remains an axis-aligned rectangle.
*
* Only the camera is rotates. None of the objects it is displaying are impacted, i.e. their positions do
* not change.
*
* The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback,
* which is invoked each frame for the duration of the effect if required.
*
* @class RotateTo
* @memberof Phaser.Cameras.Scene2D.Effects
* @constructor
* @since 3.23.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon.
*/
var RotateTo = new Class({
initialize:
function RotateTo (camera)
{
/**
* The Camera this effect belongs to.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#camera
* @type {Phaser.Cameras.Scene2D.Camera}
* @readonly
* @since 3.23.0
*/
this.camera = camera;
/**
* Is this effect actively running?
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#isRunning
* @type {boolean}
* @readonly
* @default false
* @since 3.23.0
*/
this.isRunning = false;
/**
* The duration of the effect, in milliseconds.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#duration
* @type {integer}
* @readonly
* @default 0
* @since 3.23.0
*/
this.duration = 0;
/**
* The starting angle to rotate the camera from.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#source
* @type {number}
* @since 3.23.0
*/
this.source = 0;
/**
* The constantly updated value based on the force.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#current
* @type {number}
* @since 3.23.0
*/
this.current = 0;
/**
* The destination angle in radians to rotate the camera to.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#destination
* @type {number}
* @since 3.23.0
*/
this.destination = 0;
/**
* The ease function to use during the Rotate.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#ease
* @type {function}
* @since 3.23.0
*/
this.ease;
/**
* If this effect is running this holds the current percentage of the progress, a value between 0 and 1.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#progress
* @type {number}
* @since 3.23.0
*/
this.progress = 0;
/**
* Effect elapsed timer.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_elapsed
* @type {number}
* @private
* @since 3.23.0
*/
this._elapsed = 0;
/**
* @callback CameraRotateCallback
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera on which the effect is running.
* @param {number} progress - The progress of the effect. A value between 0 and 1.
* @param {number} angle - The Camera's new angle in radians.
*/
/**
* This callback is invoked every frame for the duration of the effect.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdate
* @type {?CameraRotateCallback}
* @private
* @default null
* @since 3.23.0
*/
this._onUpdate;
/**
* On Complete callback scope.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdateScope
* @type {any}
* @private
* @since 3.23.0
*/
this._onUpdateScope;
/**
* The direction of the rotation.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#clockwise
* @type {boolean}
* @since 3.23.0
*/
this.clockwise = true;
/**
* The shortest direction to the target rotation.
*
* @name Phaser.Cameras.Scene2D.Effects.RotateTo#shortestPath
* @type {boolean}
* @since 3.23.0
*/
this.shortestPath = false;
},
/**
* This effect will scroll the Camera so that the center of its viewport finishes at the given angle,
* over the duration and with the ease specified.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#start
* @fires Phaser.Cameras.Scene2D.Events#ROTATE_START
* @fires Phaser.Cameras.Scene2D.Events#ROTATE_COMPLETE
* @since 3.23.0
*
* @param {number} radians - The destination angle in radians to rotate the Camera viewport to. If the angle is positive then the rotation is clockwise else anticlockwise
* @param {boolean} [shortestPath=false] - If shortest path is set to true the camera will rotate in the quickest direction clockwise or anti-clockwise.
* @param {integer} [duration=1000] - The duration of the effect in milliseconds.
* @param {(string|function)} [ease='Linear'] - The ease to use for the Rotate. Can be any of the Phaser Easing constants or a custom function.
* @param {boolean} [force=false] - Force the rotation effect to start immediately, even if already running.
* @param {CameraRotateCallback} [callback] - This callback will be invoked every frame for the duration of the effect.
* It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is,
* the current camera scroll x coordinate and the current camera scroll y coordinate.
* @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs.
*
* @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started.
*/
start: function (radians, shortestPath, duration, ease, force, callback, context)
{
if (duration === undefined) { duration = 1000; }
if (ease === undefined) { ease = EaseMap.Linear; }
if (force === undefined) { force = false; }
if (callback === undefined) { callback = null; }
if (context === undefined) { context = this.camera.scene; }
if (shortestPath === undefined) { shortestPath = false; }
this.shortestPath = shortestPath;
var tmpDestination = radians;
if (radians < 0)
{
tmpDestination = -1 * radians;
this.clockwise = false;
}
else
{
this.clockwise = true;
}
var maxRad = (360 * Math.PI) / 180;
tmpDestination = tmpDestination - (Math.floor(tmpDestination / maxRad) * maxRad);
var cam = this.camera;
if (!force && this.isRunning)
{
return cam;
}
this.isRunning = true;
this.duration = duration;
this.progress = 0;
// Starting from
this.source = cam.rotation;
// Destination
this.destination = tmpDestination;
// Using this ease
if (typeof ease === 'string' && EaseMap.hasOwnProperty(ease))
{
this.ease = EaseMap[ease];
}
else if (typeof ease === 'function')
{
this.ease = ease;
}
this._elapsed = 0;
this._onUpdate = callback;
this._onUpdateScope = context;
if (this.shortestPath)
{
// The shortest path is true so calculate the quickest direction
var cwDist = 0;
var acwDist = 0;
if (this.destination > this.source)
{
cwDist = Math.abs(this.destination - this.source);
}
else
{
cwDist = (Math.abs(this.destination + maxRad) - this.source);
}
if (this.source > this.destination)
{
acwDist = Math.abs(this.source - this.destination);
}
else
{
acwDist = (Math.abs(this.source + maxRad) - this.destination);
}
if (cwDist < acwDist)
{
this.clockwise = true;
}
else if (cwDist > acwDist)
{
this.clockwise = false;
}
}
this.camera.emit(Events.ROTATE_START, this.camera, this, duration, tmpDestination);
return cam;
},
/**
* The main update loop for this effect. Called automatically by the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#update
* @since 3.23.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.
*/
update: function (time, delta)
{
if (!this.isRunning)
{
return;
}
this._elapsed += delta;
var progress = Clamp(this._elapsed / this.duration, 0, 1);
this.progress = progress;
var cam = this.camera;
if (this._elapsed < this.duration)
{
var v = this.ease(progress);
this.current = cam.rotation;
var distance = 0;
var maxRad = (360 * Math.PI) / 180;
var target = this.destination;
var current = this.current;
if (this.clockwise === false)
{
target = this.current;
current = this.destination;
}
if (target >= current)
{
distance = Math.abs(target - current);
}
else
{
distance = (Math.abs(target + maxRad) - current);
}
var r = 0;
if (this.clockwise)
{
r = (cam.rotation + (distance * v));
}
else
{
r = (cam.rotation - (distance * v));
}
cam.rotation = r;
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, cam, progress, r);
}
}
else
{
cam.rotation = this.destination;
if (this._onUpdate)
{
this._onUpdate.call(this._onUpdateScope, cam, progress, this.destination);
}
this.effectComplete();
}
},
/**
* Called internally when the effect completes.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#effectComplete
* @since 3.23.0
*/
effectComplete: function ()
{
this._onUpdate = null;
this._onUpdateScope = null;
this.isRunning = false;
this.camera.emit(Events.ROTATE_COMPLETE, this.camera, this);
},
/**
* Resets this camera effect.
* If it was previously running, it stops instantly without calling its onComplete callback or emitting an event.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#reset
* @since 3.23.0
*/
reset: function ()
{
this.isRunning = false;
this._onUpdate = null;
this._onUpdateScope = null;
},
/**
* Destroys this effect, releasing it from the Camera.
*
* @method Phaser.Cameras.Scene2D.Effects.RotateTo#destroy
* @since 3.23.0
*/
destroy: function ()
{
this.reset();
this.camera = null;
this.source = null;
this.destination = null;
}
});
module.exports = RotateTo;

View file

@ -1,20 +1,20 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Cameras.Scene2D.Effects
*/
module.exports = {
Fade: require('./Fade'),
Flash: require('./Flash'),
Pan: require('./Pan'),
Shake: require('./Shake'),
RotateTo: require('./RotateTo'),
Zoom: require('./Zoom')
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Cameras.Scene2D.Effects
*/
module.exports = {
Fade: require('./Fade'),
Flash: require('./Flash'),
Pan: require('./Pan'),
Shake: require('./Shake'),
RotateTo: require('./RotateTo'),
Zoom: require('./Zoom')
};

View file

@ -1,18 +1,18 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Camera Rotate Complete Event.
*
* This event is dispatched by a Camera instance when the Rotate Effect completes.
*
* @event Phaser.Cameras.Scene2D.Events#ROTATE_COMPLETE
* @since 3.23.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on.
* @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance.
*/
module.exports = 'camerarotatecomplete';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Camera Rotate Complete Event.
*
* This event is dispatched by a Camera instance when the Rotate Effect completes.
*
* @event Phaser.Cameras.Scene2D.Events#ROTATE_COMPLETE
* @since 3.23.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on.
* @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance.
*/
module.exports = 'camerarotatecomplete';

View file

@ -1,20 +1,20 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Camera Rotate Start Event.
*
* This event is dispatched by a Camera instance when the Rotate Effect starts.
*
* @event Phaser.Cameras.Scene2D.Events#ROTATE_START
* @since 3.23.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on.
* @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance.
* @param {integer} duration - The duration of the effect.
* @param {number} destination - The destination value.
*/
module.exports = 'camerarotatestart';
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Camera Rotate Start Event.
*
* This event is dispatched by a Camera instance when the Rotate Effect starts.
*
* @event Phaser.Cameras.Scene2D.Events#ROTATE_START
* @since 3.23.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on.
* @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance.
* @param {integer} duration - The duration of the effect.
* @param {number} destination - The destination value.
*/
module.exports = 'camerarotatestart';

View file

@ -1,31 +1,31 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Cameras.Scene2D.Events
*/
module.exports = {
DESTROY: require('./DESTROY_EVENT'),
FADE_IN_COMPLETE: require('./FADE_IN_COMPLETE_EVENT'),
FADE_IN_START: require('./FADE_IN_START_EVENT'),
FADE_OUT_COMPLETE: require('./FADE_OUT_COMPLETE_EVENT'),
FADE_OUT_START: require('./FADE_OUT_START_EVENT'),
FLASH_COMPLETE: require('./FLASH_COMPLETE_EVENT'),
FLASH_START: require('./FLASH_START_EVENT'),
PAN_COMPLETE: require('./PAN_COMPLETE_EVENT'),
PAN_START: require('./PAN_START_EVENT'),
POST_RENDER: require('./POST_RENDER_EVENT'),
PRE_RENDER: require('./PRE_RENDER_EVENT'),
ROTATE_COMPLETE: require('./ROTATE_COMPLETE_EVENT'),
ROTATE_START: require('./ROTATE_START_EVENT'),
SHAKE_COMPLETE: require('./SHAKE_COMPLETE_EVENT'),
SHAKE_START: require('./SHAKE_START_EVENT'),
ZOOM_COMPLETE: require('./ZOOM_COMPLETE_EVENT'),
ZOOM_START: require('./ZOOM_START_EVENT')
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @namespace Phaser.Cameras.Scene2D.Events
*/
module.exports = {
DESTROY: require('./DESTROY_EVENT'),
FADE_IN_COMPLETE: require('./FADE_IN_COMPLETE_EVENT'),
FADE_IN_START: require('./FADE_IN_START_EVENT'),
FADE_OUT_COMPLETE: require('./FADE_OUT_COMPLETE_EVENT'),
FADE_OUT_START: require('./FADE_OUT_START_EVENT'),
FLASH_COMPLETE: require('./FLASH_COMPLETE_EVENT'),
FLASH_START: require('./FLASH_START_EVENT'),
PAN_COMPLETE: require('./PAN_COMPLETE_EVENT'),
PAN_START: require('./PAN_START_EVENT'),
POST_RENDER: require('./POST_RENDER_EVENT'),
PRE_RENDER: require('./PRE_RENDER_EVENT'),
ROTATE_COMPLETE: require('./ROTATE_COMPLETE_EVENT'),
ROTATE_START: require('./ROTATE_START_EVENT'),
SHAKE_COMPLETE: require('./SHAKE_COMPLETE_EVENT'),
SHAKE_START: require('./SHAKE_START_EVENT'),
ZOOM_COMPLETE: require('./ZOOM_COMPLETE_EVENT'),
ZOOM_START: require('./ZOOM_START_EVENT')
};

View file

@ -1,300 +1,300 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../../utils/Class');
var GetValue = require('../../utils/object/GetValue');
/**
* @classdesc
* A Fixed Key Camera Control.
*
* This allows you to control the movement and zoom of a camera using the defined keys.
*
* ```javascript
* var camControl = new FixedKeyControl({
* camera: this.cameras.main,
* left: cursors.left,
* right: cursors.right,
* speed: float OR { x: 0, y: 0 }
* });
* ```
*
* Movement is precise and has no 'smoothing' applied to it.
*
* You must call the `update` method of this controller every frame.
*
* @class FixedKeyControl
* @memberof Phaser.Cameras.Controls
* @constructor
* @since 3.0.0
*
* @param {Phaser.Types.Cameras.Controls.FixedKeyControlConfig} config - The Fixed Key Control configuration object.
*/
var FixedKeyControl = new Class({
initialize:
function FixedKeyControl (config)
{
/**
* The Camera that this Control will update.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#camera
* @type {?Phaser.Cameras.Scene2D.Camera}
* @default null
* @since 3.0.0
*/
this.camera = GetValue(config, 'camera', null);
/**
* The Key to be pressed that will move the Camera left.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#left
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.left = GetValue(config, 'left', null);
/**
* The Key to be pressed that will move the Camera right.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#right
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.right = GetValue(config, 'right', null);
/**
* The Key to be pressed that will move the Camera up.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#up
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.up = GetValue(config, 'up', null);
/**
* The Key to be pressed that will move the Camera down.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#down
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.down = GetValue(config, 'down', null);
/**
* The Key to be pressed that will zoom the Camera in.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#zoomIn
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomIn = GetValue(config, 'zoomIn', null);
/**
* The Key to be pressed that will zoom the Camera out.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#zoomOut
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomOut = GetValue(config, 'zoomOut', null);
/**
* The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#zoomSpeed
* @type {number}
* @default 0.01
* @since 3.0.0
*/
this.zoomSpeed = GetValue(config, 'zoomSpeed', 0.01);
/**
* The horizontal speed the camera will move.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#speedX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.speedX = 0;
/**
* The vertical speed the camera will move.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#speedY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.speedY = 0;
var speed = GetValue(config, 'speed', null);
if (typeof speed === 'number')
{
this.speedX = speed;
this.speedY = speed;
}
else
{
this.speedX = GetValue(config, 'speed.x', 0);
this.speedY = GetValue(config, 'speed.y', 0);
}
/**
* Internal property to track the current zoom level.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#_zoom
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._zoom = 0;
/**
* A flag controlling if the Controls will update the Camera or not.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#active
* @type {boolean}
* @since 3.0.0
*/
this.active = (this.camera !== null);
},
/**
* Starts the Key Control running, providing it has been linked to a camera.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#start
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
start: function ()
{
this.active = (this.camera !== null);
return this;
},
/**
* Stops this Key Control from running. Call `start` to start it again.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#stop
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
stop: function ()
{
this.active = false;
return this;
},
/**
* Binds this Key Control to a camera.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#setCamera
* @since 3.0.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to bind this Key Control to.
*
* @return {this} This Key Control instance.
*/
setCamera: function (camera)
{
this.camera = camera;
return this;
},
/**
* Applies the results of pressing the control keys to the Camera.
*
* You must call this every step, it is not called automatically.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#update
* @since 3.0.0
*
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
update: function (delta)
{
if (!this.active)
{
return;
}
if (delta === undefined) { delta = 1; }
var cam = this.camera;
if (this.up && this.up.isDown)
{
cam.scrollY -= ((this.speedY * delta) | 0);
}
else if (this.down && this.down.isDown)
{
cam.scrollY += ((this.speedY * delta) | 0);
}
if (this.left && this.left.isDown)
{
cam.scrollX -= ((this.speedX * delta) | 0);
}
else if (this.right && this.right.isDown)
{
cam.scrollX += ((this.speedX * delta) | 0);
}
// Camera zoom
if (this.zoomIn && this.zoomIn.isDown)
{
cam.zoom -= this.zoomSpeed;
if (cam.zoom < 0.1)
{
cam.zoom = 0.1;
}
}
else if (this.zoomOut && this.zoomOut.isDown)
{
cam.zoom += this.zoomSpeed;
}
},
/**
* Destroys this Key Control.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.camera = null;
this.left = null;
this.right = null;
this.up = null;
this.down = null;
this.zoomIn = null;
this.zoomOut = null;
}
});
module.exports = FixedKeyControl;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../../utils/Class');
var GetValue = require('../../utils/object/GetValue');
/**
* @classdesc
* A Fixed Key Camera Control.
*
* This allows you to control the movement and zoom of a camera using the defined keys.
*
* ```javascript
* var camControl = new FixedKeyControl({
* camera: this.cameras.main,
* left: cursors.left,
* right: cursors.right,
* speed: float OR { x: 0, y: 0 }
* });
* ```
*
* Movement is precise and has no 'smoothing' applied to it.
*
* You must call the `update` method of this controller every frame.
*
* @class FixedKeyControl
* @memberof Phaser.Cameras.Controls
* @constructor
* @since 3.0.0
*
* @param {Phaser.Types.Cameras.Controls.FixedKeyControlConfig} config - The Fixed Key Control configuration object.
*/
var FixedKeyControl = new Class({
initialize:
function FixedKeyControl (config)
{
/**
* The Camera that this Control will update.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#camera
* @type {?Phaser.Cameras.Scene2D.Camera}
* @default null
* @since 3.0.0
*/
this.camera = GetValue(config, 'camera', null);
/**
* The Key to be pressed that will move the Camera left.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#left
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.left = GetValue(config, 'left', null);
/**
* The Key to be pressed that will move the Camera right.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#right
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.right = GetValue(config, 'right', null);
/**
* The Key to be pressed that will move the Camera up.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#up
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.up = GetValue(config, 'up', null);
/**
* The Key to be pressed that will move the Camera down.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#down
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.down = GetValue(config, 'down', null);
/**
* The Key to be pressed that will zoom the Camera in.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#zoomIn
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomIn = GetValue(config, 'zoomIn', null);
/**
* The Key to be pressed that will zoom the Camera out.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#zoomOut
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomOut = GetValue(config, 'zoomOut', null);
/**
* The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#zoomSpeed
* @type {number}
* @default 0.01
* @since 3.0.0
*/
this.zoomSpeed = GetValue(config, 'zoomSpeed', 0.01);
/**
* The horizontal speed the camera will move.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#speedX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.speedX = 0;
/**
* The vertical speed the camera will move.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#speedY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.speedY = 0;
var speed = GetValue(config, 'speed', null);
if (typeof speed === 'number')
{
this.speedX = speed;
this.speedY = speed;
}
else
{
this.speedX = GetValue(config, 'speed.x', 0);
this.speedY = GetValue(config, 'speed.y', 0);
}
/**
* Internal property to track the current zoom level.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#_zoom
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._zoom = 0;
/**
* A flag controlling if the Controls will update the Camera or not.
*
* @name Phaser.Cameras.Controls.FixedKeyControl#active
* @type {boolean}
* @since 3.0.0
*/
this.active = (this.camera !== null);
},
/**
* Starts the Key Control running, providing it has been linked to a camera.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#start
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
start: function ()
{
this.active = (this.camera !== null);
return this;
},
/**
* Stops this Key Control from running. Call `start` to start it again.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#stop
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
stop: function ()
{
this.active = false;
return this;
},
/**
* Binds this Key Control to a camera.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#setCamera
* @since 3.0.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to bind this Key Control to.
*
* @return {this} This Key Control instance.
*/
setCamera: function (camera)
{
this.camera = camera;
return this;
},
/**
* Applies the results of pressing the control keys to the Camera.
*
* You must call this every step, it is not called automatically.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#update
* @since 3.0.0
*
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
update: function (delta)
{
if (!this.active)
{
return;
}
if (delta === undefined) { delta = 1; }
var cam = this.camera;
if (this.up && this.up.isDown)
{
cam.scrollY -= ((this.speedY * delta) | 0);
}
else if (this.down && this.down.isDown)
{
cam.scrollY += ((this.speedY * delta) | 0);
}
if (this.left && this.left.isDown)
{
cam.scrollX -= ((this.speedX * delta) | 0);
}
else if (this.right && this.right.isDown)
{
cam.scrollX += ((this.speedX * delta) | 0);
}
// Camera zoom
if (this.zoomIn && this.zoomIn.isDown)
{
cam.zoom -= this.zoomSpeed;
if (cam.zoom < 0.1)
{
cam.zoom = 0.1;
}
}
else if (this.zoomOut && this.zoomOut.isDown)
{
cam.zoom += this.zoomSpeed;
}
},
/**
* Destroys this Key Control.
*
* @method Phaser.Cameras.Controls.FixedKeyControl#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.camera = null;
this.left = null;
this.right = null;
this.up = null;
this.down = null;
this.zoomIn = null;
this.zoomOut = null;
}
});
module.exports = FixedKeyControl;

View file

@ -1,477 +1,477 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../../utils/Class');
var GetValue = require('../../utils/object/GetValue');
/**
* @classdesc
* A Smoothed Key Camera Control.
*
* This allows you to control the movement and zoom of a camera using the defined keys.
* Unlike the Fixed Camera Control you can also provide physics values for acceleration, drag and maxSpeed for smoothing effects.
*
* ```javascript
* var controlConfig = {
* camera: this.cameras.main,
* left: cursors.left,
* right: cursors.right,
* up: cursors.up,
* down: cursors.down,
* zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
* zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
* zoomSpeed: 0.02,
* acceleration: 0.06,
* drag: 0.0005,
* maxSpeed: 1.0
* };
* ```
*
* You must call the `update` method of this controller every frame.
*
* @class SmoothedKeyControl
* @memberof Phaser.Cameras.Controls
* @constructor
* @since 3.0.0
*
* @param {Phaser.Types.Cameras.Controls.SmoothedKeyControlConfig} config - The Smoothed Key Control configuration object.
*/
var SmoothedKeyControl = new Class({
initialize:
function SmoothedKeyControl (config)
{
/**
* The Camera that this Control will update.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#camera
* @type {?Phaser.Cameras.Scene2D.Camera}
* @default null
* @since 3.0.0
*/
this.camera = GetValue(config, 'camera', null);
/**
* The Key to be pressed that will move the Camera left.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#left
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.left = GetValue(config, 'left', null);
/**
* The Key to be pressed that will move the Camera right.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#right
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.right = GetValue(config, 'right', null);
/**
* The Key to be pressed that will move the Camera up.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#up
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.up = GetValue(config, 'up', null);
/**
* The Key to be pressed that will move the Camera down.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#down
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.down = GetValue(config, 'down', null);
/**
* The Key to be pressed that will zoom the Camera in.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomIn
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomIn = GetValue(config, 'zoomIn', null);
/**
* The Key to be pressed that will zoom the Camera out.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomOut
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomOut = GetValue(config, 'zoomOut', null);
/**
* The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomSpeed
* @type {number}
* @default 0.01
* @since 3.0.0
*/
this.zoomSpeed = GetValue(config, 'zoomSpeed', 0.01);
/**
* The horizontal acceleration the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#accelX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.accelX = 0;
/**
* The vertical acceleration the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#accelY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.accelY = 0;
var accel = GetValue(config, 'acceleration', null);
if (typeof accel === 'number')
{
this.accelX = accel;
this.accelY = accel;
}
else
{
this.accelX = GetValue(config, 'acceleration.x', 0);
this.accelY = GetValue(config, 'acceleration.y', 0);
}
/**
* The horizontal drag applied to the camera when it is moving.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#dragX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.dragX = 0;
/**
* The vertical drag applied to the camera when it is moving.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#dragY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.dragY = 0;
var drag = GetValue(config, 'drag', null);
if (typeof drag === 'number')
{
this.dragX = drag;
this.dragY = drag;
}
else
{
this.dragX = GetValue(config, 'drag.x', 0);
this.dragY = GetValue(config, 'drag.y', 0);
}
/**
* The maximum horizontal speed the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#maxSpeedX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.maxSpeedX = 0;
/**
* The maximum vertical speed the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#maxSpeedY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.maxSpeedY = 0;
var maxSpeed = GetValue(config, 'maxSpeed', null);
if (typeof maxSpeed === 'number')
{
this.maxSpeedX = maxSpeed;
this.maxSpeedY = maxSpeed;
}
else
{
this.maxSpeedX = GetValue(config, 'maxSpeed.x', 0);
this.maxSpeedY = GetValue(config, 'maxSpeed.y', 0);
}
/**
* Internal property to track the speed of the control.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#_speedX
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._speedX = 0;
/**
* Internal property to track the speed of the control.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#_speedY
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._speedY = 0;
/**
* Internal property to track the zoom of the control.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#_zoom
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._zoom = 0;
/**
* A flag controlling if the Controls will update the Camera or not.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#active
* @type {boolean}
* @since 3.0.0
*/
this.active = (this.camera !== null);
},
/**
* Starts the Key Control running, providing it has been linked to a camera.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#start
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
start: function ()
{
this.active = (this.camera !== null);
return this;
},
/**
* Stops this Key Control from running. Call `start` to start it again.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#stop
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
stop: function ()
{
this.active = false;
return this;
},
/**
* Binds this Key Control to a camera.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#setCamera
* @since 3.0.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to bind this Key Control to.
*
* @return {this} This Key Control instance.
*/
setCamera: function (camera)
{
this.camera = camera;
return this;
},
/**
* Applies the results of pressing the control keys to the Camera.
*
* You must call this every step, it is not called automatically.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#update
* @since 3.0.0
*
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
update: function (delta)
{
if (!this.active)
{
return;
}
if (delta === undefined) { delta = 1; }
var cam = this.camera;
// Apply Deceleration
if (this._speedX > 0)
{
this._speedX -= this.dragX * delta;
if (this._speedX < 0)
{
this._speedX = 0;
}
}
else if (this._speedX < 0)
{
this._speedX += this.dragX * delta;
if (this._speedX > 0)
{
this._speedX = 0;
}
}
if (this._speedY > 0)
{
this._speedY -= this.dragY * delta;
if (this._speedY < 0)
{
this._speedY = 0;
}
}
else if (this._speedY < 0)
{
this._speedY += this.dragY * delta;
if (this._speedY > 0)
{
this._speedY = 0;
}
}
// Check for keys
if (this.up && this.up.isDown)
{
this._speedY += this.accelY;
if (this._speedY > this.maxSpeedY)
{
this._speedY = this.maxSpeedY;
}
}
else if (this.down && this.down.isDown)
{
this._speedY -= this.accelY;
if (this._speedY < -this.maxSpeedY)
{
this._speedY = -this.maxSpeedY;
}
}
if (this.left && this.left.isDown)
{
this._speedX += this.accelX;
if (this._speedX > this.maxSpeedX)
{
this._speedX = this.maxSpeedX;
}
}
else if (this.right && this.right.isDown)
{
this._speedX -= this.accelX;
if (this._speedX < -this.maxSpeedX)
{
this._speedX = -this.maxSpeedX;
}
}
// Camera zoom
if (this.zoomIn && this.zoomIn.isDown)
{
this._zoom = -this.zoomSpeed;
}
else if (this.zoomOut && this.zoomOut.isDown)
{
this._zoom = this.zoomSpeed;
}
else
{
this._zoom = 0;
}
// Apply to Camera
if (this._speedX !== 0)
{
cam.scrollX -= ((this._speedX * delta) | 0);
}
if (this._speedY !== 0)
{
cam.scrollY -= ((this._speedY * delta) | 0);
}
if (this._zoom !== 0)
{
cam.zoom += this._zoom;
if (cam.zoom < 0.001)
{
cam.zoom = 0.001;
}
}
},
/**
* Destroys this Key Control.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.camera = null;
this.left = null;
this.right = null;
this.up = null;
this.down = null;
this.zoomIn = null;
this.zoomOut = null;
}
});
module.exports = SmoothedKeyControl;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../../utils/Class');
var GetValue = require('../../utils/object/GetValue');
/**
* @classdesc
* A Smoothed Key Camera Control.
*
* This allows you to control the movement and zoom of a camera using the defined keys.
* Unlike the Fixed Camera Control you can also provide physics values for acceleration, drag and maxSpeed for smoothing effects.
*
* ```javascript
* var controlConfig = {
* camera: this.cameras.main,
* left: cursors.left,
* right: cursors.right,
* up: cursors.up,
* down: cursors.down,
* zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
* zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
* zoomSpeed: 0.02,
* acceleration: 0.06,
* drag: 0.0005,
* maxSpeed: 1.0
* };
* ```
*
* You must call the `update` method of this controller every frame.
*
* @class SmoothedKeyControl
* @memberof Phaser.Cameras.Controls
* @constructor
* @since 3.0.0
*
* @param {Phaser.Types.Cameras.Controls.SmoothedKeyControlConfig} config - The Smoothed Key Control configuration object.
*/
var SmoothedKeyControl = new Class({
initialize:
function SmoothedKeyControl (config)
{
/**
* The Camera that this Control will update.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#camera
* @type {?Phaser.Cameras.Scene2D.Camera}
* @default null
* @since 3.0.0
*/
this.camera = GetValue(config, 'camera', null);
/**
* The Key to be pressed that will move the Camera left.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#left
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.left = GetValue(config, 'left', null);
/**
* The Key to be pressed that will move the Camera right.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#right
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.right = GetValue(config, 'right', null);
/**
* The Key to be pressed that will move the Camera up.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#up
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.up = GetValue(config, 'up', null);
/**
* The Key to be pressed that will move the Camera down.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#down
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.down = GetValue(config, 'down', null);
/**
* The Key to be pressed that will zoom the Camera in.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomIn
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomIn = GetValue(config, 'zoomIn', null);
/**
* The Key to be pressed that will zoom the Camera out.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomOut
* @type {?Phaser.Input.Keyboard.Key}
* @default null
* @since 3.0.0
*/
this.zoomOut = GetValue(config, 'zoomOut', null);
/**
* The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomSpeed
* @type {number}
* @default 0.01
* @since 3.0.0
*/
this.zoomSpeed = GetValue(config, 'zoomSpeed', 0.01);
/**
* The horizontal acceleration the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#accelX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.accelX = 0;
/**
* The vertical acceleration the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#accelY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.accelY = 0;
var accel = GetValue(config, 'acceleration', null);
if (typeof accel === 'number')
{
this.accelX = accel;
this.accelY = accel;
}
else
{
this.accelX = GetValue(config, 'acceleration.x', 0);
this.accelY = GetValue(config, 'acceleration.y', 0);
}
/**
* The horizontal drag applied to the camera when it is moving.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#dragX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.dragX = 0;
/**
* The vertical drag applied to the camera when it is moving.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#dragY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.dragY = 0;
var drag = GetValue(config, 'drag', null);
if (typeof drag === 'number')
{
this.dragX = drag;
this.dragY = drag;
}
else
{
this.dragX = GetValue(config, 'drag.x', 0);
this.dragY = GetValue(config, 'drag.y', 0);
}
/**
* The maximum horizontal speed the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#maxSpeedX
* @type {number}
* @default 0
* @since 3.0.0
*/
this.maxSpeedX = 0;
/**
* The maximum vertical speed the camera will move.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#maxSpeedY
* @type {number}
* @default 0
* @since 3.0.0
*/
this.maxSpeedY = 0;
var maxSpeed = GetValue(config, 'maxSpeed', null);
if (typeof maxSpeed === 'number')
{
this.maxSpeedX = maxSpeed;
this.maxSpeedY = maxSpeed;
}
else
{
this.maxSpeedX = GetValue(config, 'maxSpeed.x', 0);
this.maxSpeedY = GetValue(config, 'maxSpeed.y', 0);
}
/**
* Internal property to track the speed of the control.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#_speedX
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._speedX = 0;
/**
* Internal property to track the speed of the control.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#_speedY
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._speedY = 0;
/**
* Internal property to track the zoom of the control.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#_zoom
* @type {number}
* @private
* @default 0
* @since 3.0.0
*/
this._zoom = 0;
/**
* A flag controlling if the Controls will update the Camera or not.
*
* @name Phaser.Cameras.Controls.SmoothedKeyControl#active
* @type {boolean}
* @since 3.0.0
*/
this.active = (this.camera !== null);
},
/**
* Starts the Key Control running, providing it has been linked to a camera.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#start
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
start: function ()
{
this.active = (this.camera !== null);
return this;
},
/**
* Stops this Key Control from running. Call `start` to start it again.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#stop
* @since 3.0.0
*
* @return {this} This Key Control instance.
*/
stop: function ()
{
this.active = false;
return this;
},
/**
* Binds this Key Control to a camera.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#setCamera
* @since 3.0.0
*
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to bind this Key Control to.
*
* @return {this} This Key Control instance.
*/
setCamera: function (camera)
{
this.camera = camera;
return this;
},
/**
* Applies the results of pressing the control keys to the Camera.
*
* You must call this every step, it is not called automatically.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#update
* @since 3.0.0
*
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
update: function (delta)
{
if (!this.active)
{
return;
}
if (delta === undefined) { delta = 1; }
var cam = this.camera;
// Apply Deceleration
if (this._speedX > 0)
{
this._speedX -= this.dragX * delta;
if (this._speedX < 0)
{
this._speedX = 0;
}
}
else if (this._speedX < 0)
{
this._speedX += this.dragX * delta;
if (this._speedX > 0)
{
this._speedX = 0;
}
}
if (this._speedY > 0)
{
this._speedY -= this.dragY * delta;
if (this._speedY < 0)
{
this._speedY = 0;
}
}
else if (this._speedY < 0)
{
this._speedY += this.dragY * delta;
if (this._speedY > 0)
{
this._speedY = 0;
}
}
// Check for keys
if (this.up && this.up.isDown)
{
this._speedY += this.accelY;
if (this._speedY > this.maxSpeedY)
{
this._speedY = this.maxSpeedY;
}
}
else if (this.down && this.down.isDown)
{
this._speedY -= this.accelY;
if (this._speedY < -this.maxSpeedY)
{
this._speedY = -this.maxSpeedY;
}
}
if (this.left && this.left.isDown)
{
this._speedX += this.accelX;
if (this._speedX > this.maxSpeedX)
{
this._speedX = this.maxSpeedX;
}
}
else if (this.right && this.right.isDown)
{
this._speedX -= this.accelX;
if (this._speedX < -this.maxSpeedX)
{
this._speedX = -this.maxSpeedX;
}
}
// Camera zoom
if (this.zoomIn && this.zoomIn.isDown)
{
this._zoom = -this.zoomSpeed;
}
else if (this.zoomOut && this.zoomOut.isDown)
{
this._zoom = this.zoomSpeed;
}
else
{
this._zoom = 0;
}
// Apply to Camera
if (this._speedX !== 0)
{
cam.scrollX -= ((this._speedX * delta) | 0);
}
if (this._speedY !== 0)
{
cam.scrollY -= ((this._speedY * delta) | 0);
}
if (this._zoom !== 0)
{
cam.zoom += this._zoom;
if (cam.zoom < 0.001)
{
cam.zoom = 0.001;
}
}
},
/**
* Destroys this Key Control.
*
* @method Phaser.Cameras.Controls.SmoothedKeyControl#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.camera = null;
this.left = null;
this.right = null;
this.up = null;
this.down = null;
this.zoomIn = null;
this.zoomOut = null;
}
});
module.exports = SmoothedKeyControl;

View file

@ -1,16 +1,16 @@
/**
* @typedef {object} Phaser.Types.Cameras.Controls.SmoothedKeyControlConfig
* @since 3.0.0
*
* @property {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera that this Control will update.
* @property {Phaser.Input.Keyboard.Key} [left] - The Key to be pressed that will move the Camera left.
* @property {Phaser.Input.Keyboard.Key} [right] - The Key to be pressed that will move the Camera right.
* @property {Phaser.Input.Keyboard.Key} [up] - The Key to be pressed that will move the Camera up.
* @property {Phaser.Input.Keyboard.Key} [down] - The Key to be pressed that will move the Camera down.
* @property {Phaser.Input.Keyboard.Key} [zoomIn] - The Key to be pressed that will zoom the Camera in.
* @property {Phaser.Input.Keyboard.Key} [zoomOut] - The Key to be pressed that will zoom the Camera out.
* @property {number} [zoomSpeed=0.01] - The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
* @property {(number|{x:number,y:number})} [acceleration=0] - The horizontal and vertical acceleration the camera will move.
* @property {(number|{x:number,y:number})} [drag=0] - The horizontal and vertical drag applied to the camera when it is moving.
* @property {(number|{x:number,y:number})} [maxSpeed=0] - The maximum horizontal and vertical speed the camera will move.
*/
/**
* @typedef {object} Phaser.Types.Cameras.Controls.SmoothedKeyControlConfig
* @since 3.0.0
*
* @property {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera that this Control will update.
* @property {Phaser.Input.Keyboard.Key} [left] - The Key to be pressed that will move the Camera left.
* @property {Phaser.Input.Keyboard.Key} [right] - The Key to be pressed that will move the Camera right.
* @property {Phaser.Input.Keyboard.Key} [up] - The Key to be pressed that will move the Camera up.
* @property {Phaser.Input.Keyboard.Key} [down] - The Key to be pressed that will move the Camera down.
* @property {Phaser.Input.Keyboard.Key} [zoomIn] - The Key to be pressed that will zoom the Camera in.
* @property {Phaser.Input.Keyboard.Key} [zoomOut] - The Key to be pressed that will zoom the Camera out.
* @property {number} [zoomSpeed=0.01] - The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed.
* @property {(number|{x:number,y:number})} [acceleration=0] - The horizontal and vertical acceleration the camera will move.
* @property {(number|{x:number,y:number})} [drag=0] - The horizontal and vertical drag applied to the camera when it is moving.
* @property {(number|{x:number,y:number})} [maxSpeed=0] - The maximum horizontal and vertical speed the camera will move.
*/

View file

@ -1,193 +1,194 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* Global constants.
*
* @ignore
*/
var CONST = {
/**
* Phaser Release Version
*
* @name Phaser.VERSION
* @const
* @type {string}
* @since 3.0.0
*/
VERSION: '3.50.0-beta.4',
BlendModes: require('./renderer/BlendModes'),
ScaleModes: require('./renderer/ScaleModes'),
/**
* AUTO Detect Renderer.
*
* @name Phaser.AUTO
* @const
* @type {integer}
* @since 3.0.0
*/
AUTO: 0,
/**
* Canvas Renderer.
*
* @name Phaser.CANVAS
* @const
* @type {integer}
* @since 3.0.0
*/
CANVAS: 1,
/**
* WebGL Renderer.
*
* @name Phaser.WEBGL
* @const
* @type {integer}
* @since 3.0.0
*/
WEBGL: 2,
/**
* Headless Renderer.
*
* @name Phaser.HEADLESS
* @const
* @type {integer}
* @since 3.0.0
*/
HEADLESS: 3,
/**
* In Phaser the value -1 means 'forever' in lots of cases, this const allows you to use it instead
* to help you remember what the value is doing in your code.
*
* @name Phaser.FOREVER
* @const
* @type {integer}
* @since 3.0.0
*/
FOREVER: -1,
/**
* Direction constant.
*
* @name Phaser.NONE
* @const
* @type {integer}
* @since 3.0.0
*/
NONE: 4,
/**
* Direction constant.
*
* @name Phaser.UP
* @const
* @type {integer}
* @since 3.0.0
*/
UP: 5,
/**
* Direction constant.
*
* @name Phaser.DOWN
* @const
* @type {integer}
* @since 3.0.0
*/
DOWN: 6,
/**
* Direction constant.
*
* @name Phaser.LEFT
* @const
* @type {integer}
* @since 3.0.0
*/
LEFT: 7,
/**
* Direction constant.
*
* @name Phaser.RIGHT
* @const
* @type {integer}
* @since 3.0.0
*/
RIGHT: 8,
/**
* Orientation constant.
*
* @name Phaser.ORTHOGONAL
* @const
* @type {integer}
* @since 3.2.2
*/
ORTHOGONAL: 0,
/**
* Orientation constant.
*
* @name Phaser.ISOMETRIC
* @const
* @type {integer}
* @since 3.2.2
*/
ISOMETRIC: 1,
/**
* Orientation constant.
*
* @name Phaser.STAGGERED
* @const
* @type {integer}
* @since 3.2.2
*/
STAGGERED: 2,
/**
* Orientation constant.
*
* @name Phaser.HEXAGONAL
* @const
* @type {integer}
* @since 3.2.2
*/
HEXAGONAL: 3,
fromOrientationString: function (orientation)
{
var constor = CONST.ORTHOGONAL;
if (orientation === 'isometric')
{
constor = CONST.ISOMETRIC;
}
else if (orientation === 'staggered')
{
constor = CONST.STAGGERED;
}
else if (orientation === 'hexagonal')
{
constor = CONST.HEXAGONAL;
}
return constor;
}
};
module.exports = CONST;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* Global constants.
*
* @ignore
*/
var CONST = {
/**
* Phaser Release Version
*
* @name Phaser.VERSION
* @const
* @type {string}
* @since 3.0.0
*/
VERSION: '3.50.0-beta.7',
BlendModes: require('./renderer/BlendModes'),
ScaleModes: require('./renderer/ScaleModes'),
/**
* AUTO Detect Renderer.
*
* @name Phaser.AUTO
* @const
* @type {integer}
* @since 3.0.0
*/
AUTO: 0,
/**
* Canvas Renderer.
*
* @name Phaser.CANVAS
* @const
* @type {integer}
* @since 3.0.0
*/
CANVAS: 1,
/**
* WebGL Renderer.
*
* @name Phaser.WEBGL
* @const
* @type {integer}
* @since 3.0.0
*/
WEBGL: 2,
/**
* Headless Renderer.
*
* @name Phaser.HEADLESS
* @const
* @type {integer}
* @since 3.0.0
*/
HEADLESS: 3,
/**
* In Phaser the value -1 means 'forever' in lots of cases, this const allows you to use it instead
* to help you remember what the value is doing in your code.
*
* @name Phaser.FOREVER
* @const
* @type {integer}
* @since 3.0.0
*/
FOREVER: -1,
/**
* Direction constant.
*
* @name Phaser.NONE
* @const
* @type {integer}
* @since 3.0.0
*/
NONE: 4,
/**
* Direction constant.
*
* @name Phaser.UP
* @const
* @type {integer}
* @since 3.0.0
*/
UP: 5,
/**
* Direction constant.
*
* @name Phaser.DOWN
* @const
* @type {integer}
* @since 3.0.0
*/
DOWN: 6,
/**
* Direction constant.
*
* @name Phaser.LEFT
* @const
* @type {integer}
* @since 3.0.0
*/
LEFT: 7,
/**
* Direction constant.
*
* @name Phaser.RIGHT
* @const
* @type {integer}
* @since 3.0.0
*/
RIGHT: 8,
/**
* Orientation constant.
*
* @name Phaser.ORTHOGONAL
* @const
* @type {integer}
* @since 3.2.2
*/
ORTHOGONAL: 0,
/**
* Orientation constant.
*
* @name Phaser.ISOMETRIC
* @const
* @type {integer}
* @since 3.2.2
*/
ISOMETRIC: 1,
/**
* Orientation constant.
*
* @name Phaser.STAGGERED
* @const
* @type {integer}
* @since 3.2.2
*/
STAGGERED: 2,
/**
* Orientation constant.
*
* @name Phaser.HEXAGONAL
* @const
* @type {integer}
* @since 3.2.2
*/
HEXAGONAL: 3,
fromOrientationString: function (orientation)
{
var constor = CONST.ORTHOGONAL;
if (orientation === 'isometric')
{
constor = CONST.ISOMETRIC;
}
else if (orientation === 'staggered')
{
constor = CONST.STAGGERED;
}
else if (orientation === 'hexagonal')
{
constor = CONST.HEXAGONAL;
}
return constor;
}
};
module.exports = CONST;

File diff suppressed because it is too large Load diff

View file

@ -41,11 +41,11 @@ var DebugHeader = function (game)
var audioType;
if (deviceAudio.webAudio && !(audioConfig && audioConfig.disableWebAudio))
if (deviceAudio.webAudio && !audioConfig.disableWebAudio)
{
audioType = 'Web Audio';
}
else if ((audioConfig && audioConfig.noAudio) || (!deviceAudio.webAudio && !deviceAudio.audioData))
else if (audioConfig.noAudio || (!deviceAudio.webAudio && !deviceAudio.audioData))
{
audioType = 'No Audio';
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,36 +1,35 @@
/**
* @typedef {object} Phaser.Types.Core.GameConfig
* @since 3.0.0
*
* @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=undefined] - The DOM element that will contain the game canvas, or its `id`. If undefined, or if the named element doesn't exist, the game canvas is appended to the document body. If `null` no parent will be used and you are responsible for adding the canvas to the dom.
* @property {HTMLCanvasElement} [canvas=null] - Provide your own Canvas element for Phaser to use instead of creating one.
* @property {string} [canvasStyle=null] - CSS styles to apply to the game canvas instead of Phasers default styles.
* @property {boolean}[customEnvironment=false] - 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`.
* @property {CanvasRenderingContext2D} [context] - Provide your own Canvas Context for Phaser to use, instead of creating one.
* @property {(Phaser.Scene|Phaser.Scene[]|Phaser.Types.Scenes.SettingsConfig|Phaser.Types.Scenes.SettingsConfig[]|Phaser.Types.Scenes.CreateSceneFromObjectConfig|Phaser.Types.Scenes.CreateSceneFromObjectConfig[]|function|function[])} [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 }`. See the `sceneConfig` argument in `Phaser.Scenes.SceneManager#add`.
* @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|Phaser.Types.Core.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} [transparent=false] - Whether the game canvas will have a transparent background.
* @property {(boolean|Phaser.Types.Core.BannerConfig)} [banner=false] - Configuration for the banner printed in the browser console when the game starts.
* @property {Phaser.Types.Core.DOMContainerConfig} [dom] - The DOM Container configuration object.
* @property {Phaser.Types.Core.FPSConfig} [fps] - Game loop configuration.
* @property {Phaser.Types.Core.RenderConfig} [render] - Game renderer configuration.
* @property {(string|number)} [backgroundColor=0x000000] - The background color of the game canvas. The default is black.
* @property {Phaser.Types.Core.CallbacksConfig} [callbacks] - Optional callbacks to run before or after game boot.
* @property {Phaser.Types.Core.LoaderConfig} [loader] - Loader configuration.
* @property {Phaser.Types.Core.ImagesConfig} [images] - Images configuration.
* @property {Phaser.Types.Core.PhysicsConfig} [physics] - Physics configuration.
* @property {Phaser.Types.Core.PluginObject|Phaser.Types.Core.PluginObjectItem[]} [plugins] - Plugins to install.
* @property {Phaser.Types.Core.ScaleConfig} [scale] - The Scale Manager configuration.
* @property {Phaser.Types.Core.AudioConfig} [audio] - The Audio Configuration object.
*/
/**
* @typedef {object} Phaser.Types.Core.GameConfig
* @since 3.0.0
*
* @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} [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=undefined] - The DOM element that will contain the game canvas, or its `id`. If undefined, or if the named element doesn't exist, the game canvas is appended to the document body. If `null` no parent will be used and you are responsible for adding the canvas to the dom.
* @property {HTMLCanvasElement} [canvas=null] - Provide your own Canvas element for Phaser to use instead of creating one.
* @property {string} [canvasStyle=null] - CSS styles to apply to the game canvas instead of Phasers default styles.
* @property {boolean}[customEnvironment=false] - 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`.
* @property {CanvasRenderingContext2D} [context] - Provide your own Canvas Context for Phaser to use, instead of creating one.
* @property {(Phaser.Scene|Phaser.Scene[]|Phaser.Types.Scenes.SettingsConfig|Phaser.Types.Scenes.SettingsConfig[]|Phaser.Types.Scenes.CreateSceneFromObjectConfig|Phaser.Types.Scenes.CreateSceneFromObjectConfig[]|function|function[])} [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 }`. See the `sceneConfig` argument in `Phaser.Scenes.SceneManager#add`.
* @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|Phaser.Types.Core.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} [transparent=false] - Whether the game canvas will have a transparent background.
* @property {(boolean|Phaser.Types.Core.BannerConfig)} [banner=false] - Configuration for the banner printed in the browser console when the game starts.
* @property {Phaser.Types.Core.DOMContainerConfig} [dom] - The DOM Container configuration object.
* @property {Phaser.Types.Core.FPSConfig} [fps] - Game loop configuration.
* @property {Phaser.Types.Core.RenderConfig} [render] - Game renderer configuration.
* @property {(string|number)} [backgroundColor=0x000000] - The background color of the game canvas. The default is black.
* @property {Phaser.Types.Core.CallbacksConfig} [callbacks] - Optional callbacks to run before or after game boot.
* @property {Phaser.Types.Core.LoaderConfig} [loader] - Loader configuration.
* @property {Phaser.Types.Core.ImagesConfig} [images] - Images configuration.
* @property {Phaser.Types.Core.PhysicsConfig} [physics] - Physics configuration.
* @property {Phaser.Types.Core.PluginObject|Phaser.Types.Core.PluginObjectItem[]} [plugins] - Plugins to install.
* @property {Phaser.Types.Core.ScaleConfig} [scale] - The Scale Manager configuration.
* @property {Phaser.Types.Core.AudioConfig} [audio] - The Audio Configuration object.
*/

View file

@ -2,6 +2,7 @@
* @typedef {object} Phaser.Types.Core.ImagesConfig
* @since 3.0.0
*
* @property {string} [default] - URL to use for the 'default' texture.
* @property {string} [missing] - URL to use for the 'missing' texture.
* @property {string} [default] - A base64 encoded image file to use as the 'default' texture.
* @property {string} [missing] - A base64 encoded image file to use as the 'missing' texture.
* @property {string} [white] - A base64 encoded image file to use as the 'white' texture.
*/

View file

@ -3,5 +3,7 @@
* @since 3.0.0
*
* @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.
* @property {boolean} [preventDefaultDown=true] - If `true` the DOM `mousedown` event will have `preventDefault` set.
* @property {boolean} [preventDefaultUp=true] - If `true` the DOM `mouseup` event will have `preventDefault` set.
* @property {boolean} [preventDefaultMove=true] - If `true` the DOM `mousemove` event will have `preventDefault` set.
*/

View file

@ -1,19 +1,19 @@
/**
* @typedef {object} Phaser.Types.Core.RenderConfig
* @since 3.0.0
*
* @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} [antialiasGL=true] - Sets the `antialias` property when the WebGL context is created. Setting this value does not impact any subsequent textures that are created, or the canvas style attributes.
* @property {boolean} [desynchronized=false] - When set to `true` it will create a desynchronized context for both 2D and WebGL. See https://developers.google.com/web/updates/2019/05/desynchronized for details.
* @property {boolean} [pixelArt=false] - Sets `antialias` to false and `roundPixels` to true. This is the best setting for pixel-art games.
* @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. Boolean that indicates if the canvas contains an alpha channel. If set to false, the browser now knows that the backdrop is always opaque, which can speed up drawing of transparent content and images.
* @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.
* @property {integer} [maxTextures=-1] - When in WebGL mode, this sets the maximum number of GPU Textures to use. The default, -1, will use all available units. The WebGL1 spec says all browsers should provide a minimum of 8.
* @property {string} [mipmapFilter='LINEAR'] - The mipmap magFilter to be used when creating WebGL textures.
*/
/**
* @typedef {object} Phaser.Types.Core.RenderConfig
* @since 3.0.0
*
* @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} [antialiasGL=true] - Sets the `antialias` property when the WebGL context is created. Setting this value does not impact any subsequent textures that are created, or the canvas style attributes.
* @property {boolean} [desynchronized=false] - When set to `true` it will create a desynchronized context for both 2D and WebGL. See https://developers.google.com/web/updates/2019/05/desynchronized for details.
* @property {boolean} [pixelArt=false] - Sets `antialias` to false and `roundPixels` to true. This is the best setting for pixel-art games.
* @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. Boolean that indicates if the canvas contains an alpha channel. If set to false, the browser now knows that the backdrop is always opaque, which can speed up drawing of transparent content and images.
* @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.
* @property {integer} [maxTextures=-1] - When in WebGL mode, this sets the maximum number of GPU Textures to use. The default, -1, will use all available units. The WebGL1 spec says all browsers should provide a minimum of 8.
* @property {string} [mipmapFilter='LINEAR'] - The mipmap magFilter to be used when creating WebGL textures.
*/

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