I'm Jesse

I like writing Javascript

I like writing Music

I like Amanda

I help run OKCJS

I help run Thunderplains

I help run Techlahoma

Soo..

Did Ya'll Find The Secret OKC.js

Treasure ?

Why Phaser?

But really....

Isn't Jesse really into Impact.js ?

Hode up

"I mean.. he even made a level generator plugin.."

"and a node port?"

"Whoa, that was nearly 2 years ago?"

"Isn't there like a bazillion other

FANTABULOUS

Js Game frameworks?"

Yeah, its overwhelming.

 

I even did a talk about that a few years back too....

Akihabara                                                           
Irenic                                                       
Aves                                                           
bdge                                                           
CakeJS                                                           
Canvex                                                           
CasualJS                                                           
ChesterGL                                                           
ClanFX                                                           
Cocos2D                                                           
Collie                                                           
Crafty                                                           
cssgameengine                                                           
Diggy                                                           
Effect Games
Flax                                                            
FlixelJS                                                            
Float Engine                                                            
friGame             
FrozenJS
GameJs                                                            
gameQuery                                                            
GammaJS                                                            
Geom                                                            
gTile                                                            
The GMP Javascript Game Engine                                                            
Hydra                                                            
Hydrax                                                            
ingenioJS                                                            
Impact                                                            
Isogenic Engine                                                            
j5g3                                                            
The Javascript 2D Game Engine
Javascript Gamelib
Jaws
jGen
Jomoho JS
jsGameSoup
js-verge
LimeJS
MelonJS                                                            
Mibbu                                                            
PixieEngine                                                            
Play My Code                                                            
PlayCanvas                                                            
PlayN                                                            
PropulsionJS                                                            
Turbulenz                                                            
The Render Engine                                                            
Rocket Engine                                                            
Rosewood                                                            
Sarien.net interpreter                                                            
Solpeo Gaming Platform    
SpellScript                                                            
Tom's Halls                                                            
UltimateJS    
Unity3D        
vegalib                                                            
xc.js        

Not a bazillion.. but scores. Theres about 60 on the most up to date wiki I know. 

"Oh yeah?

Can't I just do this all 'game stuff' with

vanilla.js ???"

Yes.

Go nuts.

But here are a few reasons you might use Phaser anyways...

Open Source 

Built atop PIXI

Sprites, Groups, Animation worked out

Good Mobile (exportation, device scaling)

Plugin System

Particle System

Pluggable Physics Engine

Chainable Tweening

but most importantly....

THE DOCUMENTATION

DOES NOT

SUCK

THE DOCUMENTATION

DOES NOT

SUCK

There is also an alternative flavor of documentation called 

"Phaser Chains"

It is also available as a plugin in some editors

 like Brackets

And that's not all

The Basics

Fundamentally Phaser is a State System

First, one creates a

Game Object 

that essentially acts as a

State Manager

var game;

game = new Phaser.Game(700, 786, Phaser.AUTO, 'some_div_id_on_your_dom');

//width, height, renderer, and the target div!

The game object holds the various subsystems needed to load assets, state, and generally make stuff happen.

 

The list to the left are all methods and objects accessible in the created game.

 

The StateManager controls the game's state.

add -GameObjectFactory

debug - Utils.Debug

device - Device

input - Input

make - GameObjectCreator

particles - Particles

physics - Physics

renderer - PIXI

scale - ScaleManager

stage - Stage

sound - SoundManager

state - StateManager

tweens - TweenManager

world - World

game

 var someState = {
    init: function(){
        // I fire before preload.
        // Best place to handle ad hoc routing, redirection
    },
    preload: function (){
        // I fire before the state actually loads
        // Great place to load assets!
    },     
    create: function () {
        // I fire when the state is initially created, after Preload
        // Set up the scene here!
    },
    update: function () {
        // I fire 60 times a second
        // This is the bread and butter state where game logic lives
    },
    paused: function() {
        // I fire when the state gets paused ..Hooray!
    },
    render: function() {
        // I fire as fast as the screen draws, AFTER everything has drawn.
        // You can put post processing here.
    },
    shutdown: function() {
        //I fire when the state is 'shut down' - You are going to a new state.
    }
  };

//game is a reference to a created Phaser Game
game.state.add('some-state-name', someState);
game.state.start('some-state-name');

A Typical Phaser State

You've seen this before

  • MVC Routers (like angular)
  • UI Components (jqueryUI, React)

Subsystems

Lets discuss some

(but not all) 

Physics

(a good starting point to understanding the subsystems)

Physics Modes

Arcade

P2

Ninja

High speed AABB collision

Fastest

Rectangles only,

no rotation

Allows

Rotation

Full Body Physics

Springs,

polygons, etc

Allows for slopes

Good for

advanced

tile support

Arcade Physics

  var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', {
    preload: preload,
    create: create,
    update: update,
    render: render
  });

  function preload() {
    game.load.image('dude', '../assets/sprites/amanda.jpg');
    game.load.image('ball', '../assets/sprites/okcjs_icon.png');
  }

  var image;

  function create() {
    game.physics.startSystem(Phaser.Physics.ARCADE);
    cursors = game.input.keyboard.createCursorKeys();

    //  This creates a simple sprite that is using our loaded image and
    //  displays it on-screen
    //  and assign it to a variable
    ball = game.add.sprite(400, 200, 'ball');
    knocker = game.add.sprite(400, 200, 'dude');
    game.physics.enable([knocker, ball], Phaser.Physics.ARCADE);
    knocker.body.immovable = true;

    //  This gets it moving
    ball.body.velocity.setTo(200, 200);

    //  This makes the game world bounce-able
    ball.body.collideWorldBounds = true;

    //  This sets the image bounce energy for the horizontal 
    //  and vertical vectors (as an x,y point). "1" is 100% energy return
    ball.body.bounce.setTo(1, 1);
  }

  //  Move the knocker with the arrow keys
  function update() {
    //  Enable physics between the knocker and the ball
    game.physics.arcade.collide(knocker, ball);

    if (cursors.up.isDown) {
      knocker.body.velocity.y = -300;
    } else if (cursors.down.isDown) {
      knocker.body.velocity.y = 300;
    } else if (cursors.left.isDown) {
      knocker.body.velocity.x = -300;
    } else if (cursors.right.isDown) {
      knocker.body.velocity.x = 300;
    } else {
      knocker.body.velocity.setTo(0, 0);
    }
  }

  function render() {
    //debug helper
    game.debug.spriteInfo(ball, 32, 32);
  }

Ninja Physics

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update});


function preload() {

    game.load.tilemap('map', '../assets/tilemaps/maps/ninja-tilemap.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.image('ball', '../assets/sprites/billymays_head.png');
    game.load.image('sky', '../assets/skies/sky.png');
    game.load.image('kenney', '../assets/tilemaps/tiles/kenney.png');

}

var sprite1;
var cursors;
var map;
var layer;
var tiles;

function create() {

    var sky = game.add.image(0, 0, 'sky');
    sky.fixedToCamera = true;

    //  Activate the Ninja physics system
    game.physics.startSystem(Phaser.Physics.NINJA);

    map = game.add.tilemap('map');

    map.addTilesetImage('kenney');
    
    layer = map.createLayer('Tile Layer 1');

    layer.resizeWorld();

    var slopeMap = { '32': 1, '77': 1, '95': 2, '36': 3, '137': 3, '140': 2 };

    tiles = game.physics.ninja.convertTilemap(map, layer, slopeMap);

    sprite1 = game.add.sprite(50, 50, 'ball');

    game.physics.ninja.enableCircle(sprite1, sprite1.width / 2);

    //  A little more bounce
    sprite1.body.bounce = 0.5;

    game.camera.follow(sprite1);

    cursors = game.input.keyboard.createCursorKeys();

}

function update() {

    for (var i = 0; i < tiles.length; i++)
    {
        sprite1.body.circle.collideCircleVsTile(tiles[i].tile);

    }

    if (cursors.left.isDown)
    {
        sprite1.body.moveLeft(20);
    }
    else if (cursors.right.isDown)
    {
        sprite1.body.moveRight(20);
    }

    if (cursors.up.isDown)
    {
        sprite1.body.moveUp(20);
    }
    else if (cursors.down.isDown)
    {
        sprite1.body.moveUp(20);
    }

}

P2 Physics

Oh yeah and they also added BOX 2D, but you gotta buy it

Sprites

and 

Tilemaps

Use Shoebox !

And Tiled!

{ "height":75,
 "layers":[
        {
         "data":[0, 0, 0, 0, 0, 0, 0, 0, 0], //but this has like, a bazillion numbers
         "height":75,
         "name":"Tile Layer 1",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":75,
         "x":0,
         "y":0
        }],
 "nextobjectid":1,
 "orientation":"orthogonal",
 "properties":
    {

    },
 "renderorder":"right-down",
 "tileheight":16,
 "tilesets":[
        {
         "firstgid":1,
         "image":"..\/..\/phasertest\/public\/space_desert_tileset.png",
         "imageheight":64,
         "imagewidth":272,
         "margin":0,
         "name":"space_desert_tileset",
         "properties":
            {

            },
         "spacing":0,
         "tileheight":16,
         "tilewidth":16
        }],
 "tilewidth":16,
 "version":1,
 "width":75
}

Tilemap!!!

Tilemap.json  

Tileset.png

+

Tweening

and

Movement

NO 

YES 

Tweening has a pretty cool fluent interface

Phaser Tween Manager

tween = game.add.tween(sprite)
tween.to( { x: 400, y: 100 }, 2000, "Sine");
tween.to( { alpha: 0.5 }, 500);
tween.to( { x: 600, y: 300 }, 2000, "Cubic.easeInOut");
tween.to( { alpha: 1, x: 300, y: 500 }, 2000);
tween.to( { x: 400, y: 300, angle: 180 }, 2000);
tween.to( { x: 300, y: 200, angle: 320 }, 2000, "Sine.easeInOut");
tween.to( { x: 100, y: 300, angle: 0 }, 2000);
tween.loop();
tween.start();
  tweenLogo.to({
      x: screenCenterX,
      y: screenCenterY,
      angle: 360
    }, 1000)
    .to({
      angle: 2000
    }, 1000)
    .start()
    .onComplete.add(function () {
      twinkle.play();
      logoEmitter.x = screenCenterX;
      logoEmitter.y = screenCenterY;
      logoEmitter.start(true, 2500, null, 25);
      okcjsIcon.kill();
      game.time.events.add(2500, function () {
        game.state.start('win');
      })
    });
  var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', {
    preload: preload,
    create: create
  });

  function preload() {

    game.load.image('sky', '../assets/skies/sky.png');
    game.load.image('amanda', '../assets/sprites/amanda.jpg');

  }

  function create() {
    game.add.sprite(0, 0, 'sky');
    var item;
    for (var i = 0; i < 6; i++) {
      item = game.add.image(i * 150, -128, 'amanda', i);
      item.anchor.setTo(0.5, 0.5);
      // Add a simple bounce tween to each character's position.
      game.add.tween(item)
        .to({
          y: 290
        }, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, false);
      // Add another rotation tween to the same character.
      game.add.tween(item)
        .to({
          angle: 360
        }, 2400, Phaser.Easing.Cubic.In, true, 1000 + 400 * i, false);
    }
  }

Tween all the Amandas.

Thats not all

Splines 

Linear

Bezier

Catmull Rom

Particles

and

Emitters

What are particles??

no, but seriously they work well for magic...

...and Smoke and Bubbles and Sparks and Fire and Jetpacks and Popcorn and Dust and Confetti and Comets and Lightning and Lasers and Swarms of Insects Coins Going Everywhere and like a Bazillion other Cool Things

  var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', {
    preload: preload,
    create: create,
    render: render
  });

  var emitter;

  function preload() {
    game.load.image('corona', '../assets/sprites/billymays_head.png');
  }

  function create() {
    game.stage.backgroundColor = '#000000';
    emitter = game.add.emitter(game.world.centerX, 500, 200);
    emitter.makeParticles('corona');
    emitter.setRotation(0, 0);
    emitter.setAlpha(0.3, 0.8);
    emitter.setScale(0.5, 1);
    emitter.gravity = -200;

    //	false means don't explode all the sprites at once, but instead release at a rate of one particle per 100ms
    //	The 5000 value is the lifespan of each particle before it's killed
    emitter.start(false, 5000, 100);
  }

  function render() {
     game.debug.text(emitter.total, 32, 32);
  }

You can combine tweening with particles to do really cool stuff...

You can combine particles with physics

You can attach particles to sprites.

  var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', {
    preload: preload,
    create: create,
    update: update
  });
  var sprite, particle, emitter;

  function preload() {
    game.load.image('fire', '../assets/sprites/flameparticle.png');
    game.load.image('okcjs', '../assets/sprites/billymays_head.png')
  }

  function create() {
    game.physics.startSystem(Phaser.Physics.ARCADE);

    // create the sprite
    sprite = game.add.sprite(game.width / 2, game.height / 2, 'okcjs');

    // create the physics body -before- attaching an emitter to the sprite
    game.physics.arcade.enableBody(sprite);
    sprite.body.collideWorldBounds = true;
    sprite.anchor.setTo(0.5, 0.5);

    //create an emitter
    emitter = game.add.emitter(0, 0, 3000);
    emitter.makeParticles('fire');

    // Attach the emitter to the sprite
    sprite.addChild(emitter);

    //position the emitter relative to the sprite's anchor location
    emitter.y = 0;
    emitter.x = -16;

    // setup options for the emitter

    emitter.setAlpha(0.5, 0.9, 1500, Phaser.Easing.Out);
    emitter.setScale(0.5, 1, 0.5, 1, 750, Phaser.Easing.Out);
    emitter.gravity = 10;

    emitter.lifespan = 750;
    emitter.maxParticleSpeed = new Phaser.Point(-100, 50);
    emitter.minParticleSpeed = new Phaser.Point(-200, -50);
  }

  function update() {
    sprite.rotation = game.physics.arcade.angleToPointer(sprite);
    if (game.input.activePointer.isDown) {
      game.physics.arcade.accelerateToPointer(sprite);
      sprite.body.drag.setTo(0, 0);
      // emit a single particle every frame that the mouse is down
      emitter.emitParticle();
    } else {
      sprite.body.acceleration.set(0, 0);
      sprite.body.drag.setTo(25, 25);
    }
  }

Web GL

Filters/Shaders

WebGl is pretty straightforward. You take the shader, and make a filter with Phaser.Filter, then assign it to a sprite.

function create() {
    fragmentSrc = "" //This would be a big shader.
    filter = new Phaser.Filter(game, null, fragmentSrc);
    filter.setResolution(800, 600);

    sprite = game.add.sprite();
    sprite.width = 800;
    sprite.height = 600;

    sprite.filters = [ filter ];
}

function update() {
    filter.update();
}

and call the filters update method in update()

The filters are an array of strings representing the lines of the GL code, the look like this:

    var fragmentSrc = [
        "precision mediump float;",

        "uniform float     time;",
        "uniform vec2      resolution;",
        "uniform vec2      mouse;",

        "float length2(vec2 p) { return dot(p, p); }",

        "float noise(vec2 p){",
            "return fract(sin(fract(sin(p.x) * (43.13311)) + p.y) * 31.0011);",
        "}",

        "float worley(vec2 p) {",
            "float d = 1e30;",
            "for (int xo = -1; xo <= 1; ++xo) {",
                "for (int yo = -1; yo <= 1; ++yo) {",
                    "vec2 tp = floor(p) + vec2(xo, yo);",
                    "d = min(d, length2(p - tp - vec2(noise(tp))));",
                "}",
            "}",
            "return 3.0*exp(-4.0*abs(2.0*d - 1.0));",
        "}",

        "float fworley(vec2 p) {",
            "return sqrt(sqrt(sqrt(",
            "1.1 * // light",
            "worley(p*5. + .3 + time*.0525) *",
            "sqrt(worley(p * 50. + 0.3 + time * -0.15)) *",
            "sqrt(sqrt(worley(p * -10. + 9.3))))));",
        "}",

        "void main() {",
            "vec2 uv = gl_FragCoord.xy / resolution.xy;",
            "float t = fworley(uv * resolution.xy / 1500.0);",
            "t *= exp(-length2(abs(0.7*uv - 1.0)));",
            "gl_FragColor = vec4(t * vec3(0.1, 1.5*t, 1.2*t + pow(t, 0.5-t)), 1.0);",
        "}"
    ];

And here is where I show you WebGL eyecandy

This gonna be good.

Oh handy!

Oh shiny!

OOOOohhhhhhhhhhhhh sparkle.

My favorite!

Sploosh!

This is built entirely in primitives.

The early 00's called and want their screensaver back.

Where does all this magesty come from?

(So I didn't write that webGL stuff)

Things I haven't talked about

(yet)

 

  • Sound
  • Groups
  • Drawing Primitives
  • The Scale Manager
  • Plugins

Life on the bleeding edge

  • Boned Creature Animations (kinematics)
  • Dynamic gradient and sprite generation
  • Bugfixes galore

hot off the press in version 2.4

released JUST YESTERDAY

Project Organization.

No

More

Slides!

Phaser

By Jesse Harlin

Phaser

A Talk given to the Oklahoma City Javascript Usergroup March 2015

  • 4,830