WarsawJS Slides: My 10 days with Phaser.js

We talk about JavaScript. Each month in Warsaw, Poland.

Speaker

Piotr Kowalski

"My 10 days with Phaser.js"

2015-09-16

@piecioshka

Who am I?

Kierownik DziaƂu Aplikacji Webowych

Cyfrowy Polsat, Warsaw

JavaScript Ninja. Mac lover. Open source fan.
Organizer WarsawJS

"Kto chce szuka sposobu, kto nie chce szuka powodu."

Where am I?

Blog piecioshka.pl/blog
GitHub github.com/piecioshka
Twitter twitter.com/piecioshka
Soundcloud soundcloud.com/piecioshka

I made a game

7balls.game

Advantages of Phaser.js

Disadvantages of Phaser.js

"State idea"

init method

preload method

create method

update method

render method

Day I: Here we go!

31↑

Use ECMAScript 6.
webpack and Babel.js take care of compiling to ECMAScript 5 (for browser).

webpack.config.js

                module.exports = {
                    resolve: { extensions: ['.es6.js', '.js', ''] },
                    entry: './app/scripts/main',
                    output: {
                        filename: 'bundle.js',
                        path: './app/dist'
                    },
                    module: { loaders: [{
                        test: /\.es6\.js/,
                        exclude: /node_modules/,
                        loader: 'babel?stage=0'
                    }] }
                }
            

Advantages of ECMAScript 6

                // Destructuring assignment
                let [x, y] = ['abc', 100]
                // x = 'abc', y = 100
            

HTML (index.html)

No more HTML files, because everything is in the Canvas.


  1. Create container for game: <div id="game"></div>
  2. Add library file: scripts/vendors/phaser.js
  3. Add our game file: dist/bundle.js

Phaser.js v2.4.3

Type Files
Normal 2.8M phaser.js
726K phaser.min.js
Only need to 2,2M phaser-arcade-physics.js
754K phaser-arcade-physics.map
567K phaser-arcade-physics.min.js

Why not in modules?

Write first lines of code

                // Create game object
                this.game = new Phaser.Game(800, 400, Phaser.Canvas, 'game`)
            

Day II: Design (vol. 1)

157 LOC (126↑)


                // Add state to set
                this.game.state.add(name, handler)
                // Activate passed state
                this.game.state.start(name)
            

Day II: Design (vol. 2)

                // Load image file and put it to cache
                this.load.image(key, path)
                // Fetch from cache image and put to Canvas
                this.add.image(x, y, key)
            

Day II: Design (vol. 3)


                // Add button to Canvas
                this.add.button(x, y, key, handler)
            

The first big problem


Ideas?

Day III: We are moving!

258 LOC (101↑)

                this.load.tilemap(key, path, data, format)
                // data: if `path` was passed, equals null
                // format: Phaser.Tilemap.TILED_JSON
            
                this.load.spritesheet(key, path, width, height)
                // width: tile width
                // height: tile height
            

Balls positions

                // Fetch file and put response into cache
                this.load.json(key, path)
                // Return parsed object
                object = this.cache.getJSON(key)
            

Create the first sprite - character

                // Add sprite to game
                this.add.sprite(x, y, key)
            

Add dragon balls

Simple message

                // Add label
                message = this.add.text(x, y, text)
            

                message.alpha = 0
                this.add.tween(message).to(config, time, type, true)
                // config: { alpha: 1 }
                // time: Phaser.Timer.SECOND
                // type: Phaser.Easing.Linear.None
            

Navigation vol. 1

                if (keyboard.isDown(Phaser.Keyboard.LEFT) {
                    player.x -= 5
                }
            

Warning!

If we would like to use collision detection,
we should update player.velocity.x not only player.x.

Navigation vol. 2

                // Update velocity of player
                player.velocity.x -= 5
            

Remember to clear velocity before that process!

                // Reset velocity
                player.velocity.x = 0
            

Collision - a very broad subject

                // Enable arcade mode for our player
                this.physics.arcade.enable(player)
            
                map.setCollisionByIndex(1) // Start counting from 1
                layer = map.createLayer(name)
                this.physics.arcade.collide(player, layer)
            

Player will be collide with tile with index = 0 from now!

Collected items - dragon balls

                balls = this.add.group()
                balls.enableBody = true
            

                // Add body to group of balls
                this.physics.arcade.enable(balls)
                // Start collide between player and group of balls
                this.physics.arcade.collide(player, balls, handler)
            

Day IV: Time from clock

384 LOC (126↑)


                // Clock with reference to state
                this.time.events.add(time, handler, context)
            

Day V: Music!

710 LOC (326↑)

                this.load.audio(key, path)
                sound = this.add.audio(key)
                sound.play()
            

Day VI: Display bars

858 LOC (148↑)

Day VII: Player collision

1028 LOC (170↑)

                // Support mouse over
                button.events.onInputOver.add(handler, context)
            
                isOverlap() => {
                    return this.physics.arcade.overlap(player, enemy)
                }
            

Day VIII: Create Artificial Intelligence

1270 LOC (242↑)

Day IX: Easter egg

1533 LOC (263↑)

Day X: Last day

1732 LOC (199↑)

                // Upgrade collision
                map.setCollision([1, 3])
            

Future plans

The worst part of code

scripts/states/VersusState.es6.js

The best part of code

scripts/main.es6.js

What I learned?

My mistakes

                Phaser.State#rnd.integerInRange(min, max)
            
instead of:
                Utilities.random(min, max)
            

Donation

patreon.com/photonstorm

(Richard Davey @photonstorm)

Thanks!

Links

See you next month at WarsawJS

Fork me on Github

Fullscreen