Daniel Belohlavek

Phaser ES6/ES2015 Boilerplate

Recommended Posts

Hello! It's been a while since my last topic, I've been feeding my brain a little bit and here is the result:

 

I've created a tiny boilerplate available on Github. The aim of the project is to help other developers to get started a little bit faster without having to spend too much time setting up Build tasks (basically setting up the transpiler).

 

The project comes with:

  • A heavily commented gulpfile that uses Browserify and Babel to transpile your ES6 code into ES5.
  • Two build modes: development and production (neither one is too complex or opinionated).
  • Browsersync for live reload and weinre for your mobile debugging needs.
  • UglifyJS for the production build. No sitelock or heavy obfuscation code included.

You can access the repo here: https://github.com/belohlavek/phaser-es6-boilerplate

You can see the example included on codepen (no modules): http://codepen.io/belohlavek/full/aORJVL

 

Bonus information:

You can get code intellisense for ES6 with VSCode + phaser.d.ts (Typescript definition). Works like a charm on Ubuntu.

 

If you feel I missed out on something, or worst, if you think I screwed up please let me know! I'm sure there are at least a couple of dumb typos out there.

 

Are any of you already using Babel with Phaser? Any Typescript users willing to give ES2015 a try?

 

Thanks for reading :)

Share this post


Link to post
Share on other sites

Very interesting Daniel.  Running on Win7 with the latest nodejs V0.12.7, the development build works fine but the production build errors, see npm-debug.log below.  Any idea what the problem is before I start digging?

0 info it worked if it ends with ok1 verbose cli [ 'C:\\Program Files (x86)\\nodejs\\\\node.exe',1 verbose cli   'C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',1 verbose cli   'run',1 verbose cli   'production' ]2 info using npm@2.11.33 info using node@v0.12.74 verbose run-script [ 'preproduction', 'production', 'postproduction' ]5 info preproduction phaser-es6-boilerplate@1.0.06 info production phaser-es6-boilerplate@1.0.07 verbose unsafe-perm in lifecycle true8 info phaser-es6-boilerplate@1.0.0 Failed to exec production script9 verbose stack Error: phaser-es6-boilerplate@1.0.0 production: `NODE_ENV=production gulp`9 verbose stack Exit status 19 verbose stack     at EventEmitter.<anonymous> (C:\Program Files (x86)\nodejs\node_modules\npm\lib\utils\lifecycle.js:213:16)9 verbose stack     at EventEmitter.emit (events.js:110:17)9 verbose stack     at ChildProcess.<anonymous> (C:\Program Files (x86)\nodejs\node_modules\npm\lib\utils\spawn.js:24:14)9 verbose stack     at ChildProcess.emit (events.js:110:17)9 verbose stack     at maybeClose (child_process.js:1015:16)9 verbose stack     at Process.ChildProcess._handle.onexit (child_process.js:1087:5)10 verbose pkgid phaser-es6-boilerplate@1.0.011 verbose cwd C:\Users\stu\Downloads\phaser-es6-boilerplate-master\phaser-es6-boilerplate-master12 error Windows_NT 6.1.760113 error argv "C:\\Program Files (x86)\\nodejs\\\\node.exe" "C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "run" "production"14 error node v0.12.715 error npm  v2.11.316 error code ELIFECYCLE17 error phaser-es6-boilerplate@1.0.0 production: `NODE_ENV=production gulp`17 error Exit status 118 error Failed at the phaser-es6-boilerplate@1.0.0 production script 'NODE_ENV=production gulp'.18 error This is most likely a problem with the phaser-es6-boilerplate package,18 error not with npm itself.18 error Tell the author that this fails on your system:18 error     NODE_ENV=production gulp18 error You can get their info via:18 error     npm owner ls phaser-es6-boilerplate18 error There is likely additional logging output above.19 verbose exit [ 1, true ]

Share this post


Link to post
Share on other sites

Have you noticed any run-time performance problems around transpilation? Specifically, using arrow functions, generators, and promises? What about the newish Array prototype methods vs. for loops? Chrome used to not have optimized versions of those calls, not sure if anything has changed and jsperf doesn't seem to be working these days.

Share this post


Link to post
Share on other sites

About the production mode I had.  I went back and noticed some errors in the install, specifically the path was getting to long, so I re-installed somewhere else and it installed fine but still doesn't run production mode.  It was the production script "NODE_ENV=production gulp" in package.json just not compatible with windows command line.

 

Anyway, fixed and tested, pull request sent.

Share this post


Link to post
Share on other sites

@drhayes I haven't ran any perf tests myself, but please check: http://kpdecker.github.io/six-speed/

Also, keep in mind that with Babel every single transformation can be turned off (in case your environment supports ES6).

 

@stupot your solution didn't work for me, please check the comments in the PR (if you don't mind lending me a hand :)).

Share this post


Link to post
Share on other sites

Hey, i am using phaser with ES2015 modules and classes - work's like a charm. But some times you have to wait. 

My way is babel + webpack, here is configuration:

var path = require('path');var webpack = require('webpack');var glFragmentLoader = path.join(__dirname, '/node_modules/phaser-glsl-loader');module.exports = {    entry: './src/main.js',    output: {        path: __dirname,        filename: 'bundle.js'    },    module: {        loaders: [            {test: __dirname, loader: 'babel-loader'},            {test: /\.frag$/i, loader: 'gl-fragment-loader'}        ]    },    plugins: [        // Avoid publishing files when compilation failed        new webpack.NoErrorsPlugin()    ],    stats: {        // Nice colored output        colors: true    },    // Create Sourcemaps for the bundle    devtool: 'source-map',    resolveLoader: {        alias: {          'gl-fragment-loader': glFragmentLoader,        }    }};

Special thank's to glsl-loader - it's really useful.

Share this post


Link to post
Share on other sites

As long as we're sharing...

 

Here's my webpack.config.js from my current big project. Nothing special, except it turns out webpack has a special node webkit mode so it doesn't mess up the "native" requires NW lets you have:

'use strict';var webpack = require('webpack');var definitions = {  DEBUG: process.env.DEBUG === 'true',  FULL: process.env.FULL === 'true',  NATIVE: process.env.NATIVE === 'true'};var config = {  target: 'web',  plugins: [    new webpack.DefinePlugin(definitions)  ],  resolveLoader: {    modulesDirectories: ['node_modules', 'tools']  },  module: {    loaders: [{      test: /index\.html$/,      loader: 'copy'    }, {      test: /\.svg$|\.woff$|\.ttf$|\.wav$|\.mp3|\.fnt|\.ogg|\.wav$/,      loader: 'file'    }, {      test: /\.json$/,      loader: 'file!mapEntityIdGenerator'    }, {      test: /\.jpe?g$|\.gif$|\.png$/,      loader: 'file!image'    }, {      test: /phaser.js/,      loader: 'script'    }],  },  entry: {    game: './src/game.js'  },  output: {    path: './dist',    publicPath: '',    filename: 'game.js'  }};if (definitions.NATIVE) {  config.target = 'node-webkit';  // For some reason, setting the target to "node-webkit" made it lose the  // image loader. Setting the resolveLoader.moduleTemplates made it work  // again. ¯\_(ツ)_/¯  config.resolveLoader.moduleTemplates = ["*-webpack-loader", "*-web-loader", "*-loader", "*"];}module.exports = config;

I run my builds from my project's package.json as npm scripts. For my "build-native" target I set "NATIVE=true" and webpack + uglify remove dead code paths that don't use NATIVE. Pretty cool.

 

My test server is webpack's dev server, "webpack-dev-server". Works a treat! And no MAMP to set up or anything like that.

 

That "mapEntityIdGenerator" loader is something I wrote to assign deterministic IDs to objects in my tilemaps so they can save and load their states when the player checkpoints. Working well so far.

Share this post


Link to post
Share on other sites

Personally I use Webpack only with React and JSX for front-end development. The reasons why I went with Gulp + Browserify are the following:

  • Webpack takes care of everything under it's magical hood, not ideal for newcomers who are trying to wrap their heads around the build process.
  • I wasn't able to correctly configure hot module replacement, so if I was going to do Livereload, Browsersync seemed to be a little bit more robust (and comes with Weinre, lots of devs here do mobile games).
  • I needed to copy, move, and delete files/folders. While this is possible in Webpack using plugins, remember that Webpack is not intended to be a build system.

Anyways, I'm glad to see that some of you are hacking your way through Phaser development in ES6 too ^^

 

Disclaimer for other readers:

 

Webpack is by no means a weak tool. Choose whatever you are comfortable with, and if you feel like you have no idea what you are doing check out my Boilerplate where I try my best to explain each step and make it easy to change stuff.

Share this post


Link to post
Share on other sites

Interesting! Is this transpiling new ES5-files automatically (watching) on save? How long does it take for a "normal" project?

edit: Yes it does, it's quicker than I can switch to the browser and hit F5, and it's easy to debug. This is great! Thanks!

Share this post


Link to post
Share on other sites

Yeah, it's funny, but I'm a bigger fan of browserify than webpack for a bunch of different reasons (not comfortable with how it overloads require, doesn't let you write truly isomorphic code, etc)... but the on-the-fly transforms I've written for my game have been very helpful.

 

This is a great project, thanks!

 

What do you mean "Webpack is not intended to be a build system."?

Share this post


Link to post
Share on other sites

@Skeptron you are welcome! :D

 

@nkholski it's fast enough, but the build task is copying static files on each build (I think it sould only do it on the first build). Probably will fix this sometime this week to make it faster.

 

@drhayes Both Webpack and Browserify are module bundlers. Gulp (and Grunt, for example) are build systems designed to create and take control of different build tasks that are not always related to modules. Bundling be should one of several tasks found in a complex project.

 

@Nortonio Nice! You forgot to remove the RainbowText class from the source!

 

In case someone is interested: here are a couple of GIFs demonstrating how fast build tasks are executed. Please remember that this should be a little bit faster in the near future (maybe you should watch the Github repo!) 

 

Windows 7 build (i7 3.4GHz 8 CPUs, 8GB RAM): see recorded GIF.

Ubuntu 15.04 build (Virtual Machine, 4 CPUs, 2GB RAM): see recorded GIF.

 

In both recordings I run a development build + 2 updates that will reload the browser. The second one may be hard to see, recording GIFs is complicated, better test it yourself  :P

Share this post


Link to post
Share on other sites

Brief update, version 1.0.2 now features:

  • Faster builds (no need to copy static files every time).
  • Live reload now works with static files too!

That should make it a little bit easier to play with the DOM (if you need to).

 

Any suggestions or feature requests? I'll probably upload an example on how to make the most out of the boilerplate soon.

 

Repo link if you don't feel like scrolling your way up.

Share this post


Link to post
Share on other sites

I haven't tested it enough for suggestions other than it would be great to see an example that demonstrates some of the advantages of using ES6 with phaser. I would also appreciate an example with more than one state and extended sprites.

Share this post


Link to post
Share on other sites

Since I work with TypeScript which implements already many ES6 features, writing your code in ES6 would allow you to use:

- arrow functions, quite useful for callbacks.

- classes if you like this kind of programmation.

- computed properties would help you to manipulate objects.

- for..of loops will bring you syntactic sugar to iterate over collections.

- destructuring allows writing shorter and more understandable algorithms.

- typed arrays are meant to improve performance (given the fact the browser natively support ES6).

 

There are obviously many more features in ES6, but those above are the most relevant in my opinion in a Phaser game.

Share this post


Link to post
Share on other sites

@nkholski, as @yahiko said Typescript and ES6 are similar, you can check out some TS examples and "port" them to ES6 if you want a fast solution. The other alternative would be to wait a little while for me to write my own well-featured example :D

Sorry for not providing a more complex game in the repo: since it's a boilerplate people would end up deleting lots of files as they are not relevant to their projects.

 

To complement @yahiko's reply, here's a link where you can learn more about ES2015 syntax: https://babeljs.io/docs/learn-es2015/

Share this post


Link to post
Share on other sites

Very nice. I am currently using babel, gulp and browserify for my projects too.

 

I have only read your code, didn't have time to try yet. However, may I suggest using watchify to get faster incremental build while developing. Also, writing: export default class ... is sufficient enough, no need to declaring the class before exporting it :). I also use node-notifier and gulp-notify to notify me if there is any error or the build process is completed, since I am not very fond of live reloading (it's very nice for web development but messy for game development, don't you think?).

Share this post


Link to post
Share on other sites

Hey, thanks for checking out my project! Let me address your comments:

 

Watchify is a watch mode for browserify, My gulpfile actually watches several types of files that are not necessarily related to JS. I'll read more about it before deciding if it's worth including another dependency.

I'm aware that writing 'export default class' es enough, I just like the other syntax better (I guess I am being heavily opinionated on this one :P)

I try to keep things as generic as possible (though I fail to do so sometimes). Gulp-notify and node-notifier would qualify as personal-choice dependencies!

Live reloading works great for small games and quick prototyping in my experience. If many people find it annoying I will add a simpler way to disable it. 

 

For those who really want to disable Live reloading, just remove all instances of browserSync.reload

 

I'll happily read and consider suggestions filed via Github's issue tracker!

 

Again, thanks for taking your time to check my project and I hope you find it easy enough to adapt to your personal needs :D

Share this post


Link to post
Share on other sites

I'm not sure if it was something particular to my environment, but I had to change the delete in the cleanBuild task to:

del.sync(['build/*']);

As it wasn't fully deleting all the directories, and the index.html would alternately exist/not-exist on separate runs of "npm start"

 

Thanks for a nice fast build environment!

Share this post


Link to post
Share on other sites

Wow this is really awesome,  thanks for sharing.  

 

As a gulp/browserify/es6 guy myself, I have to say this is definitely up my alley.  I am looking forward to trying it out.

 

side note about module loading:

 

I actually prefer module.exports as well, but I like import over require.  Because you can have one index.js file with a ton of different "exports" and then you can just do import { foo, bar, baz} from 'lib';  instead of var foo = require('lib/foo'), bar = require('lib/bar'), baz = require('lib/baz');

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.