MiniRun

Desarrollo de videojuegos

Phaser3

  • JavaScript
  • ES6 Support
  • Desktop & Mobile
  • Free Software (MIT)

Set up

npm install phaser

Parcel support

npm install parcel-bundler

parcel index.html

index.html

<html>
    <head>
        <title>Phaser mini run</title>
    </head>
    <body>
        <script src="src/game.js"></script>
    </body>
</html>

src/game.js

import Phaser from 'phaser'
import config from './config'

new Phaser.Game(config)

src/config.js

import Phaser from 'phaser'

export default {
    type: Phaser.auto,
    title: 'Game',
    width: 800,
    height: 600,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 1200 }
        }
    },
    scene: [
    ]
}

Start your game

npm start

Creating our first scene

Download the assets

https://github.com/photonstorm/phaser-examples

Put them on `src/assets`

Add the scene

 import Phaser from 'phaser'

+import FirstScene from './scenes/FirstScene'
+
 export default {
     type: Phaser.auto,
     title: 'Game',
     width: 800,
     height: 600,
     physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 1200 }
         }
     },
     scene: [
+        FirstScene,
     ]
 }

src/scenes/FirstScene.js

import Phaser from 'phaser'
import space from '../assets/space3.png'
import logo from '../assets/phaser.png'

export default class FirstScene extends Phaser.Scene {
    preload() {
        this.load.image('space', space);
        this.load.image('logo', logo);
    }

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

        var logo = this.physics.add.image(400, 100, 'logo');

        logo.setVelocity(100, 200);
        logo.setBounce(1, 1);
        logo.setCollideWorldBounds(true);
    }
}

Components of a Scene

Preload

Used to load all the media files (assets) that will be used:

 

  • Images
  • Audio
  • Sprites
  • Videos

 

You can add a scene to preload the most common files of your game.

Create

Places assets and configures what will be used in the scene.

Update

Is called with every `click` of the game, to update whatever is necessary of the scene.

Our first game

Flappy Bird!

Preparing the assets

Game images

https://github.com/sourabhv/FlapPyBird

Aseprite

Asset types

// Import the image and give it a js name.
import background from '../assets/background-day.png'

// Load the image into the game and give it an ID.
this.load.image('background', background)

// Add the image to the scene.
// The position coordinates are based on the center of the image.
this.add.image(144, 256, 'background');

Image

// Import the sprite and give it a js name.
import bird from '../assets/bird.png'

// Load the sprite into the game and give it an ID.
const frameSize = { frameWidth: 34, frameHeight: 24 }
this.load.spritesheet('bird', bird, frameSize)

// Add the spri to the scene.
this.bird = this.add.sprite(144, 256, 'bird')

// Animate it.
this.anims.create({
    key: 'fly',
    frames: this.anims.generateFrameNumbers('bird', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
})

this.bird.anims.play('fly', true)

Sprite

Preloading our assets

src/scenes/Preload.js

import Phaser from 'phaser'
import background from '../assets/background-day.png'
import logo from '../assets/logo.png'
import bird from '../assets/bird.png'
import pipe from '../assets/pipe-green.png'

export default class Preload extends Phaser.Scene {
    preload() {
        const bg = this.add.rectangle(144, 256, 200, 40, 0x666666)
        const bar = this.add.rectangle(
            bg.x, bg.y, bg.width, bg.height, 0xffffff
        ).setScale(0, 1)

        this.load.image('background', background)
        this.load.image('logo', logo)
        const frameSize = { frameWidth: 34, frameHeight: 24 }
        this.load.spritesheet('bird', bird, frameSize)
        this.load.image('pipe', pipe)

        this.load.on('progress', progress => bar.setScale(progress, 1))
    }
}

src/config.js

import Phaser from 'phaser'

import Preload from './scenes/Preload'

export default {
    type: Phaser.auto,
    title: 'Game',
    width: 288,
    height: 512,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 1200 }
        }
    },
    scene: [
        Preload,
    ]
}

Add our menu

src/scenes/Menu.js

import Phaser from 'phaser'

export default class Menu extends Phaser.Scene {
    constructor() {
        super({ key: 'menu' })
    }

    create() {
        this.add.image(144, 256, 'background');
        this.add.image(144, 200, 'logo');

        this.bird = this.add.sprite(144, 256, 'bird')

        this.anims.create({
            key: 'fly',
            frames: this.anims.generateFrameNumbers('bird', { start: 0, end: 3 }),
            frameRate: 10,
            repeat: -1
        })

        this.bird.anims.play('fly', true)
    }
}

Configure it

Add the transition

export default class Preload extends Phaser.Scene {

	// ...

	update() {
		this.scene.start('menu')
	}
}

Designing our level

Add physics to the bird

import Phaser from 'phaser'

export default class Level extends Phaser.Scene {
    constructor() {
        super({ key: 'level' })
    }

    create() {
        this.add.image(144, 256, 'background');

        this.bird = this.physics.add.sprite(144, 256, 'bird')

        this.anims.create({
            key: 'fly',
            frames: this.anims.generateFrameNumbers('bird', 
                { start: 0, end: 3 }),
            frameRate: 10,
            repeat: -1
        })

        this.bird.anims.play('fly', true)
    }
}

Add transition on click

import Phaser from 'phaser'

export default class Menu extends Phaser.Scene {

    // ...
    
    create() {
        // ...
        this.input.on('pointerup', () => this.scene.start('level'))
    }
}

Make the bird die

import Phaser from 'phaser'

export default class Level extends Phaser.Scene {

    // ...
    
    update() {
        const position = this.bird.body.position

        if (position.y > 512) {
            this.scene.start('menu')
        }
    }
}

Make the bird fly

import Phaser from 'phaser'

export default class Level extends Phaser.Scene {

    // ...
    
    create() {
        // ...
        this.bird.setCollideWorldBounds(true)

        this.input.on('pointerup', () => this.fly())
        this.fly()
    }
    
    fly() {
        this.bird.setVelocityY(-500)
    }
}

Let's add pipes!

export default class Level extends Phaser.Scene {
    create() {
        // ...
        const config = {velocityX: -100, gravityY: -1200}
        this.pipes = this.physics.add.group(config)
        this.createPipe()
    }
    
    // ...
    
    createPipe() {
        const topPosition = Math.random() * (160 + 120) - 120
        const bottomPosition = topPosition + 440
        const topPipe = this.add.image(288, topPosition, 'pipe')
        topPipe.setFlipY(true)

        const bottomPipe = this.add.image(288, bottomPosition, 'pipe')

        this.pipes.add(topPipe)
        this.pipes.add(bottomPipe)
    }
}

Moar pipes!

export default class Level extends Phaser.Scene {
    create() {
        // ...
-        this.createPipe()
+        this.this.time.delayedCall(3000, this.createPipe, [], this)
    }
    
    // ...
    
    createPipe() {
        // ...
        
+        this.time.delayedCall(3000, this.createPipe, [], this)
    }
}

Add collisions

export default class Level extends Phaser.Scene {
    create() {
        // ...
        const config = {velocityX: -100, gravityY: -1200, immovable: true}
        this.pipes = this.physics.add.group(config)
        this.time.delayedCall(3000, this.createPipe, [], this)

        this.physics.add.collider(this.bird, this.pipes, () => this.die())
    }
    
    die() {
    	this.scene.start('menu')
    }
    
    // ...
}

Let's add sound

Load the assets

import wingOgg from '../assets/wing.ogg'
import wingWav from '../assets/wing.wav'

export default class Preload extends Phaser.Scene {
    preload() {
        this.load.audio('wing', [wingOgg, wingWav])
    }
}

Add the sound to the scene

export default class Level extends Phaser.Scene {
    create() {
        this.wing = this.sound.add('wing')
    }
}

Add them when flying

export default class Level extends Phaser.Scene {
    fly() {
        this.bird.setVelocityY(-500)

        this.sound.stopAll()
        this.wing.play()
    }
}

Resources

Software

Sample repository

MiniRunDesarrollo de videojuegos

By david_hernandez

MiniRunDesarrollo de videojuegos

  • 1,092