0 Preparation for work [ ]
1 . Introduction
2 Resource download
3 Creation of the game world
4 ( wip ) Groups
5 ( wip ) The world of physics
6 ( wip ) Management
7 ( wip ) Add targets
8 ( wip ) Finishing Touches
This series of articles will teach you the basics and the "good tone" of the Phaser gaming framework. For this course, I will try to explain to you the main ideas and possibilities of the framework, as well as show you how to correctly use it in conjunction with TypeScript and Webpack .
The main course of training is taken from the official manual , but this is not a literal translation, but an adaptation of the manual, with examples rewritten from ES5 to TypeScript and a modified project structure. I also covered some of the topics in more detail.
I think it is worth making a reservation that at the time of this writing, I am using Phaser v2.6.2 and TypeScript v2.2.1 .
The source code of all the lessons can be found in this repository . Please note that tags indicate the development stages of a project at the end of a specific article, for example:
part-0
- project status at the time of the current articlepart-1
- at the time of article # 1 Introductionand so on.
Phaser is an open source ( MIT ) cross-browser HTML5 framework for creating browser games using WebGL and Canvas . Unlike other frameworks, Phaser primarily targets mobile platforms and is optimized for them.
First of all, you will need to clone the repository with the project yourself:
git clone https://github.com/SuperPaintman/phaser-typescript-tutorial.git
And install Node.js to run the collector and other NPM scripts.
Before going directly to the framework itself, consider the structure of the future application.
As a basis for our project, I took this Phaser TypeScript template , which uses Webpack as a collector.
Let's look at its main files (note on comments):
webpack.config.js
Configuration for the Webpack collector. Depending on the environment variable, NODE_ENV
will compile a build for development, or an optimized build for production.
'use strict'; /** Requires */ const path = require('path'); const webpack = require('webpack'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin; const ImageminPlugin = require('imagemin-webpack-plugin').default; const p = require('./package.json'); /** Constants */ const IS_PRODUCTION = process.env.NODE_ENV === 'production'; const assetsPath = path.join(__dirname, 'assets/'); // const stylesPath = path.join(__dirname, 'styles/'); // css // phaser. - , phaser // -, ( ) // . const phaserRoot = path.join(__dirname, 'node_modules/phaser/build/custom/'); // phaser' const phaserPath = path.join(phaserRoot, 'phaser-split.js'); const pixiPath = path.join(phaserRoot, 'pixi.js'); const p2Path = path.join(phaserRoot, 'p2.js'); // , const outputPath = path.join(__dirname, 'dist'); // `index.html` const templatePath = path.join(__dirname, 'templates/index.ejs'); /** Helpers */ /** * , * @param {T[]} array * @param {T} searchElement * * @return {boolean} */ function includes(array, searchElement) { return !!~array.indexOf(searchElement); } /** * `expose-loader`, * window * @param {string} modulePath * @param {string} name] * * @return {Object} */ function exposeRules(modulePath, name) { return { test: (path) => modulePath === path, loader: 'expose-loader', options: name }; } /** * `null` * @param {T[]} array * * @return {T[]} */ function filterNull(array) { return array.filter((item) => item !== null); } /** * `fn`, `isIt` `true`, * `fail`. * * @param {boolean} isIt * @param {function} fn * @param {function} fail * * @return {any} */ function only(isIt, fn, fail) { if (!isIt) { return fail !== undefined ? fail() : null; } return fn(); } /** * `only`. , * `NODE_ENV` === 'production', .. . * @param {function} fn * @param {function} fail * * @return {any} */ const onlyProd = (fn, fail) => only(IS_PRODUCTION, fn, fail); /** * `only`. , * `NODE_ENV` !== 'production', .. . * @param {function} fn * @param {function} fail * * @return {any} */ const onlyDev = (fn, fail) => only(!IS_PRODUCTION, fn, fail); module.exports = { entry: { main: path.join(__dirname, 'src/index.ts') }, output: { path: outputPath, // , // filename: `js/[name]${onlyProd(() => '.[chunkhash]', () => '')}.js`, chunkFilename: `js/[name]${onlyProd(() => '.[chunkhash]', () => '')}.chunk.js`, sourceMapFilename: '[file].map', publicPath: '/' }, devtool: onlyDev(() => 'source-map', () => ''), // sourcemap' . resolve: { extensions: ['.ts', '.js'], alias: { pixi: pixiPath, // 'pixi' NPM phaser: phaserPath, // 'phaser' NPM p2: p2Path, // 'p2' NPM assets: assetsPath, // `assets/` styles: stylesPath // `styles/` } }, plugins: filterNull([ /** DefinePlugin */ // , - // , . new webpack.DefinePlugin({ IS_PRODUCTION: JSON.stringify(IS_PRODUCTION), VERSION: JSON.stringify(p.version) }), /** JavaScript */ // JS onlyProd(() => new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, comments: false })), /** Clean */ // `dist` new CleanWebpackPlugin([outputPath]), /** TypeScript */ new CheckerPlugin(), /** Images */ // svg' onlyProd(() => new ImageminPlugin({ test: /\.(jpe?g|png|gif|svg)$/ })), /** Template */ // `index.html` // `templatePath`, // new HtmlWebpackPlugin({ title: 'Phaser TypeScript boilerplate project', template: templatePath }), /** CSS */ // CSS import' `.css` (- Webpack // CSS JS ). new ExtractTextPlugin({ filename: `css/[name]${onlyProd(() => '.[chunkhash]', () => '')}.css` }), /** Chunks */ // (.. // phaser' , // . // , , // ): // * new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: (module) => /node_modules/.test(module.resource) }), // * phaser (p2, PIXI, phaser) new webpack.optimize.CommonsChunkPlugin({ name: 'phaser', minChunks: (module) => includes([p2Path, pixiPath, phaserPath], module.resource) }), // * webpack' new webpack.optimize.CommonsChunkPlugin({ name: 'commons' }) ]), devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, port: 8080, inline: true, watchOptions: { aggregateTimeout: 300, poll: true, ignored: /node_modules/ } }, module: { rules: [ /** Assets */ // asset' { test: (path) => path.indexOf(assetsPath) === 0, loader: 'file-loader', options: { name: `[path][name]${onlyProd(() => '.[sha256:hash]', () => '')}.[ext]` } }, /** CSS */ { test: /\.styl$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ 'css-loader', 'stylus-loader' ] }) }, /** JavaScript */ exposeRules(pixiPath, 'PIXI'), // `PIXI` `window` exposeRules(p2Path, 'p2'), // `p2` `window` exposeRules(phaserPath, 'Phaser'), // `Phaser` `window` { test: /\.ts$/, exclude: /node_modules/, loader: 'awesome-typescript-loader' } ] } };
assets/
In this directory we will add all the resources of our application: images, music, JSON, and so on.
styles/style.styl
It will contain CSS styles (using the Stylus preprocessor) for our page. Within this series, this will suffice:
body margin: 0px
templates/index.ejs
EJS template for the game page ( Webpack will add all scripts and styles to it):
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> </body> </html>
tsconfig.json
Config for TypeScript :
{ "compilerOptions": { "target": "es5", // "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "removeComments": false, "noImplicitAny": false, "pretty": true }, "files": [ // Phaser' , .. // , // . "./node_modules/phaser/typescript/box2d.d.ts", "./node_modules/phaser/typescript/p2.d.ts", "./node_modules/phaser/typescript/phaser.comments.d.ts", "./node_modules/phaser/typescript/pixi.comments.d.ts" ], "include": [ // - glob' "./src/**/*.ts", "./node_modules/@types/**/*.ts" ] }
src/typings.d.ts
In this file, we must declare all the global variables that we created in webpack.DefinePlugin
:
declare const IS_PRODUCTION: boolean; declare const VERSION: string;
src/index.ts
This is the main file of our application, it will input the exact one into it:
'use strict';
On this basis, we will create a platformer.
Github Repo : https://github.com/SuperPaintman/phaser-typescript-tutorial
Source: https://habr.com/ru/post/324894/
All Articles