Phaser官网实例学习笔记

by黄复雄

说明:

  1. 这是我学习Phaser官网实例的笔记,对快速了解Phaser能做什么、API概貌也许有帮助。
  2. 阅读本文前,您需要对Phaser的场景结构有大致了解。笔记只摘录了关键语句,加了少量注释;语句不完整、不连续;为便于字面理解,有些类实例名称调整得更接近类名。
  3. 可以根据实例名称从Phaser官网搜出实例来细读,还可以在PhaserChains中查找语句中关键字的API文档和相关实例源码。
  4. 有些类别我没有看或粗粗看过,包括GAMES(9个完整游戏),DEMOSCENE(水波、星空、旋转、渐变色等演示场景), CREATE(像素画、渐变、多边形三个生成工具及使用实例),两个物理系统P2 PHYSICS和NINJA PHYSICS,几个付费插件BOX2D、PARTICLE STORM、VIRTUAL JOYSTICK;其余类别共有517个实例都看了,340个实例做了摘录。
  5. 官网是按字母排列类别的,现为初学者学习、理解方便重新排序。

BASICS:基础

01 Load An Image

载入图像到缓存

//事后通过key值einstein来使用它。如果不是在preload场景中载入文件,还需要判断载入完成才能使用
function preload() {
    game.load.image('einstein', 'assets/pics/ra_einstein.png');
}

02 Click On An Image

用图像生成sprite,并添加点击事件监听器

var image = game.add.sprite(game.world.centerX, game.world.centerY, 'einstein');  //einstein是载入图像时指定的key
image.inputEnabled = true;
image.events.onInputDown.add(listener, this);
function listener () {
    //do something
}

03 Move An Image

给sprite添加运动/速度

game.physics.enable(sprite, Phaser.Physics.ARCADE);  //赋予sprite物理性质
sprite.body.velocity.x=150;  //x轴每秒150点

04 Image Follow Input

使sprite跟随输入热点(鼠标/触点)移动

function update () {
    //  判断sprite到点的距离
    if (game.physics.arcade.distanceToPointer(sprite, game.input.activePointer) > 8)
    {
        //  使sprite向输入热点移动
        game.physics.arcade.moveToPointer(sprite, 300);
    }
    else
    {
        //  停止
        sprite.body.velocity.set(0);
    }
}
//在render场景中实时显示输入信息
function render () {
    game.debug.inputInfo(32, 32);
}

05 Load An Animation

载入JSON Hash格式的图集(可用Texture Packer或Shoebox等工具生成),生成动画

function preload() {
    game.load.atlasJSONHash('bot', 'assets/sprites/running_bot.png', 'assets/sprites/running_bot.json');
}
function create() {
    //  生成sprite
    var bot = game.add.sprite(200, 200, 'bot');
    //  生成动画run(使用图集中的所有帧)
    bot.animations.add('run');
    //  循环播放动画run
    bot.animations.play('run', 15, true);
}

06 Render Text

渲染文本

var text = "- phaser -\n with a sprinkle of \n pixi dust.";
var style = { font: "65px Arial", fill: "#ff0044", align: "center" }; //文本样式
var t = game.add.text(game.world.centerX-300, 0, text, style);  //添加文本控件

07 Tween An Image

给图像添加tween动画

var tween = game.add.tween(sprite);
//  设置参与动画的属性、时长、类型等
tween.to({ x: 800 }, 5000, 'Linear', true, 0);

SPRITES:精灵

Add An Image

通过载入的图像生成、添加image

function preload() {
    game.load.image('pic', 'assets/pics/acryl_bladerunner.png');
}
function create() {
    //与sprite相比,image没有动画和物理属性
    var image = game.add.image(100, 100, 'pic');
}

Add A Sprite

通过载入的图像生成、添加sprite

function preload() {
    game.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
function create() {
    var test = game.add.sprite(200, 200, 'mushroom');
}

Sprite From Bitmapdata

通过Bitmapdata生成sprite

var bmd = game.add.bitmapData(128,128);
bmd.ctx.beginPath();
bmd.ctx.rect(0,0,128,128);
bmd.ctx.fillStyle = '#ff0000';
bmd.ctx.fill();
var sprite = game.add.sprite(200, 200, bmd);

Spritesheet

Spritesheet图单动画的用法

game.load.spritesheet('ms', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
sprite = game.add.sprite(40, 100, 'ms');
sprite.animations.add('walk');
sprite.animations.play('walk', 50, true);

Anchor

更改锚点

sprite.anchor.x += 0.1;
sprite.anchor.y += 0.1;

Move A Sprite

移动sprite

sprite.x -= 4;
sprite.y -= 4;

Destroy

销毁精灵(以备回收)

sprite.destroy();

Sprite Tint

罩色、染色(黑色无法再罩色,单色图像可预设成白色以方便处理)

sprite.tint = Math.random() * 0xffffff;

Scale A Sprite

调整尺寸

sprite.scale.setTo(rand, rand);
//  或者如下:
//  sprite.scale.x = value;
//  sprite.scale.y = value;

Fixed Scale

设定尺寸变化范围(以免父级变化造成过度影响)

parent = game.add.sprite(100, 100, 'disk');
child = game.make.sprite(0, 0, 'ball');
parent.addChild(child);
child.setScaleMinMax(1, 2);
game.add.tween(parent.scale).to( { x: 3, y: 3 }, 2000, Phaser.Easing.Linear.None, true, 0, 1000, true);

Rotate And Scale

旋转和尺寸

game.add.tween(sprite).to( { angle: 45 }, 2000, Phaser.Easing.Linear.None, true);
game.add.tween(sprite.scale).to( { x: 2, y: 2 }, 2000, Phaser.Easing.Linear.None, true);
//sprite.angle += 1;

Add Several Sprites

加载多个sprite/spriteSheet

game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);

Child Sprites

sprite加载子级sprite

parent = game.add.sprite(100, 100, 'mushroom');
parent.addChild(game.make.sprite(-50, -50, 'mummy'));
parent.addChild(game.make.sprite(100, 0, 'mummy'));
parent.addChild(game.make.sprite(200, 200, 'mummy'));
child = parent.addChild(game.make.sprite(0, 100, 'mummy'));

Sprite Bounds

定位框

rect = new Phaser.Rectangle(100, 50, 600, 500);
sprite1.centerX = rect.centerX;
sprite2.centerX = rect.centerX;
sprite3.centerX = rect.centerX;

Out Of Bounds

离开舞台事件

sprite.checkWorldBounds = true;
sprite.events.onOutOfBounds.add(spriteOut, this); //spriteOut是事件要调用的函数

Align In Rectangle

对齐矩形内边

let rect:Rectangle = new Phaser.Rectangle(100, 50, 600, 500);
sprite1.alignIn(rect, Phaser.TOP_LEFT);
sprite2.alignIn(rect, Phaser.TOP_CENTER);
sprite3.alignIn(rect, Phaser.BOTTOM_RIGHT);

Align To Rectangle

对齐矩形(外边)

let rect:Rectangle = new Phaser.Rectangle(200, 200, 400, 300);
sprite1.alignTo(rect, Phaser.TOP_CENTER);
sprite2.alignTo(rect, Phaser.BOTTOM_RIGHT);
sprite3.alignTo(rect, Phaser.LEFT_CENTER);

Align Multiple Sprites

对齐多个sprite

var sprite1 = game.add.sprite(70, 250, 'block');
var sprite2 = game.add.sprite(0, 0, 'block').alignTo(sprite1, Phaser.RIGHT_CENTER, 16);
var sprite3 = game.add.sprite(0, 0, 'block').alignTo(sprite2, Phaser.RIGHT_CENTER, 16);
var sprite4 = game.add.sprite(0, 0, 'block').alignTo(sprite3, Phaser.RIGHT_CENTER, 16);
var sprite5 = game.add.sprite(0, 0, 'block').alignTo(sprite4, Phaser.RIGHT_CENTER, 16);
var sprite6 = game.add.sprite(0, 0, 'block').alignTo(sprite5, Phaser.RIGHT_CENTER, 16);

Align Text To Sprite

text与sprite对齐

var style = { font: "32px Courier", fill: "#00ff44" };
var sprite1 = game.add.sprite(220, 160, 'pic');
var text1 = game.add.text(0, 0, "Phaser", style);
var text2 = game.add.text(0, 0, "2.4.9", style);
var text3 = game.add.text(0, 0, "Aligning Text", style);
text1.alignTo(sprite1, Phaser.RIGHT_TOP, 16);
text2.alignTo(sprite1, Phaser.RIGHT_CENTER, 16);
text3.alignTo(sprite1, Phaser.RIGHT_BOTTOM, 16);

Align Within Sprite

与sprite内边对齐

pic.alignIn(game.world.bounds, Phaser.CENTER);
sprite1.alignIn(pic, Phaser.BOTTOM_RIGHT);
sprite2.alignIn(pic, Phaser.BOTTOM_LEFT);
sprite3.alignIn(pic, Phaser.TOP_CENTER, 0, -10);

Collide World Bounds

碰撞世界的边界

pineapple.enableBody = true;
pineapple.physicsBodyType = Phaser.Physics.ARCADE;
pineapple.body.collideWorldBounds=true;
pineapple.body.bounce.setTo(0.9, 0.9);

Dynamic Crop

矩形剪切sprite

sprite = game.add.sprite(0, 0, 'trsi');
cropRect = new Phaser.Rectangle(0, 0, 128, 128);
sprite.crop(cropRect);
//如果需要实时更新,可在update场景中添加sprite.updateCrop(); //见### Horizontal Crop

Mask

sprite/group遮罩

sprite = game.add.sprite(0, 0, 'chaos');
// 遮罩要是Graphics对象(图像遮罩可用BitmapData.alphaMask())
let mask:Graphics = game.add.graphics(0, 0);
mask.beginFill(0xffffff);
mask.drawCircle(100, 100, 100);
sprite.mask = mask;

Overlap Tween Without Physics

非物理学重叠/交错检测

function checkOverlap(spriteA, spriteB) {
    var boundsA = spriteA.getBounds();
    var boundsB = spriteB.getBounds();
    return Phaser.Rectangle.intersects(boundsA, boundsB);
}

Pivot

旋转的轴心

function create() {
    sprite.pivot.x = 100;
    sprite.pivot.y = 100;
}
function update() {
    //rotation是弧度,略快;angle是角的度数,可以是正或负,超过360度则取超出部分
    sprite.rotation += 0.05;
}

Rope

绳索效果

function preload() {
    game.load.image('snake', 'assets/sprites/snake.png');
}
function create() {
    var count = 0;
    var length = 918 / 20;
    var points = [];
    for (var i = 0; i < 20; i++)
    {
        points.push(new Phaser.Point(i * length, 0));
    }
    rope = game.add.rope(32, this.game.world.centerY, 'snake', null, points);
    rope.updateAnimation = function() {
        count += 0.1;
        for (var i = 0; i < this.points.length; i++)
        {
            this.points[i].y = Math.sin(i * 0.5 + count) * 20;
        }
    };
}

Shared Sprite Textures

分用图集材质

game.load.atlas('atlas', 'assets/pics/texturepacker_test.png', 'assets/pics/texturepacker_test.json');
chick = game.add.sprite(64, 64, 'atlas');
//  设置帧名
chick.frameName = 'budbrain_chick.png';
//  或设置帧号
//chick.frame = 0;

ARCADE PHYSICS:ARCADE物理引擎

Body Enable

关闭body属性即取消运动和碰撞检测

sprite.body.enable = false;

Gravity

重力

sprite3.body.gravity.y = 50;
sprite4.body.allowGravity = false;

Bounce

反弹

image = game.add.sprite(0, 0, 'flyer');
game.physics.enable(image, Phaser.Physics.ARCADE);
image.body.velocity.setTo(200,200);
//  与世界边界碰撞
image.body.collideWorldBounds = true;
//  反弹能量( "1"即100%)
image.body.bounce.set(1, 1);

Bounce Accelerator

反弹加速度

flyer.body.acceleration.x = 500;
flyer.body.acceleration.setTo(0,0);
flyer.body.velocity.setTo(200, 200);

Body Debug

sprite物理学Body的调式信息

game.debug.bodyInfo(sprite, 32, 32);
game.debug.body(sprite);

Circle Body

圆形物体

game.physics.arcade.enable([disk, ball1, ball2]);
//  缺省情况下圆形物体碰撞边界也是方形,现设碰撞边界为直径45的圆形体
ball1.body.setCircle(45);
ball2.body.setCircle(45);

Global Pause

物理系统全局暂停

game.physics.arcade.isPaused

Asteroids Movement

爆破彗星运动,朝向旋转角度(即正向)的加速度

game.physics.arcade.accelerationFromRotation(sprite.rotation, 200, sprite.body.acceleration);

Angle To Pointer

指向输入点的角度

sprite.rotation = game.physics.arcade.angleToPointer(sprite);

Multi Angle To Pointer

角度指向热点

sprite1.rotation = game.physics.arcade.angleToPointer(sprite1);

Angle Between

两个sprite间连线的角度

target.inputEnabled = true;
target.input.enableDrag(true);
// 在update中
arrow.rotation = game.physics.arcade.angleBetween(arrow, target);

Angular Acceleration

角加速度

sprite.body.angularAcceleration -= 200;

Angular Velocity

角速度

sprite.body.angularVelocity = -200

Accelerate To Pointer

向点加速(一次)

game.physics.startSystem(Phaser.Physics.ARCADE);
sprite = game.add.sprite(400, 300, 'arrow');
sprite.anchor.setTo(0.5, 0.5);
game.physics.enable(sprite, Phaser.Physics.ARCADE);
//  不用物理学系统管理旋转
sprite.body.allowRotation = false;
//在update中
sprite.rotation = game.physics.arcade.moveToPointer(sprite, 60, game.input.activePointer, 500);

Direct Body Movement

重叠检测

game.physics.arcade.overlap(sprite1, sprite2, overlapHandler, null, this);

Distance To Pointer

显示对象到热点的距离

//Phaser.Physics.Arcade.distanceToPointer(displayObject, pointer) : number; //pointer缺省为Input.activePointer
game.physics.arcade.distanceToPointer(displayObject)

Gravity And Drag

重力与拖拽

sprite.inputEnabled = true;
sprite.input.enableDrag();
sprite.events.onDragStart.add(startDrag, this);
sprite.events.onDragStop.add(stopDrag, this);
function startDrag() {
    //  拖拽时应禁止物理运动
    sprite.body.moves = false;
}
function stopDrag() {
    //  停止拖拽时再打开物理运动
    sprite.body.moves = true;
}

Group Vs Group

组对组

veggies = game.add.group();
veggies.enableBody = true;
veggies.physicsBodyType = Phaser.Physics.ARCADE;
for (var i = 0; i < 50; i++)
{
    var c = veggies.create(game.world.randomX, Math.random() * 500, 'veggies', game.rnd.integerInRange(0, 36));
    c.name = 'veg' + i;
    c.body.immovable = true;
}
bullets = game.add.group();
bullets.enableBody = true;
bullets.physicsBodyType = Phaser.Physics.ARCADE;
for (var i = 0; i < 20; i++)
{
    var b = bullets.create(0, 0, 'bullet');
    b.name = 'bullet' + i;
    b.exists = false;
    b.visible = false;
    b.checkWorldBounds = true;
    b.events.onOutOfBounds.add(resetBullet, this);
}
//因为不需要处理速度等问题,这里用overlap检测而不是碰撞检测
game.physics.arcade.overlap(bullets, veggies, collisionHandler, null, this);

Group Vs Self

组对自身

sprites = game.add.physicsGroup(Phaser.Physics.ARCADE);
......
sprites.setAll('body.collideWorldBounds', true);
sprites.setAll('body.bounce.x', 1);
sprites.setAll('body.bounce.y', 1);
function update() {
    //自身内部的碰撞检测
    game.physics.arcade.collide(sprites);
}

Larger Bounding Box

更大的边框(检测边界)

sprite1.body.setSize(400, 50, -100, 20);

Offset Bounding Box

调整、偏置边框

//  检测框大小100x50,偏移位置为50, 25
sprite1.body.setSize(100, 50, 50, 25);

Move Over Distance

移动一定距离

//  (时间,距离,方位)
sprite.body.moveTo(2000, 300, Phaser.ANGLE_RIGHT);
// sprite.body.stopVelocityOnCollide = false;
// sprite.body.moveTo(Phaser.ANGLE_RIGHT, 2000, 400);
// sprite.body.moveFrom(2000, 100, Phaser.ANGLE_RIGHT);
// sprite.body.moveFrom(2000, 100, 300);

Move To Pointer

向热点移动

game.physics.arcade.moveToPointer(ball, 100);
// game.physics.arcade.moveToPointer(ball, 100, game.input.activePointer, 1000);

Move Towards Object

组向点移动

balls.forEach(game.physics.arcade.moveToPointer, game.physics.arcade, false, 200);

Multiball

成组控制

balls = game.add.group();
balls.createMultiple(250, 'bullets', 0, false);
atari = game.add.sprite(300, 450, 'atari');
game.physics.arcade.gravity.y = 400;
//  对目前world中的所有对象开启物理学,true表示下层对象同样适用
game.physics.arcade.enable(game.world, true);

On Collide Event

碰撞事件

//   通常我们这样处理碰撞事件Phaser.Physics.arcade.collide(object1, object2, collideCallback, processCallback, callbackContext) : boolean;不过也可以使用信号:
face1.body.onCollide = new Phaser.Signal();
face1.body.onCollide.add(hitSprite, this);
//  仍需要在update中调用 `collide`,并仍能调用其他函数。
function update () {
    game.physics.arcade.collide(face1, face2);
}

One Way Collision

单向碰撞检测(取消某个方向的检测)

sprite.body.checkCollision.up = false;
sprite.body.checkCollision.down = false;

Process Callback

处理调用

game.physics.arcade.collide(sprite1, sprite2, collisionCallback, processCallback, this);
function processCallback (obj1, obj2) {
//  此函数额外检测对象属性,以决定是否执行调用(通过返回true或false)
if (obj1.body.speed > obj2.body.speed){ return true;}
else{return false;}}

Quadtree Collision Infos

四叉树碰撞信息

game.physics.startSystem(Phaser.Physics.ARCADE);
game.physics.arcade.skipQuadTree = false;
//在render中
game.debug.quadTree(game.physics.arcade.quadTree);

Sort Direction

分类指标(没明白)

game.physics.arcade.sortDirection = Phaser.Physics.Arcade.RIGHT_LEFT;

Sprite Vs Group

精灵Sprite和物理组physicsGroup

group = game.add.physicsGroup();
for (var i = 0; i < 50; i++)
{
    var c = group.create(game.rnd.between(100, 770), game.rnd.between(0, 570), 'veggies', game.rnd.between(0, 35));
    c.body.mass = -100;
}

World Bounds Event

与游戏世界碰撞的事件

face.body.collideWorldBounds = true;
//  缺省情况下这个信号是空的
face.body.onWorldBounds = new Phaser.Signal();
//  然后监听事件
face.body.onWorldBounds.add(hitWorldBounds, this);

INPUT:输入

Bounds Rect

限制框

bounds = new Phaser.Rectangle(100, 100, 500, 400);
sprite.inputEnabled = true;
sprite.input.enableDrag();
sprite.input.boundsRect = bounds;

Bounds Sprite

限制在精灵范围内

bounds = game.add.sprite(game.world.centerX, game.world.centerY, 'pic');
sprite.input.enableDrag();
sprite.input.boundsSprite = bounds;

Bring A Child To Top

拖拽时带到顶层

var images = game.cache.getKeys(Phaser.Cache.IMAGE);
var img = game.rnd.pick(images);
var tempSprite = game.add.sprite(game.world.randomX, game.world.randomY, img);
tempSprite.inputEnabled = true;
//Phaser.Sprite.input.enableDrag(lockCenter, bringToTop, pixelPerfect, alphaThreshold, boundsRect, boundsSprite) : void;
tempSprite.input.enableDrag(false, true);

Button Destroy

销毁按钮

//许多对象有pendingDestroy方法,指令下一次update时销毁,适用于从对象的调用函数内部销毁对象自身,比如有关按钮或其他输入事件方面
button.pendingDestroy = true;

Cursor Key Movement

用方向键控制运动

cursors = game.input.keyboard.createCursorKeys();
if (cursors.up.isDown)
{
    if (cursors.up.shiftKey)
    {
        game.world.rotation += 0.05;
    }
}

Custom Candidate Handler

(不明白)

game.input.setInteractiveCandidateHandler(handler, this);

Down Duration

按键时长

game.input.onUp.add(getTime, this);
function getTime(pointer) {
// lastDuration = pointer.timeUp - pointer.timeDown;
lastDuration = pointer.duration;
}

Drag

拖拽

sprite.inputEnabled = true;
//  Phaser.Sprite.input.enableDrag(lockCenter, bringToTop, pixelPerfect, alphaThreshold, boundsRect, boundsSprite) : void;
// 参数'true'是对象中心对齐输入点/鼠标
sprite.input.enableDrag(true);

Drag Event Parameters

拖拽事件参数

game.add.sprite(0, 0, 'grid');
var group = game.add.group();
group.inputEnableChildren = true;
var atari = group.create(32, 100, 'atari');
atari.inputEnabled = true;
atari.input.enableDrag();
atari.events.onDragStart.add(onDragStart, this);
atari.events.onDragStop.add(onDragStop, this);
var sonic = group.create(300, 200, 'sonic');
sonic.inputEnabled = true;
sonic.input.enableDrag();
sonic.events.onDragStart.add(onDragStart, this);
sonic.events.onDragStop.add(onDragStop, this);
group.onChildInputDown.add(onDown, this);

Drag Update

拖拽更新事件

//与拖拽同时更新
sprite.events.onDragUpdate.add(dragUpdate);

Drop Limitation

放下时限定对齐

//Phaser.Sprite.input.enableSnap(snapX, snapY, onDrag, onRelease, snapOffsetX, snapOffsetY) : void;
// 开启对齐,当释放时
item.input.enableSnap(90, 90, false, true);
// 进一步处理
item.events.onDragStop.add(fixLocation);

Gamepad

游戏手柄支持,手柄相关实例还有:

GAMEPAD ANALOG BUTTON GAMEPAD BUTTONS GAMEPAD DEBUG GAMEPAD HOTKEYS GAMEPAD MULTIPLE PADS

game.input.gamepad.start();
// 支持四个手柄,即padX的X在1-4之间
pad1 = game.input.gamepad.pad1;
if (pad1.isDown(Phaser.Gamepad.XBOX360_DPAD_LEFT) || pad1.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_X) < -0.1)
{
    sprite.x--;
}

Group Input Events

组(成员)输入事件

group.inputEnableChildren = true;
group.onChildInputDown.add(onDown, this);
group.onChildInputOver.add(onOver, this);
group.onChildInputOut.add(onOut, this);
function onDown (sprite) {
    text = "onDown: " + sprite.name;
    sprite.tint = 0x00ff00;
}

Ignore Child Input

忽略成员的输入

group.inputEnableChildren = true;
group.ignoreChildInput = (group.ignoreChildInput) ? false : true;

Input Child Priority

成员的输入优先序号

var closeButton = game.make.sprite(pw, -ph, 'close');
closeButton.inputEnabled = true;
closeButton.input.priorityID = 1;
closeButton.events.onInputDown.add(closeWindow, this);
//  "closeButton"加入弹窗中
popup.addChild(closeButton);

Input Order

输入/渲染序号

//未加人工干预时,后加入的后渲染(renderOrderID大),在上层,先收到输入(priorityID大)
sprite.renderOrderID;
//调整输入序号,见### Input Priority
sprite.input.priorityID = 2;

Key

键盘按键

upKey = game.input.keyboard.addKey(Phaser.Keyboard.UP);
downKey = game.input.keyboard.addKey(Phaser.Keyboard.DOWN);
leftKey = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
rightKey = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
if (upKey.isDown)
//等效于:
//if (game.input.keyboard.isDown(Phaser.Keyboard.UP))
{
    sprite.y--;
}

Keyboard Hotkeys

键盘热键

key1 = game.input.keyboard.addKey(Phaser.Keyboard.ONE);
// 三种热键暂停方法:(1)移除按键捕获
game.input.keyboard.removeKeyCapture(Phaser.Keyboard.ONE);
//(2)如游戏在内联框架iframe或另开窗口,应通过是否获得焦点来处理,如下:
// game.onBlur.add(...);
// game.onFocus.add(...);
//(3)根据热点判断是否开关输入
function update() {
    if (game.input.activePointer.withinGame)
    {
        game.input.enabled = true;
    }
    else
    {
        game.input.enabled = false;
    }
}

Keyboard Justpressed

按键按钮多久了

//  捕获按键,以阻止其向浏览器传播
game.input.keyboard.addKeyCapture([ Phaser.Keyboard.LEFT, Phaser.Keyboard.RIGHT, Phaser.Keyboard.SPACEBAR ]);
if (this.leftKey.isDown)    {    }
//  downDuration==true表明上次按下按键持续到如今少于250毫秒
if (this.leftKey.downDuration(250)) {   }

Motion Lock Horizontal

锁定为横向拖拽(禁用纵向拖拽)

sprite.input.allowVerticalDrag = false;
//  禁用横向拖拽,见### Motion Lock Vertical
sprite.input.allowHorizontalDrag = false;

Mouse Buttons

鼠标按键

game.input.mouse.capture = true;
function render() {
    game.debug.text("Left Button: " + game.input.activePointer.leftButton.isDown, 300, 132);
    game.debug.text("Middle Button: " + game.input.activePointer.middleButton.isDown, 300, 196);
    game.debug.text("Right Button: " + game.input.activePointer.rightButton.isDown, 300, 260);
}

Multi Touch

多点触控

//缺省为两点,增加第三点:
game.input.addPointer();
function render() {
    game.debug.pointer(game.input.mousePointer);
    game.debug.pointer(game.input.pointer1);
    game.debug.pointer(game.input.pointer2);
    game.debug.pointer(game.input.pointer3);
}

On Tap

点击事件

game.input.onTap.add(onTap, this);
function onTap(pointer, doubleTap) {
    if (doubleTap)    {    }
}

Out Of Game

判断鼠标/触控热点是否立刻游戏窗口

if (game.input.activePointer.withinGame){  }

Override Default Controls

覆盖缺省控制

// 捕获按键事件,以阻止其向浏览器冒泡/继续传播
game.input.keyboard.addKeyCapture([
Phaser.Keyboard.LEFT,
Phaser.Keyboard.RIGHT,
Phaser.Keyboard.UP,
Phaser.Keyboard.DOWN,
Phaser.Keyboard.SPACEBAR
]);

Pixel Perfect Click Detection

为悬浮事件精细检测像素(排除透明部分)

bunny.inputEnabled = true;
//  每次鼠标移动都进行检测,相当耗费资源!(可以只在点击时检测pixelPerfectClick=true)
bunny.input.pixelPerfectOver = true;
bunny.input.useHandCursor = true;

Pixelpick Atlas

为点击事件精细检测像素(排除透明部分)

chick.inputEnabled = true;
chick.input.pixelPerfectClick = true;
chick.events.onInputDown.add(clicked, this);

Pointer Lock

鼠标请求点锁定(不明白)

game.input.mouse.requestPointerLock();
if (game.input.mouse.locked && !click)    {        }

Pointer Over

输入点悬浮检测

// bunny.input.pixelPerfectOver = true;
if (bunny.input.pointerOver())    {    }

Snap On Drag

拖拽时、后对齐

//  Input Enable the sprites
atari1.inputEnabled = true;
atari2.inputEnabled = true;
//  enableDrag parameters = (lockCenter, bringToTop, pixelPerfect, alphaThreshold, boundsRect, boundsSprite)
atari1.input.enableDrag();
atari2.input.enableDrag();
//  拖拽时、后对齐,网格为32x32像素
atari1.input.enableSnap(32, 32, true, true);
//  只在释放时对齐
atari2.input.enableSnap(32, 32, false, true);

Virtual Gamecontroller

虚拟游戏控制器(略)

Word Input

字词输入

game.input.keyboard.addCallbacks(this, null, null, keyPress);
function keyPress(char) {
    if (char === letter)    {    }
}

GROUPS:组

Create Group

创建组

yourGroup = game.add.group();

Add A Sprite To Group

把sprite加入组的两种方法

group1.create(360 + Math.random() * 200, 120 + Math.random() * 200, 'baddie');
var ufo = game.add.sprite(200, 240, 'ufo');
group2.add(ufo);

Remove ### RemoveBetween

移除

group.remove(item);
group.removeBetween(10, 19);
//group.total; 组成员数

Replace

替换

item1.parent.replace(item1, item2);

Align Frames To Grid

图集的帧对齐网格

game.add.sprite(0, 0, game.create.grid('grid', 160 * 5, 160 * 3, 160, 160, 'rgba(0, 250, 0, 1)'));
var group = game.add.group();
group.createMultiple(5, 'seacreatures', ['blueJellyfish0000', 'crab10000', 'flyingFish0000'], true);
group.align(5, 3, 160, 160, Phaser.CENTER);
// group.align(5, 3, 160, 160, Phaser.TOP_RIGHT);
// group.align(5, 3, 160, 160, Phaser.BOTTOM_LEFT);

Align Sprites To Grid

精灵对齐网格

//  每帧生成24个精灵
group.createMultiple(24, 'spritesheet', [0, 1, 2, 3, 4], true);
// sprites.createMultiple(20, ['diamonds', 'balls'], [0, 1, 2], true);
//  12列,每格48x48像素
group.align(12, -1, 48, 48);

Bring A Group To Top

移到顶层

game.world.bringToTop(group2);

Call All

对组中所有成员调用函数

game.world.callAll('revive');

Call All Animations

全部调用动画

//  对组中所有成员调用函数,相当于遍历
group.callAll('animations.add', 'animations', 'spin', [0, 1, 2, 3, 4, 5], 10, true);
group.callAll('animations.play', 'animations', 'spin');

Call All Input

全部调用输入

group.setAll('inputEnabled', true);
group.callAll('events.onInputDown.add', 'events.onInputDown', removeCoin);
function removeCoin(item) {
    item.alpha = 0.3;
}

Create If Null

组中元素生死判断

group.getFirstDead(true, x, y, key, frame);
group.countLiving();
group.countDead();

Depth Sort

层次排序

group.sort('y', Phaser.Group.SORT_ASCENDING);

Display Order

复活时保持显示层次不变

card.kill();
//  使组中元素复活,并在原来的位置显示
var deadCard = group.getFirstDead();
deadCard.revive();

Filter By Property

根据属性筛选

// 取得组中"key"值为"card"的第一个元素
var card = items.iterate('key', 'card', Phaser.Group.RETURN_CHILD);
// 更换材质
card.loadTexture('hotdog');

For Each

对所有成员逐个应用函数

game.world.forEach(function);

Get First

取得第一个活的成员

var item = game.world.getFirstAlive();
//  取得第一个死的成员,见### Get First Dead
var item = veg.getFirstDead();

Group Transform Rotate

组变形、旋转等(与sprite近似)

group.x = 300;
group.y = 200;
group.pivot.x = 300;
group.pivot.y = 300;
group.rotation += 0.02;
group.setAll('inputEnabled', true);
group.callAll('input.enableDrag', 'input');
group.scale.set(2, 2);

Set All

全部设置

game.world.setAll('alpha', Math.random());

Move To Another Group

把group1成员都移到group2

group1.moveAll(group2);

Nested Groups

组嵌套

group1.add(group2);

Recycling

成员的消灭和复活

function killBaddie() {
    var baddie = enemies.getFirstAlive();
    if (baddie)
    {
        baddie.kill();
    }
}
function createBaddie() {
    // Phaser.Group.getFirstExists(exists, createIfNull, x, y, key, frame),"exists"指示查找的是活的还是死的成员,缺省为true
    var enemy = enemies.getFirstExists(false);
    if (enemy)
    {
        enemy.revive();
    }
}

Sort

排序

let locs = [];
locs = Phaser.ArrayUtils.shuffle(locs);
group.sort('y', Phaser.Group.SORT_ASCENDING);

Swap Children In A Group

交换组成员的索引/层次

//世界 (World)类是扩展组类而来的
game.world.swap(atari1, atari2);

BUTTONS:按钮

按钮

button = game.add.button(game.world.centerX - 95, 400, 'button', actionOnClick, this, 2, 1, 0);
//button.onInputOver.add(over, this);
//button.onInputOut.add(out, this);
button.onInputUp.add(up, this);
function up() {
    console.log('button up', arguments);
}

Button In A Group

按钮分组

group = game.add.group();
var button = game.make.button(game.world.centerX - 95, 400, 'button', removeGroup, this, 2, 1, 0);
button.onInputOver.add(over, this);
button.onInputOut.add(out, this);
// game.input.onDown.addOnce(removeGroup, this);
group.add(button);

Button Using Texture Atlas

使用材质图集的按钮

game.load.atlas('button', 'assets/buttons/button_texture_atlas.png', 'assets/buttons/button_texture_atlas.json');
button = game.add.button(game.world.centerX - 95, 400, 'button', actionOnClick, this, 'over', 'out', 'down');
button = game.add.button(game.world.centerX - 95, 400, 'button', onUp, this, 2, 1, 0);

Cancel Button

取消按钮(传送按钮属性)

function onUp(button, pointer, isOver) {
    if (isOver)
    {
        background.visible =! background.visible;
    }
}

Changing The Frames

改换按钮帧

game.load.spritesheet('button', 'assets/buttons/number-buttons-90x90.png', 90,90);
button = game.add.button(game.world.centerX, game.world.centerY, 'button', actionOnClick, this, 1, 0, 2);
//(overFrame, outFrame, downFrame, upFrame)
button.setFrames(4, 3, 5);

Disable Button On Click

停止按钮功能

button.inputEnabled = false;

TWEENS:补间动画

Alpha Text

文本透明度动画

game.add.tween(text).to( { alpha: 1 }, 2000, "Linear", true);

Chained Tweens

链接动画

//前一个动画结束时触发后一个动画(一次可链接多个)
tweenA.chain(tweenB);

Combined Tweens

联合动画

pigArrives = game.add.tween(pig);
pigArrives.to({x:150}, 1000, Phaser.Easing.Bounce.Out);
//通过结束事件生成、调用新的动画
pigArrives.onComplete.add(firstTween, this);

Earthquake

通过函数递归调用自身,实现动画重复播放

addQuake();
function addQuake() {
    var quake = game.add.tween(game.camera).to({x: game.camera.x - rumbleOffset}, 100, Phaser.Easing.Bounce.InOut, false, 1000, 4, true);
    // 结束事件触发函数自身,从而无限播放
    quake.onComplete.addOnce(addQuake);
    quake.start();
}

Easing

缓冲

tween = game.add.tween(item).to( { y: 245 }, 2400, Phaser.Easing.Bounce.Out, true);

Fading In A Sprite

淡入淡出

//透明度动画
sprite.alpha = 0;
game.add.tween(sprite).to( { alpha: 1 }, 2000, Phaser.Easing.Linear.None, true, 0, 1000, true);

Generate Data

预先生成动画数据(供众多对象使用)

var tweenData = { x: 0, y: 0 };
//  使数据动起来(因为不用显示,所以用make而不是add)
tween = game.make.tween(tweenData).to( { x: 100, y: 400 }, 2000, "Sine.easeInOut");
//  以帧率60生成数据,对于同样的动画用于众多对象来说很有用,可预先计算数据
data = tween.generateData(60);
//  Now create some sprites to shown the tween data in action
bugs = game.add.group();
bugs.create(x, y, 'wasp');
//...
var index = 0;
function update() {
    bugs.getAt(0).x = x + data[index].x;
    bugs.getAt(0).y = y + data[index].y;
    //...
    index++;
    if (index === data.length)
    {
        index = 0;
    }
}

INTERPOLATION

动画插值设置

tween = game.add.tween(logo).to( { x: [ w, w, 0, 0 ], y: [ 0, h, h, 0 ] }, 4000, "Sine.easeInOut", true, -1, false);
//tween.interpolation(Phaser.Math.bezierInterpolation);
//tween.interpolation(Phaser.Math.catmullRomInterpolation);
//tween.interpolation(Phaser.Math.linearInterpolation);

Pause Tween

动画的暂停/继续播放

tween.pause();
tween.resume();

Repeat

动画的重复

//重播10次,重播前延迟1000毫秒
tween.repeat(10, 1000);

Tween From

动画到此

sprite = game.add.sprite(game.world.centerX, game.world.centerY, 'phaser');
sprite.anchor.set(0.5);
game.add.tween(sprite).from( { y: -200 }, 2000, Phaser.Easing.Bounce.Out, true);

Single Tween Reuse

单个动画的复用

tween.onComplete.addOnce(tween2, this);
//  一次性事件应如上使用addOnce,否则必须先移除上面所加的事件tween.onComplete.removeAll(),否则会再次触发
function tween2() {
    tween.to( { alpha: 0.5 }, 2000, Phaser.Easing.Bounce.Out, true);
    tween.onComplete.addOnce(tween3, this);
}
function tween3() {
    tween.to( { x: 400, y: 100, alpha: 1 }, 2000, Phaser.Easing.Bounce.Out, true);
    tween.onComplete.addOnce(tween2, this);
}

Tween Array

根据数组生成动画

tween = game.add.tween(sprite);
tween.to({ x: [500, 500, 100, 100], y: [250, 150, 150, 250] }, 3000, "Linear");
tween.start();

Tween Loop Event

动画循环事件

tween.onStart.add(onStart, this);
tween.onRepeat.add(onLoop, this);
tween.onComplete.add(onComplete, this);
//关闭延迟
tween.delay(0);

Tween Relative

相对值动画

//带引号的+300是相对值,意味着动画开始时的sprite.x+300
game.add.tween(sprite).to( { x: '+300' }, 2000, Phaser.Easing.Linear.None, true);

Tween Several Properties

同一对象的多属性动画

game.add.tween(item).to({y: 240}, 2400, Phaser.Easing.Bounce.Out, true, 1000 + 400 * i, 0);
game.add.tween(item).to({angle: 360}, 2400, Phaser.Easing.Cubic.In, true, 1000 + 400 * i, 0);

Yoyo

往复(反向动画回到原样)

var tween = game.add.tween(sprite).to( { alpha: 1 }, 2000, "Linear", true, 0, -1);
//  延迟3000毫秒后返回
tween.yoyo(true, 3000);

ANIMATION:动画

Animation Events

动画事件

anim = mummy.animations.add('walk');
anim.onStart.add(animationStarted, this);
anim.onLoop.add(animationLooped, this);
anim.onComplete.add(animationStopped, this);
anim.play(10, true);

Change Frame

改变sprite的帧

game.load.atlas('seacreatures', 'assets/sprites/seacreatures_json.png', 'assets/sprites/seacreatures_json.json');
greenJellyfish = game.add.sprite(330, 100, 'seacreatures', 'greenJellyfish0000');
greenJellyfish.frameName = 'greenJellyfish0010';

Change Texture On Click

改变材质

game.load.atlasJSONHash('bot', 'assets/sprites/running_bot.png', 'assets/sprites/running_bot.json');
game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
bot = game.add.sprite(200, 200, 'bot');
bot.animations.add('run');
bot.animations.play('run', 15, true);
bot.loadTexture('mummy', 0);
bot.animations.add('walk');
bot.animations.play('walk', 30, true);

Creature Dragon

生物龙

game.load.image('dragonTexture', 'assets/creature/dragon.png');
game.load.json('dragonMesh', 'assets/creature/dragon.json');
dragon = game.add.creature(450, 350, 'dragonTexture', 'dragonMesh');
dragon.play(true); //  true = loop

Load Texture

加载材质

game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
sprite.loadTexture('mummy', 0, false);
creature

Dynamic Animation

动态动画

game.load.image('orb', 'assets/sprites/orb-blue.png');
var bmd = game.add.bitmapData(352, 22);
//  在bmd中画16次图
var x = 0;
var y = -22;
for (var i = 0; i < 16; i++)
{
    bmd.draw(orb, x, y);
    x += 22;
    y += 3;
}
//  加入缓存,URL留空,传送bmd.canvas作为数据,尺寸22x22,帧数16
game.cache.addSpriteSheet('dynamic', '', bmd.canvas, 22, 22, 16, 0, 0);
//  生成精灵和动画
for (i = 0; i < 16; i++)
{
    var test = game.add.sprite(200, 100 + (i * 22), 'dynamic');
    test.animations.add('float');
    test.play('float', 20, true);
}

Frame Update

帧更新事件

sprite.onUpdate.add(onUpdate, this);

Group Creation

在组中生成(没明白)

Looped Animation

以15fps循环播放

sprite.animations.play('run', 15, true);

Sprite Sheet

精灵图列动画

game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
var mummy = game.add.sprite(300, 200, 'mummy');
var walk = mummy.animations.add('walk');
mummy.animations.play('walk', 30, true);

Starling Atlas

分片图集动画

game.load.atlasXML('octopus', 'assets/sprites/octopus.png', 'assets/sprites/octopus.xml');
var octopus = game.add.sprite(300, 200, 'octopus');
octopus.animations.add('swim');
octopus.animations.play('swim', 30, true);

Stop Animation

停止动画

greenJellyfish.animations.stop();
//  停止后重置到第一帧
// greenJellyfish.animations.stop(null, true);

Two Frame Test

两帧动画测试

left = player.animations.add('left', [8,9], 10, true);
right = player.animations.add('right', [1,2], 10, true);
player.animations.add('up', [11,12,13], 10, true);
player.animations.add('down', [4,5,6], 10, true);
player.play('left');

PARTICLES:粒子

Auto Scale

自动调整尺寸

//Phaser.Particles.Arcade.Emitter.setScale(minX, maxX, minY, maxY, rate, ease, yoyo) : Phaser.Particles.Arcade.Emitter;
emitter.setScale(0.1, 1, 0.1, 1, 6000, Phaser.Easing.Quintic.Out);

Click Burst

点击时爆炸

//Phaser.Particles.Arcade.Emitter.start(explode, lifespan, frequency, quantity, forceQuantity) : Phaser.Particles.Arcade.Emitter;
emitter.start(true, 2000, null, 10);
//  不爆炸,而是每帧20颗发射,生命周期是5000毫秒,见### Diamond Burst
//emitter.start(false, 5000, 20);

Collision

粒子碰撞

emitter.bounce.setTo(0.5, 0.5);
emitter.angularDrag = 30;
function update() {
game.physics.arcade.collide(emitter);
}

Destroy Emitter

销毁发射器

emitter.destroy();

Emitter Width

发射口宽度(缺省为中间一点)

emitter.width = 800;

Firestarter

喷火器

emitter = game.add.emitter(game.world.centerX, game.world.centerY, 400);
//随机使用不同火、烟的图片:[ 'fire1', 'fire2', 'fire3', 'smoke' ]
emitter.makeParticles( [ 'fire1', 'fire2', 'fire3', 'smoke' ] );
emitter.gravity = 200;
emitter.setAlpha(1, 0, 3000);
emitter.setScale(0.8, 0, 0.8, 0, 3000);
emitter.start(false, 3000, 5);

Flow

飘/漂

emitter = game.add.emitter(game.world.centerX, 0, 100);
emitter.makeParticles('leaf');
emitter.minParticleSpeed.setTo(-300, 30);
emitter.maxParticleSpeed.setTo(300, 100);
emitter.minParticleScale = 0.1;
emitter.maxParticleScale = 0.5;
emitter.gravity = 250;
//Phaser.Particles.Arcade.Emitter.flow(lifespan, frequency, quantity, total, immediate) : Phaser.Particles.Arcade.Emitter;
emitter.flow(2000, 500, 5, -1);

No Rotation

禁止粒子旋转

emitter.minRotation = 0;
emitter.maxRotation = 0;

Particle Alpha

粒子透明度

emitter.setAlpha(0.3, 0.8);

Particle Class

粒子类

//  自定粒子类
MonsterParticle = function (game, x, y) {
    Phaser.Particle.call(this, game, x, y, game.cache.getBitmapData('particleShade'));
};
MonsterParticle.prototype = Object.create(Phaser.Particle.prototype);
MonsterParticle.prototype.constructor = MonsterParticle;
emitter = game.add.emitter(game.world.centerX, 200, 200);
emitter.particleClass = MonsterParticle;
emitter.makeParticles();

Particle Scale

粒子尺寸

emitter.minParticleScale = 0.5;
emitter.maxParticleScale = 2;

Rain

下雨

var emitter = game.add.emitter(game.world.centerX, 0, 400);
emitter.width = game.world.width;
//发射角度
// emitter.angle = 30;
emitter.makeParticles('rain');
emitter.minParticleScale = 0.1;
emitter.maxParticleScale = 0.5;
emitter.setYSpeed(300, 500);
emitter.setXSpeed(-5, 5);
emitter.minRotation = 0;
emitter.maxRotation = 0;
emitter.start(false, 1600, 5, 0);

Snow

下雪

//背景发射器
back_emitter = game.add.emitter(game.world.centerX, -32, 600);
back_emitter.makeParticles('snowflakes', [0, 1, 2, 3, 4, 5]);
back_emitter.maxParticleScale = 0.6;
back_emitter.minParticleScale = 0.2;
back_emitter.setYSpeed(20, 100);
back_emitter.gravity = 0;
back_emitter.width = game.world.width * 1.5;
back_emitter.minRotation = 0;
back_emitter.maxRotation = 40;
//中景发射器
mid_emitter = game.add.emitter(game.world.centerX, -32, 250);
mid_emitter.makeParticles('snowflakes', [0, 1, 2, 3, 4, 5]);
mid_emitter.maxParticleScale = 1.2;
mid_emitter.minParticleScale = 0.8;
mid_emitter.setYSpeed(50, 150);
mid_emitter.gravity = 0;
mid_emitter.width = game.world.width * 1.5;
mid_emitter.minRotation = 0;
mid_emitter.maxRotation = 40;
//前景发射器
front_emitter = game.add.emitter(game.world.centerX, -32, 50);
front_emitter.makeParticles('snowflakes_large', [0, 1, 2, 3, 4, 5]);
front_emitter.maxParticleScale = 1;
front_emitter.minParticleScale = 0.5;
front_emitter.setYSpeed(100, 200);
front_emitter.gravity = 0;
front_emitter.width = game.world.width * 1.5;
front_emitter.minRotation = 0;
front_emitter.maxRotation = 40;
//改变风向
//changeWindDirection();
//启动
back_emitter.start(false, 14000, 20);
mid_emitter.start(false, 12000, 40);
front_emitter.start(false, 6000, 1000);

When Particles Collide

粒子碰撞

function update() {
    game.physics.arcade.collide(leftEmitter, rightEmitter, change, null, this);
}
function change(a, b) {
    a.frame = 3;
    b.frame = 3;
}

TIME:时间

Basic Timed Event

定时事件

game.time.events.add(Phaser.Timer.SECOND * 4, fadePicture, this);

BASIC LOOPED EVENT

循环事件

game.time.events.loop(Phaser.Timer.SECOND, updateCounter, this);

Basic Repeat Event

重复事件

game.time.events.repeat(Phaser.Timer.SECOND * 2, 10, createBall, this);

Custom Timer

自定定时器

timer = game.time.create(false);
timer.loop(2000, updateCounter, this);
timer.start();

Elapsed Seconds

经过的秒数

this.game.time.totalElapsedSeconds()

Remove Event

移除事件/定时器

//  从上倒下移除
game.time.events.remove(timerEvents[i]);

Slow Down Time

时钟调慢

game.time.advancedTiming = true;
game.time.desiredFps = 60;
game.time.slowMotion = 1.0;

TEXT:文本

Text Events

文本事件

//文本事件与精灵事件近似
text.inputEnabled = true;
text.input.enableDrag();
text.events.onInputOver.add(over, this);
text.events.onInputOut.add(out, this);
text.events.onInputDown.add(down, this);
text.events.onInputUp.add(up, this);
//销毁,见### REMOVE TEXT
text.destroy();

Text Gradient

文本渐变

var grd = text.context.createLinearGradient(0, 0, 0, text.height);
grd.addColorStop(0, '#8ED6FF');
grd.addColorStop(1, '#004CB3');
text.fill = grd;

Center Text

文本在边框中居中

var style = { font: "bold 32px Arial", fill: "#fff", boundsAlignH: "center", boundsAlignV: "middle" };
text = game.add.text(0, 0, "phaser 2.4 text bounds", style);
text.setShadow(3, 3, 'rgba(0,0,0,0.5)', 2);
//设定文本边框为x0, y100,800x100
text.setTextBounds(0, 100, 800, 100);

Center Text On Sprite

文本在精灵中居中

sprite = game.add.sprite(200, 200, 'pic');
var style = { font: "32px Arial", fill: "#ff0044", wordWrap: true, wordWrapWidth: sprite.width, align: "center", backgroundColor: "#ffff00" };
text = game.add.text(0, 0, "- text on a sprite -\ndrag me", style);
text.anchor.set(0.5);
function update() {
text.x = Math.floor(sprite.x + sprite.width / 2);
text.y = Math.floor(sprite.y + sprite.height / 2);
}

Word Wrap

单词折行

var style = { font: 'bold 60pt Arial', fill: 'white', align: 'left', wordWrap: true, wordWrapWidth: 450 };
var text = game.add.text(game.world.centerX, game.world.centerY, "phaser with a sprinkle of pixi dust", style);

Text Line Spacing

文本行距

text2.lineSpacing = 40;

Text Padding

文本内边距

text.padding.set(10, 16);

Text Reflect

文本镜像

textReflect = game.add.text(game.world.centerX, game.world.centerY + 50, "- PHASER -");
textReflect.scale.y = -1;

Text Resolution

文本解析度

text.resolution = 1;

Text Shadow

文本阴影

var text = createText(100, 'shadow 5');
// Phaser.Text.setShadow(x, y, color, blur, shadowStroke, shadowFill) : Phaser.Text;
text.setShadow(3, 3, 'rgba(0,0,0,0.5)', 5);

Text Shadow Stroke

文本阴影笔触(描边)

var text1 = game.add.text(20, 50, "Shadow Stroke", { font: "74px Arial Black", fill: "#c51b7d" });
text1.stroke = "#de77ae";
text1.strokeThickness = 16;
//  只给描边上阴影
text1.setShadow(2, 2, "#333333", 2, true, false);

var text2 = game.add.text(20, 180, "Shadow Fill", { font: "74px Arial Black", fill: "#c51b7d" });
text2.stroke = "#de77ae";
text2.strokeThickness = 16;
//  只给填充上阴影
text2.setShadow(2, 2, "#333333", 2, false, true);

var text3 = game.add.text(20, 310, "Shadow Both", { font: "74px Arial Black", fill: "#c51b7d" });
text3.stroke = "#de77ae";
text3.strokeThickness = 16;
//  缺省(描边和阴影都上阴影)
text3.setShadow(2, 2, "#333333", 2, true, true);

var text4 = game.add.text(20, 440, "Shadow None", { font: "74px Arial Black", fill: "#c51b7d" });
text4.stroke = "#de77ae";
text4.strokeThickness = 16;
// 都不上阴影(白调用啦)
text4.setShadow(2, 2, "#333333", 2, false, false);

Colored Characters

字符上色/着色

//  给16-24上'#ffff00'色
text.addColor('#ffff00', 16);
text.addColor('#ffffff', 25);
text.addColor('#ff00ff', 28);
text.addColor('#ffffff', 32);
//见### Text Tint
// text.tint = (item.tint === 0xffffff) ? 0xff0000 : 0xffffff;

Text Stroke With Color

给笔触/描边上色

//给13-19字符的描边上色
text.addStrokeColor('#ff0000', 13);
text.addStrokeColor('#000000', 20);

Text Tabs

文本制表符

var style = { font: "20px Courier", fill: "#fff", tabs: 132 };
text = game.add.text(100, 64, "Armor\tSpells\tDamage\tWeapons", style);
//  调整制表符宽度
// text.tabs = 132;

Text Tabs From Array

由数组生成制表文本

var style = { font: "16px Courier", fill: "#fff", tabs: [ 164, 120, 80 ] };
var headings = [ 'Name', 'Damage', 'Speed', 'Notes' ]; //可以嵌套,每行一个列表
text = game.add.text(32, 64, '', style);
text.parseList(headings);

Text With Physics

带物理属性的文本

//与精灵的物理属性近似
game.physics.arcade.enable([ text1, text2 ]);
text1.body.velocity.setTo(200, 200);
text1.body.collideWorldBounds = true;
text1.body.bounce.set(1);
text2.body.velocity.setTo(-100, -100);
text2.body.collideWorldBounds = true;
text2.body.bounce.set(1);
function update() {
game.physics.arcade.collide(text1, text2);
}

Extending Text

继承/扩充文本类

CustomText = function (game, x, y, text) {
    Phaser.Text.call(this, game, x, y, text, { font: "65px Arial", fill: "#ff0044", align: "center" });
    this.anchor.set(0.5);
    this.rotateSpeed = 1;
};
CustomText.prototype = Object.create(Phaser.Text.prototype);
CustomText.prototype.constructor = CustomText;
CustomText.prototype.update = function() {
    this.angle += this.rotateSpeed;
};

Google Webfonts

谷歌在线字体

WebFontConfig = {
    //  加载完成再延迟1秒后执行createText(使用字体)
    active: function() { game.time.events.add(Phaser.Timer.SECOND, createText, this); },
    google: {
        families: ['Revalia']
    }
};
function preload() {
    game.load.script('webfont', '//ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js');
}

Bitmap Fonts

Bitmap字体

game.load.bitmapFont('desyrel', 'assets/fonts/bitmapFonts/desyrel.png', 'assets/fonts/bitmapFonts/desyrel.xml');
bmpText = game.add.bitmapText(200, 100, 'desyrel', 'Phaser & Pixi\nrocking!', 64);

Clean Text

清除Bitmap文本中没有字体支持的文本

var text1 = game.add.bitmapText(100, 64, 'desyrel', dirtyString + (dirtyString.length), 32);
var cleanString = text1.cleanText(dirtyString);
var text2 = game.add.bitmapText(100, 300, 'desyrel', cleanString + (cleanString.length), 32);

Bitmapfont Drag

Bitmap文本拖拽

bmpText = game.add.bitmapText(10, 100, 'carrier_command','Drag me around !',34);
bmpText.inputEnabled = true;
bmpText.input.enableDrag();

Bitmaptext Anchor X

Bitmap文本锚点

var text3 = game.add.bitmapText(400, 470, 'desyrel', 'Anchor.x = 1', 64);
text3.anchor.x = 1;
//text3.anchor.y = 0.5; //### Bitmaptext Anchor Y

Bitmaptext Max Width

Bitmap文本最大行宽

//文本需要有空格才能自动折行
bmpText.maxWidth = 400;

Bitmaptext Purge Glyphs

Bitmap文本清除字符精灵

//长文本变短时,应清空BitmapText._glyphs数组中滞留的字符精灵
var purged = bmpText.purgeGlyphs();

Bitmaptext With Physics

有物理属性的Bitmap文本

game.physics.startSystem(Phaser.Physics.ARCADE);
text1 = game.add.bitmapText(200, 100, 'desyrel', 'BitmapText', 64);
text2 = game.add.bitmapText(400, 400, 'stack', 'with Physics', 32);
game.physics.arcade.enable([ text1, text2 ]);
text1.body.velocity.setTo(200, 200);
text1.body.collideWorldBounds = true;
text1.body.bounce.set(1);

Retro Font 1

retroFont复古字体

//retroFont复古字体只生成一个对象,而Bitmap文本为每个字母生成一个对象
game.load.image('knightHawks', 'assets/fonts/retroFonts/KNIGHT3.png');
font = game.add.retroFont('knightHawks', 31, 25, Phaser.RetroFont.TEXT_SET6, 10, 1, 1);
font.text = "phaser x: " + game.input.x + " y: " + game.input.y;

DEBUG:调试信息

通过叠加场景render渲染调试信息

function render() {
    // 画出调试工具
    game.debug.geom( rect, 'rgba(255,0,0,1)' ) ;
    game.debug.geom( circle, 'rgba(255,255,0,1)' ) ;
    game.debug.geom( point, 'rgba(255,255,255,1)' ) ;
    game.debug.pixel( 200, 280, 'rgba(0,255,255,1)' ) ;
    game.debug.text( "This is debug text", 100, 380 );

    // Camera调试信息
    game.debug.cameraInfo(game.camera, 32, 32);

    // Display调试信息
    game.debug.spriteBounds(sprite);
    game.debug.spriteCorners(sprite, true, true);

    // Input输入调试信息
    game.debug.inputInfo(32, 32);
    game.debug.spriteInputInfo(sprite, 32, 130);
    game.debug.pointer( game.input.activePointer );

    // Physics调试信息
    game.debug.body(sprite);

    // Sprite调试信息
    game.debug.spriteInfo(sprite, 32, 32);
}

TILE SPRITES:瓷砖精灵

Tiling Sprite

生成铺砖精灵

// (x, y, width, height, key)
tileSprite = game.add.tileSprite(0, 0, 800, 600, 'starfield');

Animated Tiling Sprite

移动瓷砖铺设的精灵tileSprite

tilesprite.tileScale.x++
tilesprite.tilePosition.y++
tilesprite.x++

Sprite Sheet Tiling Sprite

用精灵条spritesheet铺设的铺砖精灵tileSprite

game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
sprite = game.add.tileSprite(0, 0, 800, 600, 'mummy');
sprite.animations.add('walk');
sprite.animations.play('walk', 20, true);

Tiling Sprite Atlas

用图集Atlas生成铺砖精灵tileSprite

game.load.atlas('seacreatures', 'assets/sprites/seacreatures_json.png', 'assets/sprites/seacreatures_json.json');
//  'seacreatures'是缓存中的图集
//  'octopus0002'是图集中的帧
sprite = game.add.tileSprite(0, 0, 800, 600, 'seacreatures', 'octopus0002');

Colliding With Tiling Sprite

铺砖精灵tileSprite的碰撞

game.load.image('starfield', 'assets/misc/starfield.jpg');
game.load.image('ball', 'assets/sprites/pangball.png');
ball = game.add.sprite(400, 0, 'ball');
tilesprite = game.add.tileSprite(300, 450, 200, 100, 'starfield');
game.physics.enable([ ball, tilesprite ], Phaser.Physics.ARCADE);
ball.body.collideWorldBounds = true;
ball.body.bounce.set(1);
tilesprite.body.collideWorldBounds = true;
tilesprite.body.immovable = true;
tilesprite.body.allowGravity = false;
game.physics.arcade.collide(ball, tilesprite);

Tile Sprite From Animated Sprite

铺砖精灵动画

water = game.add.tileSprite(0, 24 * 16, 128 * 16, 24 * 16, 'waters');
water.animations.add('waves0', [0, 1, 2, 3, 2, 1]);
water.animations.add('waves1', [4, 5, 6, 7, 6, 5]);
water.animations.add('waves2', [8, 9, 10, 11, 10, 9]);
water.animations.add('waves3', [12, 13, 14, 15, 14, 13]);
water.animations.add('waves4', [16, 17, 18, 19, 18, 17]);
water.animations.add('waves5', [20, 21, 22, 23, 22, 21]);
water.animations.add('waves6', [24, 25, 26, 27, 26, 25]);
water.animations.add('waves7', [28, 29, 30, 31, 30, 29]);
// change to animation num
var n = 7;
water.animations.play('waves' + n, 8, true);

TILEMAPS:瓷砖地图

Blank Tilemap

生成空白铺砖地图

map = game.add.tilemap();
map.addTilesetImage('ground_1x1');
//  40x30块,每块32x32像素
layer1 = map.create('level1', 40, 30, 32, 32);
layer1.scrollFactorX = 0.5;
layer1.scrollFactorY = 0.5;
// 卷动世界
layer1.resizeWorld();
layer2 = map.createBlankLayer('level2', 40, 30, 32, 32);

Create From Array

通过数组生成铺砖地图

//  把位置数组加入缓存中
game.cache.addTilemap('dynamicMap', null, data, Phaser.Tilemap.CSV);
map = game.add.tilemap('dynamicMap', 16, 16);
map.addTilesetImage('tiles', 'tiles', 16, 16);
layer = map.createLayer(0);

Create From Objects

从对象生成地图(没看懂)

Csv Map

Csv地图

game.load.tilemap('map', 'assets/tilemaps/csv/catastrophi_level2.csv', null, Phaser.Tilemap.CSV);
game.load.image('tiles', 'assets/tilemaps/tiles/catastrophi_tiles_16.png');
map = game.add.tilemap('map', 16, 16);
map.addTilesetImage('tiles');
layer = map.createLayer(0);
layer.resizeWorld();

Csv Map Collide

与Csv地图碰撞

game.physics.arcade.collide(player, layer);

CSV MAP WITH P2

(存目)

Features Test

状态监测

map.setCollisionBetween(1, 12);
//  This will set Tile ID 26 (the coin) to call the hitCoin function when collided with
map.setTileIndexCallback(26, hitCoin, this);
//  This will set the map location 2, 0 to call the function
map.setTileLocationCallback(2, 0, 1, 1, hitCoin, this);

Fill Tiles

瓷砖填充

map.fill(31, layer.getTileX(sprite.x), layer.getTileY(sprite.y), 8, 8);

Paint Tiles

绘制(拾取、替换)瓷砖

if (map.getTile(layer.getTileX(marker.x), layer.getTileY(marker.y)).index != currentTile.index)
{
    map.putTile(currentTile, layer.getTileX(marker.x), layer.getTileY(marker.y));
}

Randomise Tiles

随机瓷砖

map.random(layer.getTileX(sprite.x), layer.getTileY(sprite.y), 6, 6);

Replace Tiles

替换瓷砖

//  整层替换某类瓷砖,可指定范围 x, y, width, height
map.replace(31, 46);

Swap Tiles

倒换瓷砖

//  整层倒换两类瓷砖,可限制范围x, y, width, height
map.swap(30, 31);

Resize Map

调整地图尺寸

layer.scale.set(2);
layer.resizeWorld();
layer.resize(w, h);

Tile Callbacks

瓷砖调用

//  设置瓷砖碰撞时26 (the coin)调用hitCoin
map.setTileIndexCallback(26, hitCoin, this);
//  设置瓷砖(2, 0)调用
map.setTileLocationCallback(2, 0, 1, 1, hitCoin, this);

Tileset From Bitmapdata

通过Bitmapdata生成map

bmd = game.make.bitmapData(32 * 25, 32 * 2);
map.addTilesetImage('tiles', bmd);

CAMERA:镜头

Moving The Camera

移动镜头

game.camera.y += 4;
game.camera.x -= 4;

Basic Follow

镜头跟随

//Camera.follow(target, style, lerpX, lerpY): void;
//线性插值lerpX、lerpY,值越小镜头越平稳,跟进也越慢
game.camera.follow(player);

Camera Fade

淡出

game.camera.follow(player, Phaser.Camera.FOLLOW_LOCKON, 0.1, 0.1);
game.input.onDown.add(fade, this);
game.camera.onFadeComplete.add(resetFade, this);
game.input.onDown.add(fade, this);
function fade() {
game.camera.fade(0x000000, 4000);
}
    function resetFade() {
    game.camera.resetFX();
}

Camera Flash

镜头闪动

game.camera.flash(0xff0000, 500);

Camera Shake

镜头晃动

game.camera.shake(0.05, 500);

Deadzone

定死区域

game.camera.follow(player);
//  如果目标在限定区域则不摇动镜头,要突出边界时才摇动
game.camera.deadzone = new Phaser.Rectangle(100, 100, 600, 400);

Fixed To Camera

与镜头绑定

sprite = game.add.sprite(100, 300, 'phaser');
sprite.fixedToCamera = true;
sprite.cameraOffset.setTo(200, 500);

Follow Styles

镜头跟随类型

game.camera.follow(ufo, Phaser.Camera.FOLLOW_LOCKON);
style = 'STYLE_LOCKON';
//style = 'STYLE_PLATFORMER';
//style = 'STYLE_TOPDOWN';
//style = 'STYLE_TOPDOWN_TIGHT';

WORLD:世界

Fixed To Camera

固定sprite、text到镜头/前

sprite = game.add.sprite(0, 0, 'phaser');
sprite.fixedToCamera = true;
sprite.cameraOffset.setTo(100, 100);
var text = game.add.text(0, 0, "this text is fixed to the camera", { font: "32px Arial", fill: "#ffffff", align: "center" });
text.fixedToCamera = true;
text.cameraOffset.setTo(200, 500);
//镜头跟随见实例### World Wrap
//game.camera.follow(sprite);

Move Around World

镜头移动

game.camera.x += 4;

World Wrap

世界折返

game.world.wrap(card, 0, true);

DISPLAY:显示

Circle

画圆

graphics.drawCircle(300, 300, 100);

Ellips

画椭圆

graphics.drawEllipse(100, 100, 200, 60);

Arc

画扇形/弧线

graphics.arc(0, 0, 135, game.math.degToRad(90), game.math.degToRad(180), false);

Arcade Physics Graphics Shape

给Graphics图形赋予物理属性

var graphics = game.add.graphics(0, 0);
game.physics.arcade.enable(graphics);

Extract Mask

同色提取到遮罩

bitmapData.extract(bitmapData_mask, 237, 0, 140);

 Fullscreen

全屏

// 拉伸以填满
game.scale.fullScreenScaleMode = Phaser.ScaleManager.EXACT_FIT;
// 保持原尺寸
// game.scale.fullScreenScaleMode = Phaser.ScaleManager.NO_SCALE;
// 保持比例
// game.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL;
game.scale.startFullScreen(false);
//game.scale.stopFullScreen();

Game Background Color

游戏背景色

game.stage.backgroundColor = "#4488AA";
// game.stage.backgroundColor = 0x4488aa;
// game.stage.backgroundColor = 'rgb(68, 136, 170)';
// game.stage.backgroundColor = 'rgba(68, 136, 170, 0.5)';
//随机色
// game.stage.backgroundColor = Phaser.Color.getRandomColor(50, 255, 255);

Generate Texture From Graphics

用图形生成材质

sprite = game.add.sprite(400, 300, graphics.generateTexture());

Gradient

在遍历中步进插色以生成渐变

for (var i = 0; i < 30; i++)
{
    var c = Phaser.Color.interpolateColor(0x66d973, 0x40b54d, 30, i);
    //Phaser.Color.interpolateColorWithRGB(color, r, g, b, steps, currentStep) : number;
    bmd.rect(0, y, 800, y+2, Phaser.Color.getWebRGB(c));
    out.push(Phaser.Color.getWebRGB(c));
    y += 2;
}

Graphics

绘制图形

var graphics = game.add.graphics(100, 100);
// 设置填充和线条样式
graphics.beginFill(0xFF3300);
graphics.lineStyle(10, 0xffd900, 1);
// 用直线逐步绘制图形
graphics.moveTo(50,50);
graphics.lineTo(250, 50);
graphics.lineTo(100, 100);
graphics.lineTo(250, 220);
graphics.lineTo(50, 220);
graphics.lineTo(50, 50);
graphics.endFill();
// 绘制二次方程曲线
graphics.quadraticCurveTo(600, 0, 480,100);
// 绘制方形
graphics.drawRect(50, 250, 100, 100);
// 绘制圆形
graphics.drawCircle(470, 200, 200);

Graphics Input Events

图形输入事件

graphics.inputEnabled = true;
graphics.input.useHandCursor = true;
//graphics.events.onInputDown.add(onDown, this);
//graphics.events.onInputUp.add(onUp, this);
//graphics.events.onInputOut.add(onOut, this);
graphics.events.onInputOver.add(onOver, this);
function onOver() {
    //...
}

Hsv Color Wheel

Hsv色盘

colorsArray = Phaser.Color.HSVColorWheel();

Pixi Render Texture

生成Pixi渲染材质

renderTexture = game.add.renderTexture(800, 600, 'texture1');

Render Texture Image

生成渲染材质图像

ball = game.make.sprite(0, 0, 'ball');
texture = game.add.renderTexture(game.width, game.height);
game.add.sprite(0, 0, texture);
//将sprite加入材质中
texture.renderXY(ball, game.input.activePointer.x, game.input.activePointer.y, true);

Render Crisp

渲染锐化?

sprite.smoothed = false;
//  全舞台锐化
// game.stage.smoothed = false;

Sprite Shadow

用tint着色法生成阴影

shadow = game.add.sprite(game.world.centerX, game.world.centerY, 'hotdog');
shadow.tint = 0x000000;
shadow.alpha = 0.6;

Viewport

视图/窗口尺寸

game.scale.viewportWidth
game.scale.viewportHeight
window.innerWidth
window.outerWidth
window.innerHeight
window.outerHeight
game.scale.documentWidth
game.scale.documentHeight
window.screen.width
window.screen.height
window.screen.availWidth
window.screen.availHeight

BITMAPDATA:BITMAPD数据

Fastcopy Draw

快速拷贝

bmdDest.copy(bmd, 0, 0);

Copy Bitmapdata

拷贝Bitmapdata

bmd = game.make.bitmapData(800, 600);
//贴图
bmd.copy('pic');
bmd.addToWorld();
bmd2 = game.make.bitmapData(64, 64);
bmd2.circle(32, 32, 32, 'rgba(255,0,255,0.2)');
//画出Bitmapdata数据
bmd.draw(bmd2, x - 16, y - 16);

Copy Pixels

拷贝像素

bmd = game.make.bitmapData(800, 600);
bmd.addToWorld();
area = new Phaser.Rectangle(0, 300, 200, 16);
//拷贝图片的矩形区域
bmd.copyRect('pic', area, 300, 0);

Draw Sprite

绘制精灵

bmd = game.add.bitmapData(game.width, game.height);
bmd.addToWorld();
bmd.draw(sprite, 10, 10);

Alpha Mask

alphaMask透明度遮罩

var bmd = game.make.bitmapData(320, 256);
// 原图pic应用遮罩mask后拷贝到bmd中
bmd.alphaMask('pic', 'mask');
// BitmapData只是材质,转换为sprite或image后显示
game.add.image(game.world.centerX, 320, bmd).anchor.set(0.5, 0);

Atlas

图集

game.load.atlas('seacreatures', 'assets/sprites/seacreatures_json.png', 'assets/sprites/seacreatures_json.json');
bmd = game.make.bitmapData(800, 600);
game.add.image(0, 0, bmd);
//选择seacreatures图集中的blueJellyfish0010帧生成sprite
jellyfish = game.add.sprite(0, 0, 'seacreatures', 'blueJellyfish0010');
//(prefix, start, stop, suffix, zeroPad) 指文件名(如explosion_0001-large)的前部字符串(explosion_)、开始编号(1)、结束编号、后缀字符串(-large)、编号的填零位数(4)
jellyfish.animations.add('swim', Phaser.Animation.generateFrameNames('blueJellyfish', 0, 32, '', 4), 30, true);
jellyfish.animations.play('swim');
//  画上的是动画当前帧
bmd.draw(jellyfish, game.input.activePointer.position.x, game.input.activePointer.position.y);

Cached Bitmapdata

缓存Bitmapdata数据

var bmd = game.add.bitmapData(32, 32);
//填充渐变
var grd = bmd.context.createLinearGradient(0, 0, 0, 32);
grd.addColorStop(0, '#8ED6FF');
grd.addColorStop(1, '#004CB3');
bmd.context.fillStyle = grd;
bmd.context.fillRect(0, 0, 32, 32);
//重新渲染
//bmd.dirty = true;
//  缓存与取用
game.cache.addBitmapData('blueShade', bmd);
game.add.sprite(8, 8, game.cache.getBitmapData('blueShade'));

Draw Atlas Frame

绘制图集的帧

game.load.atlas('atlas', 'assets/sprites/atlas_hash_trim.png', 'assets/sprites/atlas_json_hash_trim.json');
bmd = game.add.bitmapData(800, 600);
bmd.addToWorld(8, 8);
sprite = game.add.sprite(100, 64, 'atlas', 'contra3');
sprite.tint = 0;
bmd.draw(sprite);

Draw Full

全部绘制

var bmd = game.add.bitmapData(game.width, game.height);
var bmdContainer = bmd.addToWorld(390, 290, 0, 0, 0.5, 0.5);
game.stage.updateTransform();
//  把world整个儿绘制到BitmapData
bmd.drawFull(game.world);

Draw Group

绘制组

var bmd = game.add.bitmapData(game.width, game.height);
var bmdContainer = bmd.addToWorld(390, 290, 0, 0, 0.5, 0.5);
game.stage.updateTransform();
// bmd.drawGroup(group);
bmd.drawGroup(game.world);

Get Pixel

取得像素

var color = bmd.getPixelRGB(x, y);
bmd.fill(0, 0, 0);
bmd.rect(1, 1, 62, 62, color.rgba);

Process Pixels 1

处理像素

//processPixelRGB(callback, callbackContext, x, y, width, height)
bmd.processPixelRGB(forEachPixel, this);
function forEachPixel (pixel) {
    //换色
    var r = pixel.r;
    var g = pixel.g;
    var b = pixel.b;
    pixel.r = b;
    pixel.g = g;
    pixel.b = r;
    //灰度效果,见### Process Pixels 2
    //pixel.r = pixel.r;
    //pixel.g = pixel.r;
    //pixel.b = pixel.r;
    //反色
    //pixel.r = 255 - pixel.r;
    //pixel.g = 255 - pixel.g;
    //pixel.b = 255 - pixel.b;
    return pixel;
}

Radial Gradient

放射状渐变

var grd = bmd.context.createRadialGradient(innerCircle.x, innerCircle.y, innerCircle.radius, outerCircle.x, outerCircle.y, outerCircle.radius);

Replace Color

替换颜色

// replaceRGB: function (sourceR, sourceG, sourceB, sourceA, destR, destG, destB, destA, region)
bmd.replaceRGB(0, 85, 255, 255, 0, 250, 40, 255);

Set Hsl

设置、调整HSL色彩空间

//BitmapData.setHSL(h, s, l, region)
// bmd.setHSL(0.2);
//BitmapData.shiftHSL(h, s, l, region) 在原值上累积
bmd.shiftHSL(0.1);
// bmd.shiftHSL(0.1, null, null, new Phaser.Rectangle(32, 32, 100, 100));
//亮度调到最高/白色
// bmd.shiftHSL(null, null, 1.0);
//降低饱和度
// bmd.shiftHSL(null, -1.0, null);

Sprite Texture

用作精灵材质

//  绘制图形
//清除
bmd.cls();
bmd.circle(100, 100, 32, 'rgba(255,0,0,0.8)');
bmd.rect(110, 40, 64, 120, 'rgba(255,0,255,0.8)');
sprite = game.add.sprite(300, 300, bmd);

Text

绘制文本

text = game.make.text(0, 0, "phaser", { font: "bold 32px Arial", fill: "#ff0044" });
bmd.draw(text, game.world.randomX, game.world.randomY, null, null, 'destination-out');

GEOMETRY:几何形状

Line

line1 = new Phaser.Line(handle1.x, handle1.y, handle2.x, handle2.y);
//在update中:
//从sprite获得新的端点位置,根据sprite划线
line1.fromSprite(sprite1, sprite2, false);

Rotate Line

旋转

function update() {
    line.rotate(1, true);
}

Line Bounds

调试

line.end.set(game.input.activePointer.x, game.input.activePointer.y);
line.start.set(pointer.x, pointer.y);
game.debug.geom(line);
game.debug.rectangle(line);

Center Line

通过中点点位线

line = new Phaser.Line(100, 100, 200, 200);
line.centerOn(game.input.activePointer.x, game.input.activePointer.y);
line.rotate(0.05);
game.debug.geom(line);

Centroid

中心(重心)

Phaser.Point.centroid(points, out) : Phaser.Point;
points:Array.<Phaser.Point>
out (optional):Phaser.Point //存储结果的点,如果不设置则返回一个结果点
returns:Point

var points = [];
var centroid;
points.push(img.position);
var c = Phaser.Point.centroid(points);
centroid.position.copyFrom(c);

Circle

圆形

circle = new Phaser.Circle(game.world.centerX, 100,64);
game.debug.geom(circle,'#cfffff');
game.debug.text('Diameter : '+circle.diameter,50,200);
game.debug.text('Circumference : '+circle.circumference(),50,230);

Circle Random Point

圆中的随机点

circle = new Phaser.Circle(game.world.centerX, game.world.centerY, 500);
p = new Phaser.Point();
circle.random(p);
//  ellipse.random(p);  //椭圆中的随机点
//  line.random(p); //线中随机点
//  rectangle.random(p); //方形中随机点
//  将浮点数转为整书
p.floor();
bmd.setPixel(p.x, p.y, colors[i].r, colors[i].g, colors[i].b);

Line Intersection

两线交点

var p = new Phaser.Point();
p = line1.intersects(line2, true);

Line Midpoint

线段中点

mid = new Phaser.Point();
line.midPoint(mid);

Line Reflection

线的镜像

//  Update the normal from the intersection point (100px length)
line3.fromAngle(p.x, p.y, line2.normalAngle, 100);
//  Either of these is fine:
// var outgoing = Phaser.Line.reflect(line1, line2);
var outgoing = line1.reflect(line2);
reflection.fromAngle(p.x, p.y, outgoing, 200);

Playing With Points

点运动

p1 = new Phaser.Point(game.world.centerX, game.world.centerY);
p2 = new Phaser.Point(p1.x - 50, p1.y - 50);
p3 = new Phaser.Point(p2.x - 50, p2.y - 50);
p4 = new Phaser.Point(p3.x - 50, p3.y - 50);
function update() {
    //绕点旋转
    //Phaser.Point.rotate(x, y, angle, asDegrees, distance)
    p2.rotate(p1.x, p1.y, d2, true, 150);
    p3.rotate(p2.x, p2.y, d3, true, 100);
    p4.rotate(p3.x, p3.y, d4, true, 50);
}
function render() {
    //在CANVAS渲染材质上绘图
    game.context.strokeStyle = 'rgb(0,255,255)';
    game.context.beginPath();
    game.context.moveTo(p1.x, p1.y);
    game.context.lineTo(p2.x, p2.y);
    game.context.lineTo(p3.x, p3.y);
    game.context.lineTo(p4.x, p4.y);
    game.context.stroke();
    game.context.closePath();
}

Polygon

绘制多边形

//  用Point数组绘制
// poly = new Phaser.Polygon([ new Phaser.Point(200, 100), new Phaser.Point(350, 100), new Phaser.Point(375, 200), new Phaser.Point(150, 200) ]);
//  用Point参数绘制
// poly = new Phaser.Polygon(new Phaser.Point(200, 100), new Phaser.Point(350, 100), new Phaser.Point(375, 200), new Phaser.Point(150, 200));
//  用x,y数值数组绘制
// poly = new Phaser.Polygon([200, 100, 350, 100, 375, 200, 150, 200]);
//  用x,y参数绘制
// poly = new Phaser.Polygon(200, 100, 350, 100, 375, 200, 150, 200);
//  用混合类型数组绘制
// poly = new Phaser.Polygon([ new Phaser.Point(200, 100), 350, 100, 375, 200, new Phaser.Point(150, 200) ]);
//  用混合类型参数绘制
// poly = new Phaser.Polygon(new Phaser.Point(200, 100), 350, 100, 375, 200, new Phaser.Point(150, 200));
//  用包含x,y属性的对象数组绘制
// poly = new Phaser.Polygon([ { x: 200, y: 100 }, { x: 350, y: 100 }, { x: 375, y: 200}, { x: 150, y: 200 } ]);
//  用包含x,y属性的对象作为参数绘制
// poly = new Phaser.Polygon( { x: 200, y: 100 }, { x: 350, y: 100 }, { x: 375, y: 200}, { x: 150, y: 200 });
//  先生成空多边形
poly = new Phaser.Polygon();
//  再用setTo绘制,参数同上各式
poly.setTo([ new Phaser.Point(200, 100), new Phaser.Point(350, 100), new Phaser.Point(375, 200), new Phaser.Point(150, 200) ]);
graphics = game.add.graphics(0, 0);
graphics.beginFill(0xFF33ff);
graphics.drawPolygon(poly.points);
graphics.endFill();

Polygon Contains

多边形包含判断

if (poly.contains(game.input.x, game.input.y)){}

Rectangle

方形

floor = new Phaser.Rectangle(0, 550, 800, 50);
function render () {game.debug.geom(floor,'#0fffff');}

Rectangle Get Point

方形取定位点

var p = new Phaser.Point();
rectangle.getPoint(Phaser.TOP_LEFT, p);

Rectangle Intersects

方形交叉/重叠

var intersects = Phaser.Rectangle.intersection(rectA, rectB);
game.debug.geom(intersects, 'rgba(255,0,0,1)');

AUDIO:音频

Audio Sprite/### Audio Sprite Duration

声音精灵

game.load.audio('sfx', [ 'assets/audio/SoundEffects/magical_horror_audiosprite.mp3', 'assets/audio/SoundEffects/magical_horror_audiosprite.ogg' ]);
fx = game.add.audio('sfx');
fx.allowMultiple = true;
//标签名、开始位置、长度
fx.addMarker('alien death', 1, 1.0);
......
fx.play('alien death');
....
//暂停、继续
if (fx.paused)
{
    fx.resume();
}
else
{
    fx.pause();
}

Play Music

音量控制

music.mute = false;
music.volume += 0.1;

Fade In

音频淡入

game.load.audio('boden', 'assets/audio/goaman_intro.mp3');
music = game.add.audio('boden');
music.onDecoded.add(start, this);
function start() {
    music.fadeIn(4000);
}

Audio Sprite Json

音频JSON数据(代替标签)

var audioJSON = {
    spritemap: {
        'alien death': {
            start: 1,
            end: 2,
            loop: false
        },
        ......
    }
};
game.load.audiosprite('sfx', 'assets/audio/SoundEffects/fx_mixdown.ogg', null, audioJSON);

Loop

循环

bass = game.add.audio('bass');
......
sounds = [ bass, drums, percussion, synth1, synth2, top1, top2 ];
//  mp3需要解码时间,并且解码完成顺序是不定的
game.sound.setDecodedCallback(sounds, start, this);
function start() {
    sounds.shift();
    //整体循环,音量比例0.6
    bass.loopFull(0.6);
    bass.onLoop.add(hasLooped, this);
    text.text = 'bass';
}

Remove Sound

移除音频

music.destroy();
game.cache.removeSound('wizball');

Restart Sound

重播

music.restart();

Sound Complete

完成事件

explosion.onStop.add(soundStopped, this);

VIDEO:视频

Alpha Webm

带透明度的Webm视频(谷歌浏览器支持)

game.load.video('space', 'assets/video/alpha-webm.webm');
video = game.add.video('space');
video.play(true);
video.addToWorld(400, 300, 0.5, 0.5);

Change Source

改变视频源

video.onPlay.addOnce(start, this);
function start() {
    //  5秒后切换源
    game.time.events.add(5000, changeSource, this);
}
function changeSource() {
    video.changeSource('assets/video/skull.mp4');
}

Snapshot Blend Mode

视频快照混色模式

function takeSnapshot() {
    if (bmd.width !== video.width || bmd.height !== video.height)
    {
        bmd.resize(video.width, video.height);
    }
    video.grab(true, alpha.alpha);
    bmd.draw(video.snapshot);
    bmd.draw('swirl', 0, 0, video.width, video.height, 'color');
}

Sprites Sharing Video

精灵分有视频

group = game.add.group();
video = game.add.video('liquid');
for (var i = 0; i < 10; i++)
{
    var sprite = group.create(game.world.randomX, game.world.randomY, video);
}

Video Stream

摄像

video = game.add.video();
//  可以使用镜头时
video.onAccess.add(camAllowed, this);
//  不能使用镜头时
video.onError.add(camBlocked, this);
video.startMediaStream();

WEAPON:武器

Asteroids

爆破彗星

//  用图bullet生成30颗子弹的武器
weapon = game.add.weapon(30, 'bullet');
weapon.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
weapon.bulletSpeed = 600;
weapon.fireRate = 100;
sprite = this.add.sprite(400, 300, 'ship');
//追踪
weapon.trackSprite(sprite, 0, 0, true);
weapon.fire();

Asteroids Bullet Wrap

weapon.bulletKillType = Phaser.Weapon.KILL_LIFESPAN;
weapon.bulletLifespan = 2000;
//子弹折返
weapon.bulletWorldWrap = true;

Bullet Angle Variance

子弹角度变量

weapon.bulletAngleVariance = 10;

Bullet Speed Variance

字典速度变量

weapon.bulletSpeedVariance = 200;

Fire Rate

射击速率

//每60毫秒允许一颗子弹
weapon.fireRate = 60;

Single Bullet

单发

weapon = game.add.weapon(1, 'bullet');

LOADER:文件加载器

Asset Pack

载入资源包

game.load.pack('level1', 'assets/asset-pack1.json', null, this);

Check Cache

检测缓存中是否有某键值

//   检测是否存在
let image:Boolean = game.cache.checkImageKey('image');
let text:Boolean = game.cache.checkTextKey('html');
let tilemap:Boolean = game.cache.checkTilemapKey('mario');
let audio:Boolean = game.cache.checkSoundKey('sfx');

Load Audio

载入音频文件

game.load.audio('boden', ['assets/audio/bodenstaendig_2000_in_rock_4bit.mp3', 'assets/audio/bodenstaendig_2000_in_rock_4bit.ogg']);
//  如果确定浏览器支持某种文件,可如下:
// game.load.audio('boden', 'assets/audio/bodenstaendig_2000_in_rock_4bit.mp3');
music = game.sound.play('boden');

Load Binary File

载入二进制文件

//  Phaser使用XMLHttpRequest载入二进制文件。如果从域外载入,会有'Access-Control-Allow-Origin'头标记;是原处数据,不需要解码。
game.load.binary('mod', 'assets/audio/protracker/global_trash_3_v2.mod', binaryLoadCallback, this);
function binaryLoadCallback(key, data) {
    //  把文件转换为Uint8Array,并把结果返回给缓存
    return new Uint8Array(data);
}
function create() {
    var buffer = game.cache.getBinary('mod');
    //   getString在区间内进行文本扫描并返回文本
    var signature = getString(buffer, 1080, 1084);
    var text = game.add.text(32, 32, "Signature: " + signature, { fill: '#ffffff' });
}

Load Bitmap Font

载入Bitmap字体(可用BMFont等生成)

game.load.bitmapFont('desyrel', 'assets/fonts/bitmapFonts/desyrel.png', 'assets/fonts/bitmapFonts/desyrel.xml');
text = game.add.bitmapText(200, 100, 'desyrel','Bitmap Fonts!',64);

Load Events

game.load.onLoadStart.add(loadStart, this);
game.load.onFileComplete.add(fileComplete, this);
game.load.onLoadComplete.add(loadComplete, this);
function fileComplete(progress, cacheKey, success, totalLoaded, totalFiles) {
    text.setText("File Complete: " + progress + "% - " + totalLoaded + " out of " + totalFiles);
    var newImage = game.add.image(x, y, cacheKey);
}

Load Image

载入图像

game.load.image('imageKey', 'assets/sprites/phaser2.png');
game.add.sprite(0, 0, 'imageKey');

Load Spritesheet

载入精灵单子

//Phaser.Game.load.spritesheet(key, url, frameWidth, frameHeight, frameMax, margin, spacing) : Phaser.Loader;
game.load.spritesheet('uniqueKey', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);
var sprite = game.add.sprite(300, 200, 'uniqueKey');
sprite.animations.add('walk');
sprite.animations.play('walk', 50, true);

Load Starling Atlas

载入图集

game.load.atlasXML('seacreatures', 'assets/sprites/seacreatures.png', 'assets/sprites/seacreatures.xml');
jellyfish = game.add.sprite(330, 100, 'seacreatures');
jellyfish.animations.add('swim', Phaser.Animation.generateFrameNames('greenJellyfish', 0, 39, '', 4), 30, true);
jellyfish.animations.play('swim');

Load Text File

载入文本文件

game.load.text('html', 'http://phaser.io');
var html = game.cache.getText('html');
text = html.split('\n');

Load Json File

载入Json文件

//如果要控制解析,请用load.text;域外载入时有文件头
game.load.json('version', 'http://phaser.io/version.json');
var phaserJSON = game.cache.getJSON('version');
var text2 = game.add.text(100, 200, "Name: " + phaserJSON.name, { fill: '#ffffff' });

Load Texture Atlas

载入材质图集

game.load.atlas('test', 'assets/sprites/atlas_hash_trim.png', 'assets/sprites/atlas_json_array_trim.json', Phaser.Loader.TEXTURE_ATLAS_JSON_HASH);
game.add.sprite(0, 0, 'test');

Load Tilemap Json

载入瓷砖地图Json

game.load.tilemap('mario', 'assets/tilemaps/maps/super_mario.json', null, Phaser.Tilemap.TILED_JSON);
map = game.add.tilemap('mario');
//Phaser.Tilemap.addTilesetImage(tileset, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid) : Phaser.Tileset;
map.addTilesetImage('SuperMarioBros-World1-1', 'tiles');
layer = map.createLayer('World1');

Load Video

载入视频

game.load.video('chrome', 'assets/video/chrome.webm');
video = game.add.video('chrome');
sprite = video.addToWorld(game.world.centerX, game.world.centerY, 0.5, 0.5, 2, 2);
video.play(true);

Pick Images From Cache

存缓存中拣出图像

//  返回缓存中的图像键值数组
let images:Array = game.cache.getKeys(Phaser.Cache.IMAGE);
let img:String = game.rnd.pick(images);
let tempSprite:Sprite = game.add.sprite(game.world.randomX, game.world.randomY, img);

FILTERS:滤镜

可应用到sprite的WebGL影子/滤镜(shader/filter)

new Filter(game, uniforms, fragmentSrc)
//game:Phaser.Game实例,当前game的引用
//uniforms:Uniform mappings对象
//fragmentSrc:Array或者string,fragment shader代码,可以是数组(每行代码作一个元素,加上引号),也可以是string

Blue Dots

game.load.shader('blueDots', 'assets/shaders/blue-dots.frag');
filter = new Phaser.Filter(game, null, game.cache.getShader('blueDots'));
filter.setResolution(800, 600);
sprite = game.add.sprite();
sprite.filters = [ filter ];
// 在update中:
filter.update();

Blur

模糊

game.load.script('BlurX', 'https://cdn.rawgit.com/photonstorm/phaser/master/v2/filters/BlurX.js');
game.load.script('BlurY', 'https://cdn.rawgit.com/photonstorm/phaser/master/v2/filters/BlurY.js');
var blurX = game.add.filter('BlurX');
var blurY = game.add.filter('BlurY');
blurX.blur = 100;
blurY.blur = 1;
sprite.filters = [blurX, blurY];

MISC:杂项

Antialias Game

抗锯齿

var transparent = false;
var antialias = false;
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', this, transparent, antialias);

Device

设备

function render () {
    game.debug.text('Navigator: ' + navigator.userAgent, 32, 32);
    game.debug.text('iOS: ' + game.device.iOS, 32, 64);
    game.debug.text('Mobile Safari: ' + game.device.mobileSafari, 32, 98);
    game.debug.text('WebApp: ' + game.device.webApp, 32, 128);
    game.debug.text('nav: ' + navigator['standalone'], 32, 128+32);
    game.debug.text('app: ' + game.device.iOSVersion, 32, 128+64);
}

Game Config

通过对象设置游戏

var conf = {
    width: 800,
    height: 600,
    renderer: Phaser.AUTO,
    parent: 'phaser-example',
    transparent: false,
    antialias: false,
    state: this,
    scaleMode: Phaser.ScaleManager.EXACT_FIT
};
var game = new Phaser.Game(conf);
function preload() {
    //...
}
function create() {
    //...
}

Net

网络信息

game.net.getHostName()
game.net.checkDomainName('192')
game.net.checkDomainName('google.com')
game.net.updateQueryString('atari', '520')
game.net.updateQueryString('amiga', '1200')
game.net.getQueryString()
game.net.getQueryString('atari')

Pause Menu

暂停游戏

game.paused = true;
game.stop(); //### Webcam

Random Generators

随机数生成器

var style = { font: "14px Arial", fill: "#ff0044", align: "center" };
game.add.text(32, 30, 'Integer: ' + game.rnd.integer(), style);
game.add.text(32, 60, 'Frac: ' + game.rnd.frac(), style);
game.add.text(32, 90, 'Real: ' + game.rnd.real(), style);
game.add.text(32, 120, 'Integer in Range (100-200): ' + game.rnd.integerInRange(100, 200), style);

Weighted Pick

加权挑拣

var test = [0,1,2,3,4,5,6,7,8,9];
var total = [0,0,0,0,0,0,0,0,0,0];
for (var i = 0; i < 1000000; i++)
{
    rnd = this.game.rnd.weightedPick(test);
    total[rnd]++;
}