Phaser JS for HTML5 game development

Phaser JS was mentioned in another thread. It’s a topic that interests me, so I’ll start a thread where people who are working with it can communicate.

I subscribe to their newsletter Phaser World, and they have some interesting links in each issue.

Here’s one link from today’s issue that might interest people: How to use Phaser with Vim (also useful for other development with Vim)

This course uses an older version[1] of Phaser, but it’s good:
RPG Game Development with Phaser

UPDATE: they have newer courses that cover Phaser 3.

Two useful resources that were mentioned:

[1] version 2.3

The first part of the Zenva tutorial shows the basics of Phaser with this game.

I saw this tutorial in a newsletter today:

Here is a quick intro to Phaser 3:

Here’s some code based on the video, if anyone wants a quicker version:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Phaser 3 Demo</title>
    </head>
    <body>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.15.1/phaser.min.js"></script>
        <script>
            class Example1 extends Phaser.Scene {
                constructor() {
                    super({ key: 'Example1' });
                }

                preload() {
                    this.load.image('DRAGON', 'assets/dragon.png');
                }

                create() {
                    this.image = this.add.image(400, 300, 'DRAGON');

                    // one way to bind a key
                    this.input.keyboard.on('keyup_D', () => {
                        this.image.x += 10;
                    });

                    // another way to bind a key (repeats)
                    this.key_A = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
                    this.input.on('pointerdown', event => {
                        this.image.x = event.x;
                        this.image.y = event.y;
                    });

                    this.input.keyboard.on('keyup_P', () => {
                        const physicsImage = this.physics.add.image(this.image.x, this.image.y, 'DRAGON');
                        physicsImage.setVelocity(Phaser.Math.RND.integerInRange(-100, 100), -300);
                    });

                    this.input.keyboard.on('keyup', e => {
                        if (e.key === '2') {
                            this.scene.start('Example2');
                        } else if (e.key === '3') {
                            this.scene.start('Example3');
                        }
                    });
                }

                update(delta) {
                    // handle the 'a' keybinding
                    if (this.key_A.isDown) {
                        this.image.x -= 3;
                    }
                }
            }

            class Example2 extends Phaser.Scene {
                constructor() {
                    super({ key: 'Example2' });
                }

                create() {
                    this.text = this.add.text(0, 0, 'Welcome to Example2', { font: '40px Impact' });

                    // this is horrible, but it's just an example
                    const tween = this.tweens.add({
                        targets: this.text,
                        x: 200,
                        y: 250,
                        duration: 2000,
                        ease: 'Elastic',
                        easeParams: [1.5, 0.5],
                        delay: 1000,
                        onComplete: (src, target) => {
                            target[0].x = 0;
                            target[0].y = 0;
                            target[0].setColor('Red');
                        }
                    });

                    this.input.keyboard.on('keyup', e => {
                        if (e.key === '1') {
                            this.scene.start('Example1');
                        }
                    });
                }
            }

            class Example3 extends Phaser.Scene {
                constructor() {
                    super({ key: 'Example3' });
                }

                preload() {
                    this.load.audio('test', ['assets/roar.mp3'])
                }

                create() {
                    this.soundFX = this.sound.add('test', { loop: false });
                    this.soundFX.play();
                    this.soundFX.rate = 0.55; // slow it down

                    // loop control
                    this.input.keyboard.on('keydown_L', () => {
                        this.soundFX.loop = !this.soundFX.loop;
                        if (this.soundFX.loop) {
                            this.soundFX.play();
                        }
                    });

                    // pause control
                    this.input.keyboard.on('keydown_P', () => {
                        if (this.soundFX.isPlaying) {
                            this.soundFX.pause();
                        } else {
                            this.soundFX.resume();
                        }
                    });
                }
            }

            const config = {
                type: Phaser.AUTH,
                width: 800,
                height: 600,
                physics: {
                    default: 'arcade',
                    arcade: {
                        gravity: { y: 200 }
                    }
                },
                scene: [Example1, Example2, Example3]
            };

            const game = new Phaser.Game(config);
        </script>
    </body>
</html>

The files below go in an assets directory next to the index.html file.

The dragon image:
dragon

I used this sound file for the dragon:

There is also a good Phaser-3 video series here:

(I’m doing holiday research for a present for a kid.)

It uses parcel.js which is a good tool if you need quick JavaScript/TypeScript bundling during development: