├── .editorconfig
├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .istanbul.yml
├── .npmignore
├── .prettierrc
├── .publishrc
├── .travis.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── assets
├── nnp.gif
├── np.gif
└── what-is-nine-patch.png
├── example
└── index.ts
├── karma.conf.js
├── package-lock.json
├── package.json
├── src
├── com
│ └── koreez
│ │ └── plugin
│ │ ├── NinePatchPlugin.ts
│ │ └── ninepatch
│ │ ├── INinePatchConfig.ts
│ │ ├── INinePatchCreator.ts
│ │ ├── INinePatchFactory.ts
│ │ ├── IPatchesConfig.ts
│ │ └── NinePatch.ts
└── index.ts
├── static
├── assets
│ ├── metalPanel_blueCorner.png
│ ├── player.png
│ ├── squareGreen.png
│ └── squareYellow.png
├── index.html
├── manifest.json
├── scripts
│ └── cache-polyfill.js
├── service-worker.js
└── styles
│ └── main.css
├── test
├── README.md
├── com
│ └── koreez
│ │ └── plugin
│ │ └── plugin.test.ts
└── entry.ts
├── tsconfig.json
├── tsconfig.test.json
├── tslint.json
├── tslint.test.json
├── types
└── phaser.d.ts
├── webpack.config.js
└── webpack.example.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | charset = utf-8
6 | trim_trailing_whitespace = true
7 | indent_style = space
8 | indent_size = 4
9 |
10 | [*.{ts}]
11 | indent_style = space
12 | indent_size = 4
13 |
14 | [*.{js,json}]
15 | indent_style = space
16 | indent_size = 2
17 |
18 | [{.codeclimate.yml,.eslintignore,.eslintrc,.istanbul.yml,.publishrc,.travis.yml}]
19 | indent_style = space
20 | indent_size = 2
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Expected Behavior
4 |
5 |
6 |
7 | ## Current Behavior
8 |
9 |
10 |
11 | ## Possible Solution
12 |
13 |
14 |
15 | ## Steps to Reproduce (for bugs)
16 |
17 |
18 | 1.
19 | 2.
20 | 3.
21 | 4.
22 |
23 | ## Context
24 |
25 |
26 |
27 | ## Your Environment
28 |
29 | * Version used:
30 | * Environment name and version (e.g. Chrome 39, node.js 5.4):
31 | * Operating System and version (desktop or mobile):
32 | * Link to your project:
33 |
34 | # Stack trace
35 |
36 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Description
4 |
5 |
6 |
7 | ## Related Issue
8 |
9 |
10 |
11 |
12 |
13 |
14 | ## Motivation and Context
15 |
16 |
17 |
18 | ## How Has This Been Tested?
19 |
20 |
21 |
22 |
23 |
24 | ## Types of changes
25 |
26 |
27 |
28 | - [ ] Updated docs / Refactor code / Added a tests case (non-breaking change)
29 | - [ ] Bug fix (non-breaking change which fixes an issue)
30 | - [ ] New feature (non-breaking change which adds functionality)
31 | - [ ] Breaking change (fix or feature that would cause existing functionality to change)
32 |
33 | ## Checklist:
34 |
35 |
36 |
37 |
38 | - [ ] My code follows the code style of this project.
39 | - [ ] My change requires a change to the documentation.
40 | - [ ] I have updated the documentation accordingly.
41 | - [ ] I have read the **CONTRIBUTING** document.
42 | - [ ] I have added tests to cover my changes.
43 | - [ ] All new and existing tests passed.
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .nyc_output
3 | coverage
4 | dist/lib
5 | dist-test
6 | lib
7 | lib-test
8 | node_modules
9 | *.as
10 | *.iml
11 | src/**/*.js
12 | src/**/*.js.map
13 | test/**/*.js
14 | test/**/*.js.map
15 | npm-debug.log
16 | yarn-error.log
17 | .DS_Store
18 |
--------------------------------------------------------------------------------
/.istanbul.yml:
--------------------------------------------------------------------------------
1 | verbose: false
2 | instrumentation:
3 | root: lib
4 | extensions:
5 | - .ts
6 | # default-excludes: true
7 | # excludes: []
8 | # variable: __coverage__
9 | # compact: true
10 | # preserve-comments: false
11 | # complete-copy: false
12 | # save-baseline: false
13 | # baseline-file: ./coverage/coverage-baseline.raw.json
14 | # include-all-sources: false
15 | # include-pid: false
16 | # es-modules: true
17 | # auto-wrap: true
18 | # reporting:
19 | # print: summary
20 | # reports:
21 | # - lcov
22 | # dir: ./coverage
23 | # summarizer: pkg
24 | # report-config: {}
25 | # watermarks:
26 | # statements: [50, 80]
27 | # functions: [50, 80]
28 | # branches: [50, 80]
29 | # lines: [50, 80]
30 | # hooks:
31 | # hook-run-in-context: false
32 | # post-require-hook: null
33 | # handle-sigint: false
34 | # check:
35 | # global:
36 | # statements: 0
37 | # lines: 0
38 | # branches: 0
39 | # functions: 0
40 | # excludes: []
41 | # each:
42 | # statements: 0
43 | # lines: 0
44 | # branches: 0
45 | # functions: 0
46 | # excludes: []
47 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /.nyc_output
3 | /.vscode
4 | /coverage
5 | /dist
6 | /dist-test
7 | /docs
8 | /lib-test
9 | /not-ported-extensions
10 | /src
11 | /test
12 | /transpiled-code
13 | /typings
14 | CODE_OF_CONDUCT.md
15 | CONTRIBUTING.md
16 | ISSUE_TEMPLATE.md
17 | PULL_REQUEST_TEMPLATE.md
18 | karma.conf.js
19 | tsconfig.json
20 | tsconfig.test.json
21 | tslint.json
22 | tslint.test.json
23 | webpack.config.js
24 | yarn.lock
25 | .editorconfig
26 | .gitignore
27 | .istanbul.yml
28 | .npmignore
29 | .prettierrc
30 | .publishrc
31 | .travis.yml
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "tabWidth": 4,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": false,
7 | "trailingComma": "none",
8 | "bracketSpacing": true
9 | }
10 |
--------------------------------------------------------------------------------
/.publishrc:
--------------------------------------------------------------------------------
1 | {
2 | "validations": {
3 | "vulnerableDependencies": false,
4 | "uncommittedChanges": true,
5 | "untrackedFiles": true,
6 | "sensitiveData": false,
7 | "branch": "master",
8 | "gitTag": true
9 | },
10 | "confirm": true,
11 | "publishTag": "latest --access public",
12 | "prePublishScript": false,
13 | "postPublishScript": false
14 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - stable
4 | env:
5 | global:
6 | - CC_TEST_REPORTER_ID=71e455189fdcb3925ba38e620c090f72e7734ab75219b2a39fbaaad0021daab7
7 | before_install:
8 | - export CHROME_BIN=chromium-browser
9 | - export DISPLAY=:99.0
10 | - sh -e /etc/init.d/xvfb start
11 | - yarn config set registry "https://registry.npmjs.org"
12 | - yarn global add greenkeeper-lockfile@1
13 | - yarn global add codeclimate-test-reporter
14 | before_script:
15 | - greenkeeper-lockfile-update
16 | script:
17 | - yarn test
18 | after_script:
19 | - greenkeeper-lockfile-upload
20 | after_success:
21 | - codeclimate-test-reporter < coverage/lcov.info
22 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Phaser3 Nine Patch Changelog:
2 |
3 | ## Phaser3 Nine Patch 2.0.0
4 |
5 | ### v2.0.1
6 |
7 | #### Added
8 |
9 | - Add `setTint`, `setTintFill` and `clearTint` methods to be able to change tint.
10 |
11 | ### v2.0.0
12 |
13 | #### Added
14 |
15 | - Now NinePatch class extends Phaser.GameObjects.Container instead of Phaser.GameObjects.RenderTexture to not add additional draws and calls.
16 |
17 | ### v1.1.5
18 |
19 | #### Fixed
20 |
21 | - Minor fixings.
22 |
23 | ### v1.1.4
24 |
25 | #### Fixed
26 |
27 | - Minor fixings.
28 |
29 | ### v1.1.3
30 |
31 | #### Fixed
32 |
33 | - Fix canvas rendering issue.
34 |
35 | ### v1.1.2
36 |
37 | #### Added
38 |
39 | - Add `setTexture` and `setFrame` methods to be able to change texture and/or frame dynamically (see #18).
40 |
41 | #### Fixed
42 |
43 | - Fix `addToScene` to be optional for nine patch creator.
44 |
45 | ### v1.1.1 - Planned stable version
46 |
47 | - fixed resize method to be chainable
48 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | - Using welcoming and inclusive language
12 | - Being respectful of differing viewpoints and experiences
13 | - Gracefully accepting constructive criticism
14 | - Focusing on what is best for the community
15 | - Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | - Trolling, insulting/derogatory comments, and personal or political attacks
21 | - Public or private harassment
22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | - Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@koreez.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to phaser3-ninepatch-plugin
2 |
3 | ## Setup
4 |
5 | 1 - Clone your fork of the repository:
6 |
7 | ```
8 | $ git clone https://github.com/koreezgames/phaser3-ninepatch-plugin.git
9 | ```
10 |
11 | 2 - Install npm dependencies using yarn:
12 |
13 | ```
14 | $ yarn install
15 | ```
16 |
17 | 3 - Run start process
18 |
19 | ```
20 | $ yarn run start
21 | ```
22 |
23 | 4 - Run test process
24 |
25 | ```
26 | $ yarn test
27 | ```
28 |
29 | ## Guidelines
30 |
31 | - Please try to [combine multiple commits before
32 | pushing](http://stackoverflow.com/questions/6934752/combining-multiple-commits-before-pushing-in-git).
33 |
34 | - Please use `TDD` when fixing bugs. This means that you should write a unit
35 | test that fails because it reproduces the issue, then fix the issue and finally run
36 | the test to ensure that the issue has been resolved. This helps us to prevent
37 | fixed bugs from happening again in the future.
38 |
39 | - Always format your code using `yarn run autoformat`.
40 |
41 | - Please keep the test coverage at 100%. Write additional unit test if
42 | necessary.
43 |
44 | - Please create an issue before sending a PR if your commit is going to change the
45 | public interface of the package or it includes significant architecture
46 | changes.
47 |
48 | - Feel free to ask for help from other members of the Koreez team via the
49 | [github issues](https://github.com/koreezgames/phaser3-ninepatch-plugin/issues).
50 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Koreez LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Phaser3 Nine Patch
2 |
3 | [](https://github.com/koreezgames/phaser3-ninepatch-plugin/blob/master/LICENSE)
4 | [](https://travis-ci.org/koreezgames/phaser3-ninepatch-plugin)
5 | [](https://codebeat.co/projects/github-com-koreezgames-phaser3-ninepatch-plugin-master)
6 | [](https://codeclimate.com/github/koreezgames/phaser3-ninepatch-plugin/test_coverage)
7 | [](https://badge.fury.io/js/%40koreez%2Fphaser3-ninepatch)
8 | [](https://greenkeeper.io/)
9 | [](https://github.com/prettier/prettier)
10 |
11 | Phaser3 Nine Patch plugin adds 9-slice scaling support to Phaser3!
12 |
13 | #### Resizing with nine patch
14 |
15 | 
16 |
17 | #### Resizing without nine patch
18 |
19 | 
20 |
21 | Key features:
22 |
23 | - Blazing fast
24 | - Low memory usage
25 | - Easy to use API
26 |
27 | ## What is Nine-Patch?
28 |
29 | A **Nine-Patch** is an image format that uses extra information, defining what parts of it should be scaled (and which are not) when the image is rendered in a larger or smaller size. This technique is very useful for creating UI components like buttons, panels, containers, etc.
30 |
31 | Using this technique, you can define the background of multiples UI components like panels or buttons with the same image asset. You can also create large panels with a reduced image asset so is very useful for optimizing your project resources.
32 |
33 | 
34 |
35 | ## Getting Started
36 |
37 | First you want to get a fresh copy of the plugin. You can get it from this repo or from npm, ain't that handy.
38 |
39 | [](https://www.npmjs.com/package/@koreez/phaser3-ninepatch)
40 |
41 | ```
42 | npm install @koreez/phaser3-ninepatch --save
43 | ```
44 |
45 | ## Usage
46 |
47 | ### Load the plugin
48 |
49 | You still need to load the plugin in your game. This is done just like any other global plugin in Phaser3.
50 | So, to load the plugin, include it in phaser game config.
51 |
52 | ```javascript
53 | {
54 | type: Phaser.WEBGL,
55 | width: 540,
56 | height: 960,
57 | backgroundColor: '#626262',
58 | parent: 'gameContainer',
59 | scene: [GameScene],
60 | plugins: {
61 | global: [{ key: 'NinePatchPlugin', plugin: NinePatchPlugin, start: true }],
62 | },
63 | }
64 | ```
65 |
66 | The plugin will patch your Phaser game with additional add/make methods so the NinePatch game object fits up in Phaser like any normal object!
67 |
68 | ### Adding a container
69 |
70 | Also adding and creating of 9-patch images is exposed through Phaser's GameObjectCreator and GameObjectFactory.
71 | So you can add a 9-patch image to your game just like any other image once it's preloaded!
72 |
73 | ```javascript
74 | //We specify the x and y position, the width and height and the key for the image of the image. It will be automaticly scaled!
75 | this.add.ninePatch(100, 100, 200, 400, "my-image", null, {
76 | top: 10, // Amount of pixels for top
77 | bottom: 20, // Amount of pixels for bottom
78 | left: 30, // Amount of pixels for left
79 | right: 40 // Amount of pixels for right
80 | });
81 | ```
82 |
83 | Or if you'd want to do something with it first:
84 |
85 | ```javascript
86 | //Two options here, first we use Phaser
87 | var ninePatch = this.make.ninePatch({
88 | key: "my-image",
89 | width: 200,
90 | height: 200,
91 | patchesConfig: {
92 | top: 10, // Amount of pixels for top
93 | bottom: 20, // Amount of pixels for bottom
94 | left: 30, // Amount of pixels for left
95 | right: 40 // Amount of pixels for right
96 | }
97 | });
98 | ninePatch.x = 20;
99 | ninePatch.y = 20;
100 | this.add.existing(ninePatch);
101 |
102 | //Or we use the Constructor
103 | var ninePatch = new NinePatch(this, 0, 0, 200, 50, "my-image", null, {
104 | top: 10, // Amount of pixels for top
105 | bottom: 20, // Amount of pixels for bottom
106 | left: 30, // Amount of pixels for left
107 | right: 40 // Amount of pixels for right
108 | });
109 | ninePatch.x = 50;
110 | ninePatch.y = 50;
111 | this.add.existing(nineSlice);
112 | ```
113 |
114 | ### Using a Texture Atlas
115 |
116 | It's also possible to use an image that's located inside a Texture atlas. The only difference then is that you don't have to preload the image, instead you use the object's constructor and pass the framedata directly on creation:
117 |
118 | ```javascript
119 | //Add an nineslice image with an texture atlas
120 | var ninePatch = new NinePatch(
121 | this, // Phaser.Scene
122 | 150, // x position
123 | 100, // y position
124 | 200, // expected width
125 | 100, // expected height
126 | "buttons", // atlas key
127 | "btn_clean.png", // Image frame
128 | {
129 | top: 20, // Amount of pixels for top
130 | bottom: 23, // Amount of pixels for bottom
131 | left: 27, // Amount of pixels for left
132 | right: 28 // Amount of pixels for right
133 | }
134 | );
135 | this.add.existing(ninePatch);
136 | ```
137 |
138 | ### Resize method
139 |
140 | 9-patch image has a resize method which lets you expand/shorten the width or length of the image.
141 | When using resize method, make sure values are not lower than the width of the image corners
142 |
143 | ```javascript
144 | var ninePatch = this.add.ninePatch(5, 5, 48, 48, "image", null, {
145 | top: 5 // Amount of pixels for top, bottom, left, right
146 | });
147 | ninePatch.resize(100, 200);
148 | ```
149 |
150 | ## Credits
151 |
152 | Big thanks to this great repo:
153 |
154 | https://github.com/orange-games/phaser-nineslice
155 |
156 | ## License
157 |
158 | [MIT](LICENSE)
159 |
--------------------------------------------------------------------------------
/assets/nnp.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/assets/nnp.gif
--------------------------------------------------------------------------------
/assets/np.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/assets/np.gif
--------------------------------------------------------------------------------
/assets/what-is-nine-patch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/assets/what-is-nine-patch.png
--------------------------------------------------------------------------------
/example/index.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import "phaser";
4 | import { NinePatch } from "../src/com/koreez/plugin/ninepatch/NinePatch";
5 | import { NinePatchPlugin } from "../src/com/koreez/plugin/NinePatchPlugin";
6 |
7 | export default class Game extends Phaser.Game {
8 | public centerX: number;
9 | public centerY: number;
10 | constructor(config: GameConfig) {
11 | super(config);
12 | }
13 | }
14 |
15 | function preload() {
16 | console.log("preload");
17 | this.load.image("metalPanel_blueCorner", "static/assets/metalPanel_blueCorner.png");
18 | this.load.image("squareGreen", "static/assets/squareGreen.png");
19 | this.load.image("squareYellow", "static/assets/squareYellow.png");
20 | }
21 |
22 | function create() {
23 | console.log("create");
24 | // We specify the x and y position, the width and height and the key for the image of the image.
25 | // It will be automatically scaled!
26 | const metalPanel = this.add.ninePatch(200, 200, 300, 300, "metalPanel_blueCorner", null, {
27 | bottom: 11, // Amount of pixels for bottom
28 | left: 11, // Amount of pixels for left
29 | right: 53, // Amount of pixels for right
30 | top: 32 // Amount of pixels for top
31 | });
32 | let metalPanelDir = 0.6;
33 | metalPanel.setTint(0xff0000);
34 | this.tweens.add({
35 | /* tslint:disable */
36 | targets: metalPanel,
37 | duration: 3000,
38 | y: 190,
39 | onUpdate: (tween: any) => {
40 | metalPanel.resize(metalPanel.width + metalPanelDir, metalPanel.height + metalPanelDir);
41 | },
42 | onYoyo: (tween: any) => {
43 | metalPanelDir = -1 * metalPanelDir;
44 | },
45 | onRepeat: (tween: any) => {
46 | metalPanelDir = -1 * metalPanelDir;
47 | },
48 | repeat: -1,
49 | yoyo: true
50 | /* tslint:enable */
51 | });
52 | setTimeout(() => {
53 | metalPanel.setTintFill(0xff0000);
54 | setTimeout(() => {
55 | metalPanel.clearTint(0xff0000);
56 | }, 3000);
57 | }, 3000);
58 | let squareGreen = this.make.ninePatch({
59 | /* tslint:disable */
60 | key: "squareGreen",
61 | width: 100,
62 | height: 50,
63 | patchesConfig: {
64 | bottom: 14, // Amount of pixels for bottom
65 | left: 6, // Amount of pixels for left
66 | right: 6, // Amount of pixels for right
67 | top: 10 // Amount of pixels for top
68 | }
69 | /* tslint:enable */
70 | });
71 |
72 | squareGreen.x = 450;
73 | squareGreen.y = 50;
74 | this.add.existing(squareGreen);
75 | let squareGreenDir = 1;
76 | this.tweens.add({
77 | /* tslint:disable */
78 | targets: squareGreen,
79 | duration: 3000,
80 | x: 550,
81 | onUpdate: (tween: any) => {
82 | squareGreen.resize(squareGreen.width + squareGreenDir, squareGreen.height);
83 | },
84 | onYoyo: (tween: any) => {
85 | squareGreenDir = -1 * squareGreenDir;
86 | },
87 | onRepeat: (tween: any) => {
88 | squareGreenDir = -1 * squareGreenDir;
89 | },
90 | repeat: -1,
91 | yoyo: true
92 | /* tslint:enable */
93 | });
94 |
95 | this.cache.custom.ninePatch.add("squareYellow", {
96 | /* tslint:disable */
97 | bottom: 14, // Amount of pixels for bottom
98 | left: 6, // Amount of pixels for left
99 | right: 6, // Amount of pixels for right
100 | top: 10 // Amount of pixels for top
101 | /* tslint:enable */
102 | });
103 |
104 | const squareYellow = this.add.ninePatch(550, 500, 300, 100, "squareYellow");
105 | let squareYellowDir = 0.6;
106 | this.tweens.add({
107 | /* tslint:disable */
108 | targets: squareYellow,
109 | duration: 3000,
110 | x: 150,
111 | repeat: -1,
112 | yoyo: true,
113 | onUpdate: (tween: any) => {
114 | squareYellow.resize(squareYellow.width + squareYellowDir, squareYellow.height);
115 | },
116 | onYoyo: (tween: any) => {
117 | squareYellowDir = -1 * squareYellowDir;
118 | },
119 | onRepeat: (tween: any) => {
120 | squareYellowDir = -1 * squareYellowDir;
121 | }
122 | /* tslint:enable */
123 | });
124 |
125 | // Or we use the Constructor
126 | const newNinePatch = new NinePatch(this, 630, 300, 200, 50, "squareGreen", null, {
127 | /* tslint:disable */
128 | bottom: 14, // Amount of pixels for bottom
129 | left: 6, // Amount of pixels for left
130 | right: 6, // Amount of pixels for right
131 | top: 10 // Amount of pixels for top
132 | /* tslint:enable */
133 | });
134 | this.add.existing(newNinePatch);
135 | let newNinePatchDir = 0.6;
136 | this.tweens.add({
137 | /* tslint:disable */
138 | targets: newNinePatch,
139 | duration: 3000,
140 | rotation: Math.PI,
141 | repeat: -1,
142 | yoyo: true,
143 | onUpdate: (tween: any) => {
144 | newNinePatch.resize(newNinePatch.width + newNinePatchDir, newNinePatch.height);
145 | },
146 | onYoyo: (tween: any) => {
147 | newNinePatchDir = -1 * newNinePatchDir;
148 | },
149 | onRepeat: (tween: any) => {
150 | newNinePatchDir = -1 * newNinePatchDir;
151 | }
152 | /* tslint:enable */
153 | });
154 | setTimeout(() => {
155 | newNinePatch.setTexture("squareYellow");
156 | }, 4000);
157 | }
158 |
159 | document.onreadystatechange = () => {
160 | if (document.readyState === "complete") {
161 | const config = {
162 | banner: true,
163 | height: 600,
164 | plugins: {
165 | global: [{ key: "NinePatchPlugin", plugin: NinePatchPlugin, start: true }]
166 | },
167 | scene: {
168 | create,
169 | preload
170 | },
171 | type: Phaser.AUTO,
172 | width: 800
173 | };
174 | (window as any).game = new Game(config);
175 | }
176 | };
177 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | process.env.TEST = true;
2 | process.env.NODE_ENV = "test";
3 |
4 | const webpackConfig = require("./webpack.config.js")({ production: false, karma: true });
5 |
6 | delete webpackConfig.entry;
7 |
8 | module.exports = config => {
9 | var configuration = {
10 | basePath: "",
11 | frameworks: ["mocha", "chai", "sinon", "es6-shim"],
12 | files: [
13 | { pattern: "node_modules/bluebird/js/browser/bluebird.js", include: true },
14 | { pattern: "node_modules/phaser/dist/phaser.js", include: true },
15 | { pattern: "./test/**/**/**.test.ts", include: true },
16 | { pattern: "**/*.map", served: true, included: false, watched: true }
17 | ],
18 | preprocessors: {
19 | "./**/**/**/**.ts": ["sourcemap"],
20 | "./test/**/**/**.test.ts": ["webpack"]
21 | },
22 | webpack: webpackConfig,
23 | webpackMiddleware: {
24 | noInfo: true
25 | },
26 | plugins: [
27 | "karma-webpack",
28 | "karma-sourcemap-writer",
29 | "karma-sourcemap-loader",
30 | "karma-remap-istanbul",
31 | "karma-mocha-reporter",
32 | "karma-mocha",
33 | "karma-chai",
34 | "karma-sinon",
35 | "karma-es6-shim",
36 | "karma-coverage-istanbul-reporter"
37 | ],
38 | reporters: config.singleRun ? ["dots", "mocha", "coverage-istanbul"] : ["dots", "mocha"],
39 | coverageIstanbulReporter: {
40 | reports: ["html", "lcov", "lcovonly", "text-summary"],
41 | dir: "coverage",
42 | fixWebpackSourcePaths: true,
43 | "report-config": {
44 | html: {
45 | subdir: "html-report"
46 | }
47 | }
48 | },
49 | port: 9876,
50 | colors: true,
51 | logLevel: config.LOG_INFO,
52 | autoWatch: true,
53 | browsers: []
54 | };
55 |
56 | if (process.env.TRAVIS) {
57 | configuration.browsers.push("PhantomJS");
58 | configuration.plugins.push("karma-phantomjs-launcher");
59 | } else {
60 | configuration.browsers.push("PhantomJS");
61 | configuration.plugins.push("karma-phantomjs-launcher");
62 | }
63 |
64 | config.set(configuration);
65 | };
66 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@koreez/phaser3-ninepatch",
3 | "version": "2.0.2",
4 | "description": "Phaser3 Nine Patch",
5 | "main": "lib/index.js",
6 | "typings": "lib/index.d.ts",
7 | "scripts": {
8 | "start": "webpack-dev-server --config ./webpack.example.config.js",
9 | "test": "karma start --single-run",
10 | "mocha": "mocha test/**/*.test.ts --require ts-node/register",
11 | "autoformat": "prettier --config .prettierrc --write {src,test}{/,/**/}{*,*.test}.ts",
12 | "tslint-check:src": "tslint-config-prettier-check ./tslint.json",
13 | "tslint-check:test": "tslint-config-prettier-check ./tslint.test.json",
14 | "tslint:src": "tslint --project tsconfig.json",
15 | "tslint:test": "tslint --config tslint.test.json --project tsconfig.test.json",
16 | "tslint": "npm run tslint-check:src && npm run tslint-check:test && npm run tslint:src && npm run tslint:test",
17 | "clean-up": "rimraf .nyc_output && rimraf coverage && rimraf lib && rimraf lib-test && rimraf dist-test",
18 | "compile:src": "tsc -d",
19 | "compile:test": "tsc -p tsconfig.test.json -d",
20 | "dev": "webpack",
21 | "build": "webpack --env.production",
22 | "prepare": "npm run clean-up && npm run compile:src",
23 | "prepublishOnly": "publish-please guard",
24 | "publish-please": "npm run tslint && npm run autoformat && npm run clean-up && npm run test && publish-please"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "git@github.com:koreezgames/phaser3-ninepatch-plugin.git"
29 | },
30 | "publishConfig": {
31 | "registry": "https://registry.npmjs.org"
32 | },
33 | "keywords": [
34 | "Phaser3",
35 | "Phaser",
36 | "ninepatch",
37 | "nine patch",
38 | "nine slice"
39 | ],
40 | "author": "Koreez LLC",
41 | "contributors": [
42 | "Sargis Sargsyan ",
43 | "Gnun Ulikhanyan "
44 | ],
45 | "license": "MIT",
46 | "bugs": {
47 | "url": "https://github.com/koreezgames/phaser3-ninepatch-plugin/issues"
48 | },
49 | "homepage": "https://github.com/koreezgames/phaser3-ninepatch-plugin#readme",
50 | "dependencies": {},
51 | "peerDependencies": {
52 | "phaser": "^3.12.0"
53 | },
54 | "devDependencies": {
55 | "@types/bluebird": "^3.5.26",
56 | "@types/chai": "^4.1.7",
57 | "@types/mocha": "^5.2.6",
58 | "@types/sinon": "^7.0.11",
59 | "bluebird": "^3.5.4",
60 | "browserify-versionify": "^1.0.6",
61 | "chai": "^4.2.0",
62 | "es6-map": "^0.1.5",
63 | "es6-symbol": "^3.1.1",
64 | "glslify": "^7.0.0",
65 | "html-webpack-plugin": "^3.2.0",
66 | "imports-loader": "^0.8.0",
67 | "istanbul": "^0.4.5",
68 | "istanbul-instrumenter-loader": "^3.0.1",
69 | "karma": "^4.0.1",
70 | "karma-chai": "^0.1.0",
71 | "karma-chai-sinon": "^0.1.5",
72 | "karma-chrome-launcher": "^2.2.0",
73 | "karma-coverage-istanbul-reporter": "^2.0.5",
74 | "karma-es6-shim": "^1.0.0",
75 | "karma-mocha": "^1.3.0",
76 | "karma-mocha-reporter": "^2.2.5",
77 | "karma-phantomjs-launcher": "^1.0.4",
78 | "karma-remap-istanbul": "^0.6.0",
79 | "karma-sinon": "^1.0.5",
80 | "karma-sourcemap-loader": "^0.3.7",
81 | "karma-sourcemap-writer": "^0.1.2",
82 | "karma-webpack": "^3.0.5",
83 | "mocha": "^5.2.0",
84 | "phaser": "^3.16.2",
85 | "prettier": "^1.16.4",
86 | "publish-please": "^5.4.3",
87 | "remap-istanbul": "^0.13.0",
88 | "rimraf": "^2.6.3",
89 | "sinon": "^7.3.1",
90 | "sinon-chai": "^3.3.0",
91 | "ts-loader": "^5.3.3",
92 | "ts-node": "^8.0.3",
93 | "tslint": "^5.15.0",
94 | "tslint-config-prettier": "^1.18.0",
95 | "typescript": "^3.4.2",
96 | "uglifyjs-webpack-plugin": "^2.1.2",
97 | "webpack": "^4.29.6",
98 | "webpack-cli": "^3.3.0",
99 | "webpack-concat-plugin": "^3.0.0",
100 | "webpack-dev-server": "^3.3.0"
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/com/koreez/plugin/NinePatchPlugin.ts:
--------------------------------------------------------------------------------
1 | import { NinePatch } from "./ninepatch/NinePatch";
2 |
3 | export class NinePatchPlugin extends Phaser.Plugins.BasePlugin {
4 | constructor(pluginManager: Phaser.Plugins.PluginManager) {
5 | super(pluginManager);
6 |
7 | pluginManager.game.cache.addCustom("ninePatch");
8 |
9 | // Register our new Game Object type
10 | pluginManager.registerGameObject("ninePatch", this.ninePatchFactory, this.ninePatchCreator);
11 | }
12 |
13 | private ninePatchFactory(
14 | x: number,
15 | y: number,
16 | width: number,
17 | height: number,
18 | key: string,
19 | frame?: string | number,
20 | patchesConfig?: any
21 | ): NinePatch {
22 | return this.scene.add.existing(new NinePatch(this.scene, x, y, width, height, key, frame, patchesConfig)) as NinePatch;
23 | }
24 |
25 | private ninePatchCreator(config: any, addToScene?: boolean): NinePatch {
26 | if (config === undefined) {
27 | config = {};
28 | }
29 |
30 | const key: any = (Phaser.Utils as any).Objects.GetAdvancedValue(config, "key", null);
31 | const frame: any = (Phaser.Utils as any).Objects.GetAdvancedValue(config, "frame", null);
32 | const width: any = (Phaser.Utils as any).Objects.GetAdvancedValue(config, "width", null);
33 | const height: any = (Phaser.Utils as any).Objects.GetAdvancedValue(config, "height", null);
34 | const patchesConfig: any = (Phaser.Utils as any).Objects.GetAdvancedValue(config, "patchesConfig", null);
35 |
36 | const ninePatch: NinePatch = new NinePatch(this.scene, 0, 0, width, height, key, frame, patchesConfig);
37 |
38 | if (addToScene !== undefined) {
39 | config.add = addToScene;
40 | }
41 |
42 | Phaser.GameObjects.BuildGameObject(this.scene, ninePatch, config);
43 |
44 | return ninePatch;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/com/koreez/plugin/ninepatch/INinePatchConfig.ts:
--------------------------------------------------------------------------------
1 | export interface INinePatchConfig {
2 | x: number;
3 | y: number;
4 | width: number;
5 | height: number;
6 | key: string;
7 | frame?: string | number;
8 | patchesConfig?: any;
9 | }
10 |
--------------------------------------------------------------------------------
/src/com/koreez/plugin/ninepatch/INinePatchCreator.ts:
--------------------------------------------------------------------------------
1 | import { NinePatch } from "./NinePatch";
2 |
3 | export interface INinePatchCreator extends Phaser.GameObjects.GameObjectCreator {
4 | ninePatch: (config: any, addToScene?: boolean) => NinePatch;
5 | }
6 |
--------------------------------------------------------------------------------
/src/com/koreez/plugin/ninepatch/INinePatchFactory.ts:
--------------------------------------------------------------------------------
1 | import { NinePatch } from "./NinePatch";
2 |
3 | export interface INinePatchFactory extends Phaser.GameObjects.GameObjectFactory {
4 | ninePatch: (
5 | x: number,
6 | y: number,
7 | width: number,
8 | height: number,
9 | key: string,
10 | frame?: string | number,
11 | patchesConfig?: any
12 | ) => NinePatch;
13 | }
14 |
--------------------------------------------------------------------------------
/src/com/koreez/plugin/ninepatch/IPatchesConfig.ts:
--------------------------------------------------------------------------------
1 | export interface IPatchesConfig {
2 | top: number;
3 | left?: number;
4 | right?: number;
5 | bottom?: number;
6 | }
7 |
8 | const normalizePatchesConfig: (config: IPatchesConfig) => IPatchesConfig = (config: IPatchesConfig) => {
9 | config.bottom = config.bottom || config.top;
10 | config.left = config.left || config.top;
11 | config.right = config.right || config.left;
12 | return config;
13 | };
14 |
15 | export { normalizePatchesConfig };
16 |
--------------------------------------------------------------------------------
/src/com/koreez/plugin/ninepatch/NinePatch.ts:
--------------------------------------------------------------------------------
1 | import { IPatchesConfig, normalizePatchesConfig } from "./IPatchesConfig";
2 |
3 | export class NinePatch extends Phaser.GameObjects.Container {
4 | private static readonly __BASE: string = "__BASE";
5 | private static readonly patches: string[] = ["[0][0]", "[1][0]", "[2][0]", "[0][1]", "[1][1]", "[2][1]", "[0][2]", "[1][2]", "[2][2]"];
6 |
7 | private originTexture: Phaser.Textures.Texture;
8 | private originFrame: Phaser.Textures.Frame;
9 | private config: IPatchesConfig;
10 | private finalXs: number[];
11 | private finalYs: number[];
12 | private internalTint: number;
13 |
14 | constructor(
15 | scene: Phaser.Scene,
16 | x: number,
17 | y: number,
18 | width: number,
19 | height: number,
20 | key: string,
21 | frame?: string | number,
22 | config?: IPatchesConfig
23 | ) {
24 | super(scene, x, y);
25 | this.config = config || this.scene.cache.custom.ninePatch.get(frame ? `${frame}` : key);
26 | normalizePatchesConfig(this.config);
27 | this.setSize(width, height);
28 | this.setTexture(key, frame);
29 | }
30 |
31 | public resize(width: number, height: number): this {
32 | width = Math.round(width);
33 | height = Math.round(height);
34 | if (!this.config) {
35 | return this;
36 | }
37 | if (this.width === width && this.height === height) {
38 | return this;
39 | }
40 | width = Math.max(width, this.config.left + this.config.right);
41 | height = Math.max(height, this.config.top + this.config.bottom);
42 | this.setSize(width, height);
43 | this.drawPatches();
44 | return this;
45 | }
46 |
47 | public setTexture(key: string, frame?: string | integer): this {
48 | this.originTexture = this.scene.textures.get(key);
49 | this.setFrame(frame);
50 | return this;
51 | }
52 |
53 | public setFrame(frame: string | integer): this {
54 | this.originFrame = (this.originTexture.frames as any)[frame] || (this.originTexture.frames as any)[NinePatch.__BASE];
55 | this.createPatches();
56 | this.drawPatches();
57 | return this;
58 | }
59 |
60 | public setSize(width: number, height: number): this {
61 | super.setSize(width, height);
62 | // These are the positions we need the eventual texture to have
63 | this.finalXs = [0, this.config.left, this.width - this.config.right, this.width];
64 | this.finalYs = [0, this.config.top, this.height - this.config.bottom, this.height];
65 | return this;
66 | }
67 |
68 | public setTint(tint: number): this {
69 | this.tint = tint;
70 | return this;
71 | }
72 |
73 | public setTintFill(tint: number): this {
74 | this.tint = tint;
75 | this.tintFill = true;
76 | return this;
77 | }
78 |
79 | public clearTint(): this {
80 | this.each((patch: Phaser.GameObjects.Image) => patch.clearTint());
81 | this.internalTint = undefined;
82 | return this;
83 | }
84 |
85 | public get tintFill(): boolean {
86 | return this.first && (this.first as Phaser.GameObjects.Image).tintFill;
87 | }
88 |
89 | public set tintFill(value: boolean) {
90 | this.each((patch: Phaser.GameObjects.Image) => (patch.tintFill = value));
91 | }
92 |
93 | public set tint(value: number) {
94 | this.each((patch: Phaser.GameObjects.Image) => patch.setTint(value));
95 | this.internalTint = value;
96 | }
97 |
98 | get isTinted(): boolean {
99 | return this.first && (this.first as Phaser.GameObjects.Image).isTinted;
100 | }
101 |
102 | private createPatches(): void {
103 | // The positions we want from the base texture
104 | const textureXs: number[] = [0, this.config.left, this.originFrame.width - this.config.right, this.originFrame.width];
105 | const textureYs: number[] = [0, this.config.top, this.originFrame.height - this.config.bottom, this.originFrame.height];
106 | let patchIndex: number = 0;
107 | for (let yi: number = 0; yi < 3; yi++) {
108 | for (let xi: number = 0; xi < 3; xi++) {
109 | this.createPatchFrame(
110 | this.getPatchNameByIndex(patchIndex),
111 | textureXs[xi], // x
112 | textureYs[yi], // y
113 | textureXs[xi + 1] - textureXs[xi], // width
114 | textureYs[yi + 1] - textureYs[yi] // height
115 | );
116 | ++patchIndex;
117 | }
118 | }
119 | }
120 |
121 | private drawPatches(): void {
122 | const tintFill = this.tintFill;
123 | this.removeAll(true);
124 | let patchIndex: number = 0;
125 | for (let yi: number = 0; yi < 3; yi++) {
126 | for (let xi: number = 0; xi < 3; xi++) {
127 | // @ts-ignore
128 | const patch: Phaser.Textures.Frame = this.originTexture.frames[this.getPatchNameByIndex(patchIndex)];
129 | const patchImg = new Phaser.GameObjects.Image(this.scene, 0, 0, patch.texture.key, patch.name);
130 | patchImg.setOrigin(0);
131 | patchImg.setPosition(this.finalXs[xi] - this.width * this.originX, this.finalYs[yi] - this.height * this.originY);
132 | patchImg.setScale(
133 | (this.finalXs[xi + 1] - this.finalXs[xi]) / patch.width,
134 | (this.finalYs[yi + 1] - this.finalYs[yi]) / patch.height
135 | );
136 | this.add(patchImg);
137 | patchImg.setTint(this.internalTint);
138 | patchImg.tintFill = tintFill;
139 | ++patchIndex;
140 | }
141 | }
142 | }
143 |
144 | private createPatchFrame(patch: string, x: number, y: number, width: number, height: number): void {
145 | if (this.originTexture.frames.hasOwnProperty(patch)) {
146 | return;
147 | }
148 | this.originTexture.add(patch, this.originFrame.sourceIndex, this.originFrame.cutX + x, this.originFrame.cutY + y, width, height);
149 | }
150 |
151 | private getPatchNameByIndex(index: number): string {
152 | return `${this.originFrame.name}|${NinePatch.patches[index]}`;
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | // ------------------------------------------------------------------------------
2 | // Copyright (c) 2018 Koreez LLC. All Rights Reserved.
3 | //
4 | // NOTICE: You are permitted to use, modify, and distribute this file
5 | // in accordance with the terms of the license agreement accompanying it.
6 | // ------------------------------------------------------------------------------
7 |
8 | /**
9 | * NinePatchPlugin
10 | */
11 | export { NinePatchPlugin } from "./com/koreez/plugin/NinePatchPlugin";
12 |
13 | export { INinePatchCreator } from "./com/koreez/plugin/ninepatch/INinePatchCreator";
14 |
15 | export { INinePatchFactory } from "./com/koreez/plugin/ninepatch/INinePatchFactory";
16 |
17 | export { INinePatchConfig } from "./com/koreez/plugin/ninepatch/INinePatchConfig";
18 |
19 | export { IPatchesConfig } from "./com/koreez/plugin/ninepatch/IPatchesConfig";
20 |
21 | export { NinePatch } from "./com/koreez/plugin/ninepatch/NinePatch";
22 |
--------------------------------------------------------------------------------
/static/assets/metalPanel_blueCorner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/static/assets/metalPanel_blueCorner.png
--------------------------------------------------------------------------------
/static/assets/player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/static/assets/player.png
--------------------------------------------------------------------------------
/static/assets/squareGreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/static/assets/squareGreen.png
--------------------------------------------------------------------------------
/static/assets/squareYellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koreezgames/phaser3-ninepatch-plugin/11cfc39edb972db092aff0652172610df98756fc/static/assets/squareYellow.png
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Phaser Boilerplate
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/static/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Your Game",
3 | "short_name": "Your Game",
4 | "start_url": "index.html",
5 | "display": "standalone",
6 | "orientation": "landscape",
7 | "icons": [
8 | {
9 | "src": "icon.png",
10 | "sizes": "512x512",
11 | "type": "image/png"
12 | },
13 | {
14 | "src": "launcher-icon-2x.png",
15 | "sizes": "96x96",
16 | "type": "image/png"
17 | },
18 | {
19 | "src": "launcher-icon-3x.png",
20 | "sizes": "144x144",
21 | "type": "image/png"
22 | },
23 | {
24 | "src": "launcher-icon-4x.png",
25 | "sizes": "192x192",
26 | "type": "image/png"
27 | }
28 | ]
29 | }
--------------------------------------------------------------------------------
/static/scripts/cache-polyfill.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2015 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | (function() {
19 | var nativeAddAll = Cache.prototype.addAll;
20 | var userAgent = navigator.userAgent.match(/(Firefox|Chrome)\/(\d+\.)/);
21 |
22 | // Has nice behavior of `var` which everyone hates
23 | if (userAgent) {
24 | var agent = userAgent[1];
25 | var version = parseInt(userAgent[2]);
26 | }
27 |
28 | if (
29 | nativeAddAll && (!userAgent ||
30 | (agent === 'Firefox' && version >= 46) ||
31 | (agent === 'Chrome' && version >= 50)
32 | )
33 | ) {
34 | return;
35 | }
36 |
37 | Cache.prototype.addAll = function addAll(requests) {
38 | var cache = this;
39 |
40 | // Since DOMExceptions are not constructable:
41 | function NetworkError(message) {
42 | this.name = 'NetworkError';
43 | this.code = 19;
44 | this.message = message;
45 | }
46 |
47 | NetworkError.prototype = Object.create(Error.prototype);
48 |
49 | return Promise.resolve().then(function() {
50 | if (arguments.length < 1) throw new TypeError();
51 |
52 | // Simulate sequence<(Request or USVString)> binding:
53 | var sequence = [];
54 |
55 | requests = requests.map(function(request) {
56 | if (request instanceof Request) {
57 | return request;
58 | }
59 | else {
60 | return String(request); // may throw TypeError
61 | }
62 | });
63 |
64 | return Promise.all(
65 | requests.map(function(request) {
66 | if (typeof request === 'string') {
67 | request = new Request(request);
68 | }
69 |
70 | var scheme = new URL(request.url).protocol;
71 |
72 | if (scheme !== 'http:' && scheme !== 'https:') {
73 | throw new NetworkError("Invalid scheme");
74 | }
75 |
76 | return fetch(request.clone());
77 | })
78 | );
79 | }).then(function(responses) {
80 | // If some of the responses has not OK-eish status,
81 | // then whole operation should reject
82 | if (responses.some(function(response) {
83 | return !response.ok;
84 | })) {
85 | throw new NetworkError('Incorrect response status');
86 | }
87 |
88 | // TODO: check that requests don't overwrite one another
89 | // (don't think this is possible to polyfill due to opaque responses)
90 | return Promise.all(
91 | responses.map(function(response, i) {
92 | return cache.put(requests[i], response);
93 | })
94 | );
95 | }).then(function() {
96 | return undefined;
97 | });
98 | };
99 |
100 | Cache.prototype.add = function add(request) {
101 | return this.addAll([request]);
102 | };
103 | }());
--------------------------------------------------------------------------------
/static/service-worker.js:
--------------------------------------------------------------------------------
1 | importScripts('scripts/cache-polyfill.js');
2 |
3 | var CACHE_VERSION = 'app-v1';
4 | var CACHE_FILES = [
5 | 'index.html'
6 | ];
7 |
8 | self.addEventListener('install', function (event) {
9 | event.waitUntil(
10 | caches.open(CACHE_VERSION)
11 | .then(function (cache) {
12 | console.log('Opened cache');
13 | return cache.addAll(CACHE_FILES);
14 | })
15 | );
16 | });
17 |
18 | self.addEventListener('activate', function (event) {
19 | event.waitUntil(
20 | caches.keys().then(function(keys){
21 | return Promise.all(keys.map(function(key, i){
22 | if(key !== CACHE_VERSION){
23 | return caches.delete(keys[i]);
24 | }
25 | }))
26 | })
27 | )
28 | });
29 |
30 | self.addEventListener('fetch', function (event) {
31 | event.respondWith(
32 | caches.match(event.request).then(function(res){
33 | if(res){
34 | return res;
35 | }
36 | requestBackend(event);
37 | })
38 | )
39 | });
40 |
41 | function requestBackend(event){
42 | var url = event.request.clone();
43 | return fetch(url).then(function(res){
44 | //if not a valid response send the error
45 | if(!res || res.status !== 200 || res.type !== 'basic'){
46 | return res;
47 | }
48 |
49 | var response = res.clone();
50 |
51 | caches.open(CACHE_VERSION).then(function(cache){
52 | cache.put(event.request, response);
53 | });
54 |
55 | return res;
56 | })
57 | }
--------------------------------------------------------------------------------
/static/styles/main.css:
--------------------------------------------------------------------------------
1 | html {
2 | width: 100%;
3 | height: 100%;
4 | margin: 0px;
5 | padding: 0px;
6 | }
7 |
8 | body {
9 | height: inherit;
10 | width: inherit;
11 | margin: 0px;
12 | display: flex;
13 | justify-content: center;
14 | align-items: center;
15 | }
16 |
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | # Plugin Testing
2 |
3 | Unit tests are written using Mocha, Chai and Sinon.
--------------------------------------------------------------------------------
/test/com/koreez/plugin/plugin.test.ts:
--------------------------------------------------------------------------------
1 | // ------------------------------------------------------------------------------
2 | // Copyright (c) 2018 Koreez LLC. All Rights Reserved.
3 | //
4 | // NOTICE: You are permitted to use, modify, and distribute this file
5 | // in accordance with the terms of the license agreement accompanying it.
6 | // ------------------------------------------------------------------------------
7 |
8 | import "../../../entry";
9 |
10 | import { expect } from "chai";
11 |
12 | import { NinePatchPlugin } from "../../../../src/com/koreez/plugin/NinePatchPlugin";
13 |
14 | describe("Ninepatch Plugin", () => {
15 | it("plugin_is_properly_installed", done => {
16 | const config = {
17 | banner: false,
18 | height: 10,
19 | plugins: {
20 | global: [{ key: "NinePatchPlugin", plugin: NinePatchPlugin, start: true }]
21 | },
22 | scene: {
23 | create
24 | },
25 | type: Phaser.AUTO,
26 | width: 10
27 | };
28 | let plugin: NinePatchPlugin;
29 | function create() {
30 | plugin = this.plugins.get("NinePatchPlugin");
31 | expect(plugin).instanceOf(NinePatchPlugin);
32 | done();
33 | }
34 | (window as any).game = new Phaser.Game(config);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/entry.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | import "bluebird/js/browser/bluebird";
4 | import "es6-map/implement";
5 | import "es6-symbol/implement";
6 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "lib",
4 | "target": "es5",
5 | "lib": ["es7", "dom"],
6 | "sourceMap": true,
7 | "inlineSources": true,
8 | "module": "commonjs",
9 | "moduleResolution": "node",
10 | "experimentalDecorators": true,
11 | "emitDecoratorMetadata": true,
12 | "removeComments": true,
13 | "strict": false,
14 | "noImplicitAny": true,
15 | "strictNullChecks": false,
16 | "noImplicitThis": false,
17 | "alwaysStrict": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": false,
20 | "noImplicitReturns": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["./src/**/*.ts"],
24 | "files": ["./types/phaser.d.ts"]
25 | }
26 |
--------------------------------------------------------------------------------
/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "lib-test"
5 | },
6 | "include": ["./src/**/*.ts", "./test/**/*.ts"],
7 | "files": ["./types/phaser.d.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint:latest", "tslint-config-prettier"],
3 | "rules": {
4 | "ban-types": [false],
5 | "class-name": true,
6 | "comment-format": [true, "check-space"],
7 | "curly": true,
8 | "forin": true,
9 | "label-position": true,
10 | "member-access": true,
11 | "member-ordering": [
12 | true,
13 | {
14 | "order": [
15 | "static-field",
16 | "instance-field",
17 | "constructor",
18 | "public-instance-method",
19 | "protected-instance-method",
20 | "private-instance-method"
21 | ]
22 | }
23 | ],
24 | "no-angle-bracket-type-assertion": false,
25 | "no-arg": true,
26 | "no-bitwise": true,
27 | "no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
28 | "no-construct": true,
29 | "no-debugger": true,
30 | "no-duplicate-variable": true,
31 | "no-empty": false,
32 | "no-eval": true,
33 | "no-inferrable-types": false,
34 | "no-shadowed-variable": true,
35 | "no-string-literal": true,
36 | "no-switch-case-fall-through": false,
37 | "no-this-assignment": false,
38 | "no-unused-expression": true,
39 | "no-use-before-declare": true,
40 | "no-var-keyword": true,
41 | "object-literal-sort-keys": true,
42 | "ordered-imports": false,
43 | "only-arrow-functions": [false],
44 | "prefer-const": false,
45 | "radix": true,
46 | "trailing-comma": [false],
47 | "triple-equals": [true, "allow-null-check"],
48 | "variable-name": false
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tslint.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "./tslint.json"
4 | ],
5 | "rules": {
6 | "no-implicit-dependencies": false,
7 | "no-reference": false,
8 | "no-submodule-imports": false
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require("webpack");
2 | const path = require("path");
3 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
4 |
5 | module.exports = env => {
6 | if (!env) env = { production: false, karma: false };
7 |
8 | let mode = env.production ? "production" : "development";
9 | let tsconfig = !env.karma ? "tsconfig.json" : "tsconfig.test.json";
10 | let output = env.production ? "dist" : "dist-test";
11 | let filename = env.production ? "ninepatch.min.js" : "ninepatch.js";
12 |
13 | return {
14 | mode: mode,
15 |
16 | entry: {
17 | main: path.join(__dirname, "src/index.ts")
18 | },
19 |
20 | output: {
21 | path: path.join(__dirname, output),
22 | filename: filename,
23 |
24 | libraryTarget: "var",
25 | library: "Phaser3Ninepatch"
26 | },
27 |
28 | devtool: env.production ? undefined : "inline-source-map",
29 |
30 | module: {
31 | rules: [
32 | {
33 | test: /\.ts$/,
34 | loader: "ts-loader?configFile=" + tsconfig
35 | },
36 | {
37 | test: env.production /* disable this loader for production builds */ ? /^$/ : /^(.(?!\.test))*\.ts$/,
38 | loader: "istanbul-instrumenter-loader",
39 | query: {
40 | embedSource: true
41 | },
42 | enforce: "post"
43 | }
44 | ]
45 | },
46 |
47 | plugins: env.production ? [] : [new webpack.SourceMapDevToolPlugin({ test: /\.ts$/i })],
48 |
49 | optimization: env.production
50 | ? {
51 | concatenateModules: true,
52 | minimize: true,
53 | minimizer: [
54 | new UglifyJsPlugin({
55 | cache: true,
56 | parallel: 4,
57 | uglifyOptions: {
58 | output: {
59 | comments: false
60 | }
61 | }
62 | })
63 | ]
64 | }
65 | : {},
66 | resolve: {
67 | extensions: [".ts", ".js", ".json"]
68 | }
69 | };
70 | };
71 |
--------------------------------------------------------------------------------
/webpack.example.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require("webpack");
2 | const path = require("path");
3 | const HtmlWebpackPlugin = require("html-webpack-plugin");
4 | const ConcatPlugin = require("webpack-concat-plugin");
5 |
6 | const concatPluginConfigGenerator = (name, files) => {
7 | return {
8 | uglify: false,
9 | sourceMap: false,
10 | name: name,
11 | fileName: "[name].js",
12 | filesToConcat: files,
13 | injectType: "none"
14 | };
15 | };
16 |
17 | module.exports = (function(options) {
18 | return {
19 | mode: "development",
20 |
21 | entry: {
22 | main: path.resolve("example/index.ts")
23 | },
24 |
25 | output: {
26 | path: __dirname + "/dist",
27 | filename: "bundle.js"
28 | },
29 |
30 | devtool: "source-map",
31 |
32 | module: {
33 | rules: [{ test: /\.ts$/, loader: "ts-loader" }]
34 | },
35 |
36 | plugins: [
37 | new HtmlWebpackPlugin({
38 | template: path.resolve("static/index.html"),
39 | inject: false
40 | }),
41 |
42 | new ConcatPlugin(concatPluginConfigGenerator("phaser", [path.resolve(__dirname, "./node_modules/phaser/dist/phaser.js")]))
43 | ],
44 |
45 | resolve: {
46 | extensions: [".ts", ".js", ".json"]
47 | }
48 | };
49 | })();
50 |
--------------------------------------------------------------------------------