├── .eslintignore ├── assets ├── fonts │ ├── font.png │ └── font.xml ├── sounds │ ├── button.m4a │ ├── button.mp3 │ └── button.ogg └── sprites │ └── mushroom.png ├── babel.config.js ├── .editorconfig ├── src ├── config.ts ├── prefabs │ └── mushroom.ts ├── helpers │ └── sound.ts ├── app.ts └── states │ ├── preload.ts │ ├── game.ts │ └── boot.ts ├── .gitignore ├── tsconfig.json ├── .eslintrc.json ├── index.html ├── package.json ├── webpack.dev.config.js ├── README.md └── webpack.prod.config.js /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | assets 4 | webpack.* 5 | babel.* 6 | -------------------------------------------------------------------------------- /assets/fonts/font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numbofathma/phaser-typescript-webpack/HEAD/assets/fonts/font.png -------------------------------------------------------------------------------- /assets/sounds/button.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numbofathma/phaser-typescript-webpack/HEAD/assets/sounds/button.m4a -------------------------------------------------------------------------------- /assets/sounds/button.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numbofathma/phaser-typescript-webpack/HEAD/assets/sounds/button.mp3 -------------------------------------------------------------------------------- /assets/sounds/button.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numbofathma/phaser-typescript-webpack/HEAD/assets/sounds/button.ogg -------------------------------------------------------------------------------- /assets/sprites/mushroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numbofathma/phaser-typescript-webpack/HEAD/assets/sprites/mushroom.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@babel/preset-typescript"], 3 | plugins: [ 4 | ["@babel/plugin-proposal-class-properties"], 5 | ["@babel/plugin-transform-typescript"], 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = spaces 9 | indent_size = 2 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser-ce'; 2 | 3 | export class Config { 4 | static gameWidth: number = 800; 5 | 6 | static gameHeight: number = 480; 7 | 8 | static enableDebug = false; 9 | 10 | static renderer = Phaser.CANVAS; 11 | } 12 | -------------------------------------------------------------------------------- /src/prefabs/mushroom.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser-ce'; 2 | 3 | export class Mushroom extends Phaser.Sprite { 4 | constructor(game: Phaser.Game, x: number, y: number) { 5 | super(game, x, y, 'mushroom'); 6 | 7 | this.anchor.setTo(0.5); 8 | this.game.physics.arcade.enableBody(this); 9 | this.checkWorldBounds = true; 10 | this.body.collideWorldBounds = true; 11 | } 12 | 13 | update() { 14 | this.angle += 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | .next 3 | node_modules 4 | scripts/flow/*/.flowconfig 5 | *~ 6 | *.pyc 7 | .grunt 8 | _SpecRunner.html 9 | __benchmarks__ 10 | build/ 11 | remote-repo/ 12 | coverage/ 13 | .module-cache 14 | fixtures/dom/public/react-dom.js 15 | fixtures/dom/public/react.js 16 | test/the-files-to-test.generated.js 17 | *.log* 18 | chrome-user-data 19 | *.sublime-project 20 | *.sublime-workspace 21 | .idea 22 | *.iml 23 | .vscode 24 | *.swp 25 | *.swo 26 | /dist -------------------------------------------------------------------------------- /src/helpers/sound.ts: -------------------------------------------------------------------------------- 1 | import { Howl } from 'howler'; 2 | 3 | const createHowler: any = ( 4 | src: string[], 5 | preload: boolean = false, 6 | ) => { 7 | const sound: any = new Howl({ 8 | src, 9 | preload, 10 | volume: 1, 11 | onload: () => { 12 | sound.loaded = true; 13 | }, 14 | }); 15 | 16 | return sound; 17 | }; 18 | 19 | export const Sound: any = createHowler([ 20 | 'assets/sounds/button.m4a', 21 | 'assets/sounds/button.mp3', 22 | 'assets/sounds/button.ogg', 23 | ]); 24 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser-ce'; 2 | 3 | import { Config } from './config'; 4 | 5 | import { Boot } from './states/boot'; 6 | import { Preload } from './states/preload'; 7 | import { Game } from './states/game'; 8 | 9 | class Template extends Phaser.Game { 10 | constructor() { 11 | const config = { 12 | width: Config.gameWidth, 13 | height: Config.gameHeight, 14 | renderer: Config.renderer, 15 | parent: 'content', 16 | state: null, 17 | enableDebug: Config.enableDebug, 18 | }; 19 | 20 | super(config); 21 | 22 | this.state.add('Boot', Boot, false); 23 | this.state.add('Preload', Preload, false); 24 | this.state.add('Game', Game, false); 25 | 26 | this.state.start('Boot'); 27 | } 28 | } 29 | 30 | window.onload = () => new Template(); 31 | -------------------------------------------------------------------------------- /src/states/preload.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser-ce'; 2 | import { Sound } from '../helpers/sound'; 3 | 4 | export class Preload extends Phaser.State { 5 | private ready: boolean; 6 | 7 | public preload(): void { 8 | // Load awesome fonts 9 | this.game.load.bitmapFont('font', 'assets/fonts/font.png', 'assets/fonts/font.xml'); 10 | 11 | // Load sprite 12 | this.game.load.image('mushroom', 'assets/sprites/mushroom.png'); 13 | 14 | // Initialize Howler 15 | Sound.load(); 16 | 17 | this.load.onLoadComplete.addOnce(this.onLoadComplete, this); 18 | } 19 | 20 | public update(): void { 21 | if ((this.ready === true) && (Sound.loaded === true)) { 22 | this.game.state.start('Game'); 23 | } 24 | } 25 | 26 | private onLoadComplete(): void { 27 | this.ready = true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "allowSyntheticDefaultImports": true, 5 | "declaration": false, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "strictPropertyInitialization": false, 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "noEmit": false, 13 | "esModuleInterop": true, 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "lib": [ 17 | "dom", 18 | "es2015", 19 | "es2016", 20 | "esnext" 21 | ], 22 | "module": "esnext", 23 | "moduleResolution": "node", 24 | "sourceMap": false, 25 | "target": "es5", 26 | "typeRoots": [ 27 | "node_modules/@types", 28 | "node_modules/phaser-ce/typescript/phaser.d.ts", 29 | "node_modules/phaser-ce/typescript/pixi.d.ts", 30 | "node_modules/phaser-ce/typescript/p2.d.ts" 31 | ], 32 | "outDir": "dist" 33 | }, 34 | "include": [ 35 | "src/**/*.ts" 36 | ], 37 | "exclude": [ 38 | "node_modules", 39 | "src/**/*.spec.ts", 40 | "src/**/__tests__/*.ts" 41 | ], 42 | "compileOnSave": false, 43 | "atom": { 44 | "rewriteTsconfig": false 45 | } 46 | } -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "airbnb-base" 8 | ], 9 | "globals": { 10 | "Atomics": "readonly", 11 | "SharedArrayBuffer": "readonly" 12 | }, 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "project": "./tsconfig.json", 16 | "ecmaVersion": 2023, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@typescript-eslint" 21 | ], 22 | "settings": { 23 | "import/resolver": { 24 | "node": { 25 | "extensions": [ 26 | ".ts", 27 | ".js" 28 | ] 29 | } 30 | } 31 | }, 32 | "rules": { 33 | "@typescript-eslint/explicit-function-return-type": "off", 34 | "@typescript-eslint/no-unused-vars": "error", 35 | "no-continue": "off", 36 | "no-plusplus": "off", 37 | "no-bitwise": "off", 38 | "class-methods-use-this": "warn", 39 | "import/extensions": [ 40 | "error", 41 | "ignorePackages", 42 | { 43 | "js": "never", 44 | "jsx": "never", 45 | "ts": "never", 46 | "tsx": "never" 47 | } 48 | ], 49 | "import/prefer-default-export": "off", 50 | "max-len": [ 51 | "warn", 52 | { 53 | "code": 160, 54 | "ignoreStrings": true, 55 | "ignoreTemplateLiterals": true, 56 | "ignoreComments": true 57 | } 58 | ], 59 | "no-nested-ternary": "off" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Template 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/states/game.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser-ce'; 2 | import { Sound } from '../helpers/sound'; 3 | import { Mushroom } from '../prefabs/mushroom'; 4 | 5 | export class Game extends Phaser.State { 6 | private mushroom: Mushroom; 7 | 8 | private cursors: Phaser.CursorKeys; 9 | 10 | private text: Phaser.BitmapText; 11 | 12 | private spaceKey: Phaser.Key; 13 | 14 | public create(): void { 15 | this.game.physics.startSystem(Phaser.Physics.ARCADE); 16 | 17 | this.text = this.game.add.bitmapText(this.game.world.centerX, this.game.world.centerY + 100, 'font', 'Press Arrows / Space', 15); 18 | this.text.x -= ~~(this.text.width * 0.5); 19 | 20 | this.mushroom = new Mushroom(this.state.getCurrentState().game, this.game.world.centerX, this.game.world.centerY); 21 | this.game.add.existing(this.mushroom); 22 | 23 | this.cursors = this.game.input.keyboard.createCursorKeys(); 24 | 25 | this.spaceKey = this.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR); 26 | this.spaceKey.onDown.add(() => { 27 | Sound.play(); 28 | this.mushroom.x = this.game.world.centerX; 29 | this.mushroom.y = this.game.world.centerY; 30 | }, this); 31 | } 32 | 33 | public update(): void { 34 | this.game.input.update(); 35 | 36 | if (this.cursors.down.isDown) { 37 | this.mushroom.position.y++; 38 | } 39 | if (this.cursors.up.isDown) { 40 | this.mushroom.position.y--; 41 | } 42 | if (this.cursors.left.isDown) { 43 | this.mushroom.position.x--; 44 | } 45 | if (this.cursors.right.isDown) { 46 | this.mushroom.position.x++; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser-typescript-webpack", 3 | "version": "1.1.2", 4 | "description": "A good place to get started with Phaser and TypeScript development", 5 | "scripts": { 6 | "start": "webpack serve --config webpack.dev.config.js --mode development --progress", 7 | "build": "npm run check && npm run transpile", 8 | "transpile": "rimraf ./dist && webpack --config webpack.prod.config.js --mode production --progress", 9 | "tsc": "tsc --noemit --project tsconfig.json", 10 | "lint": "eslint --ext .js,.ts src --color", 11 | "lint:fix": "eslint --fix --ext .js,.ts src --color", 12 | "check": "npm run lint && npm run tsc" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/numbofathma/phaser-typescript-webpack.git" 17 | }, 18 | "engines": { 19 | "node": ">= 7.0.0" 20 | }, 21 | "author": "Costin Mirica (https://www.costinmirica.com/)", 22 | "license": "MIT", 23 | "homepage": "https://github.com/numbofathma/phaser-typescript-webpack", 24 | "devDependencies": { 25 | "@babel/cli": "^7.23.9", 26 | "@babel/core": "^7.24.0", 27 | "@babel/plugin-proposal-class-properties": "^7.18.6", 28 | "@babel/plugin-proposal-object-rest-spread": "^7.20.7", 29 | "@babel/plugin-transform-typescript": "^7.23.6", 30 | "@babel/polyfill": "^7.12.1", 31 | "@babel/preset-env": "^7.24.0", 32 | "@babel/preset-typescript": "^7.23.3", 33 | "@types/howler": "^2.2.11", 34 | "@typescript-eslint/eslint-plugin": "^7.2.0", 35 | "@typescript-eslint/parser": "^7.2.0", 36 | "babel-loader": "^9.1.3", 37 | "copy-webpack-plugin": "^12.0.2", 38 | "eslint": "^8.57.0", 39 | "eslint-config-airbnb-base": "^15.0.0", 40 | "eslint-import-resolver-webpack": "^0.13.8", 41 | "eslint-webpack-plugin": "^4.1.0", 42 | "expose-loader": "^5.0.0", 43 | "html-webpack-plugin": "^5.6.0", 44 | "javascript-obfuscator": "^4.1.0", 45 | "rimraf": "^5.0.5", 46 | "typescript": "^5.4.2", 47 | "webpack": "^5.90.3", 48 | "webpack-cli": "^5.1.4", 49 | "webpack-dev-server": "^5.0.3", 50 | "webpack-obfuscator": "^3.5.1" 51 | }, 52 | "dependencies": { 53 | "howler": "^2.2.4", 54 | "phaser-ce": "^2.20.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const ESLintPlugin = require('eslint-webpack-plugin'); 5 | 6 | const phaserModule = path.join(__dirname, '/node_modules/phaser-ce/'); 7 | const phaser = path.join(phaserModule, 'build/custom/phaser-arcade-physics.js'); 8 | const pixi = path.join(phaserModule, 'build/custom/pixi.js'); 9 | const p2 = path.join(phaserModule, 'build/custom/p2.js'); 10 | 11 | module.exports = { 12 | devServer: { 13 | static: { 14 | directory: path.resolve(__dirname, 'assets'), 15 | publicPath: '/assets', 16 | }, 17 | hot: true, 18 | open: true, 19 | compress: true, 20 | port: 8000, 21 | }, 22 | entry: { 23 | app: [ 24 | path.resolve(pixi), 25 | path.resolve(p2), 26 | path.resolve(__dirname, 'src/app.ts'), 27 | ] 28 | }, 29 | output: { 30 | filename: '[name].bundle.js', 31 | path: path.resolve('./dist'), 32 | publicPath: '/' 33 | }, 34 | plugins: [ 35 | new ESLintPlugin({ 36 | files: ['./src/**/*.ts'] 37 | }), 38 | new HtmlWebpackPlugin({ 39 | template: './index.html', 40 | inject: 'body' 41 | }) 42 | ], 43 | module: { 44 | rules: [ 45 | { 46 | test: /\.(j|t)s$/, 47 | exclude: /(node_modules|bower_components)/, 48 | use: { 49 | loader: 'babel-loader' 50 | } 51 | }, 52 | { 53 | test: /pixi\.js/, 54 | use: { 55 | loader: 'expose-loader', 56 | options: { 57 | exposes: ['PIXI', pixi] 58 | } 59 | } 60 | }, 61 | { 62 | test: /p2\.js$/, 63 | use: { 64 | loader: 'expose-loader', 65 | options: { 66 | exposes: ['p2', p2] 67 | } 68 | } 69 | }, 70 | { 71 | test: /phaser-arcade-physics\.js/, 72 | use: { 73 | loader: 'expose-loader', 74 | options: { 75 | exposes: ['Phaser', phaser] 76 | } 77 | } 78 | }, 79 | ] 80 | }, 81 | resolve: { 82 | extensions: ['.js', '.ts'], 83 | alias: { 84 | 'phaser-ce': phaser, 85 | 'pixi': pixi, 86 | 'p2': p2, 87 | } 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /src/states/boot.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser-ce'; 2 | 3 | export class Boot extends Phaser.State { 4 | public create(): void { 5 | // set up input max pointers 6 | this.input.maxPointers = 1; 7 | this.game.stage.backgroundColor = '000000'; 8 | // set up stage disable visibility change 9 | // this.stage.disableVisibilityChange = true; 10 | // Set up the scaling method used by the ScaleManager 11 | // Valid values for scaleMode are: 12 | // * EXACT_FIT 13 | // * NO_SCALE 14 | // * SHOW_ALL 15 | // * RESIZE 16 | // See http://docs.phaser.io/Phaser.ScaleManager.html for full document 17 | this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; 18 | // If you wish to align your game in the middle of the page then you can 19 | // set this value to true. It will place a re-calculated margin-left 20 | // pixel value onto the canvas element which is updated on orientation / 21 | // resizing events. It doesn't care about any other DOM element that may 22 | // be on the page, it literally just sets the margin. 23 | this.scale.pageAlignHorizontally = true; 24 | this.scale.pageAlignVertically = true; 25 | // this.game.scale.compatibility.forceMinimumDocumentHeight = true; 26 | // this.scale.compatibility.forceMinimumDocumentHeight = true; 27 | // Force the orientation in landscape or portrait. 28 | // * Set first to true to force landscape. 29 | // * Set second to true to force portrait. 30 | // this.scale.forceOrientation(false, true); 31 | // this.game.scale.compatibility.forceMinimumDocumentHeight = true; 32 | // Sets the callback that will be called when the window resize event 33 | // occurs, or if set the parent container changes dimensions. Use this 34 | // to handle responsive game layout options. Note that the callback will 35 | // only be called if the ScaleManager.scaleMode is set to RESIZE. 36 | // this.scale.setResizeCallback(this.gameResized, this); 37 | // Set screen size automatically based on the scaleMode. This is only 38 | // needed if ScaleMode is not set to RESIZE. 39 | // this.scale.updateLayout(true); 40 | // Re-calculate scale mode and update screen size. This only applies if 41 | // ScaleMode is not set to RESIZE. 42 | this.scale.refresh(); 43 | 44 | this.game.state.start('Preload'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phaser.io CE 2.20.0, Howler.js 2.2.4, TypeScript 5.4.2 and Webpack 5.90, play nice together. 2 | #### A boilerplate project to create games with Phaser.io, Howler.js, TypeScript and Webpack. 3 | 4 | ## Features 5 | - Uses the latest Phaser CE 6 | - Uses Howler (an awesome audio library) - can be easily removed if one does not use it 7 | - TypeScript linter that checks TypeScript code for readability, maintainability, and functionality errors 8 | - Webpack 5 ready 9 | - Built-in commands to easily deploy code your code (minify, uglify, comments removal, etc) 10 | - Other awesome stuff! 11 | 12 | # Setup 13 | To use this boilerplate you’ll need to install a few things before you have a working copy of the project. 14 | 15 | ## 1. Clone this repo: 16 | 17 | Navigate into your workspace directory. 18 | 19 | Run: 20 | 21 | ```git clone https://github.com/numbofathma/phaser-typescript-webpack.git``` 22 | 23 | ## 2. Install node.js and npm: 24 | 25 | https://nodejs.org/en/ 26 | 27 | 28 | ## 3. Install dependencies: 29 | 30 | Navigate to the cloned repo’s directory. 31 | 32 | Run: 33 | 34 | ```npm install``` 35 | 36 | ## 4. Run the development server: 37 | 38 | Run: 39 | 40 | ```npm run start``` 41 | 42 | This will run a server so you can run the game in a browser. 43 | 44 | Open your browser and enter localhost:8000 into the address bar. 45 | 46 | As you change your code, Webpack will watch for changes and the browser will refresh. 47 | 48 | 49 | ## 5. Build for deployment: 50 | 51 | Run: 52 | 53 | ```npm run build``` 54 | 55 | This will optimize and minimize the compiled bundle. Your code will be minified and uglyfied for reverse engineering protection. 56 | The vendor library will only be minified because uglify will add extra MBs to your game. 57 | 58 | 59 | ## 6. Extra features 60 | I've also added a command that auto-fixes your code according to the rules in the .eslintrc.json file. 61 | 62 | Run: 63 | 64 | ``` npm run lint:fix``` 65 | 66 | ...and also a commad to check your TypeScript types. 67 | 68 | Run: 69 | 70 | ``` npm run check``` 71 | 72 | ## Credits 73 | Big thanks to this great repos: 74 | 75 | https://github.com/lean/phaser-es6-webpack/tree/typescript
76 | https://github.com/eduardonunesp/phaser-typescript-webpack-boilerplate
77 | https://github.com/heathkit/phaser-typescript-webpack-starter/tree/master/src/sprites 78 | 79 | Special thanks to: 80 | dimorphic 81 | 82 |
83 | Made with <3 in Romania 84 | -------------------------------------------------------------------------------- /webpack.prod.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | const JavaScriptObfuscator = require('webpack-obfuscator'); 6 | const TerserPlugin = require('terser-webpack-plugin'); 7 | 8 | const phaserModule = path.join(__dirname, '/node_modules/phaser-ce/'); 9 | const phaser = path.join(phaserModule, 'build/custom/phaser-arcade-physics.js'); 10 | const pixi = path.join(phaserModule, 'build/custom/pixi.js'); 11 | const p2 = path.join(phaserModule, 'build/custom/p2.js'); 12 | 13 | module.exports = { 14 | entry: { 15 | app: [ 16 | path.resolve(pixi), 17 | path.resolve(p2), 18 | path.resolve(__dirname, 'src/app.ts'), 19 | ] 20 | }, 21 | output: { 22 | filename: '[name].bundle.js', 23 | path: path.resolve('./dist'), 24 | publicPath: '/' 25 | }, 26 | mode: 'production', 27 | devtool: false, 28 | plugins: [ 29 | new CopyWebpackPlugin({ 30 | patterns: [ 31 | { from: './assets', to: './assets' }, 32 | ], 33 | options: { 34 | concurrency: 100, 35 | }, 36 | }), 37 | new JavaScriptObfuscator({ 38 | rotateUnicodeArray: true 39 | }, ['vendor.bundle.js']), 40 | new HtmlWebpackPlugin({ 41 | template: './index.html', 42 | inject: 'body', 43 | }) 44 | ], 45 | performance: { 46 | hints: false, 47 | maxEntrypointSize: 512000, 48 | maxAssetSize: 512000 49 | }, 50 | optimization: { 51 | splitChunks: { 52 | minSize: 10000, 53 | maxSize: 250000, 54 | cacheGroups: { 55 | vendor: { 56 | test: /node_modules/, 57 | chunks: 'initial', 58 | name: 'vendor', 59 | priority: 10, 60 | enforce: true 61 | } 62 | } 63 | }, 64 | minimizer: [ 65 | new TerserPlugin({ 66 | parallel: true, 67 | terserOptions: { 68 | // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions 69 | }, 70 | }), 71 | ], 72 | }, 73 | module: { 74 | rules: [ 75 | { 76 | test: /\.(j|t)s$/, 77 | exclude: /(node_modules|bower_components)/, 78 | use: { 79 | loader: 'babel-loader' 80 | } 81 | }, 82 | { 83 | test: /pixi\.js/, 84 | use: { 85 | loader: 'expose-loader', 86 | options: { 87 | exposes: ['PIXI', pixi] 88 | } 89 | } 90 | }, 91 | { 92 | test: /p2\.js$/, 93 | use: { 94 | loader: 'expose-loader', 95 | options: { 96 | exposes: ['p2', p2] 97 | } 98 | } 99 | }, 100 | { 101 | test: /phaser-arcade-physics\.js/, 102 | use: { 103 | loader: 'expose-loader', 104 | options: { 105 | exposes: ['Phaser', phaser] 106 | } 107 | } 108 | }, 109 | ] 110 | }, 111 | resolve: { 112 | extensions: ['.js', '.ts'], 113 | alias: { 114 | 'phaser-ce': phaser, 115 | 'pixi': pixi, 116 | 'p2': p2, 117 | } 118 | } 119 | }; 120 | -------------------------------------------------------------------------------- /assets/fonts/font.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | --------------------------------------------------------------------------------