Phaser系列课程初步分成《基础篇上》、《基础篇下》、《动画篇》、《交互篇》、《物理引擎篇》、《图形绘制篇》、《场景篇》。

上一篇我们讲了如何创建Phaser动画,而互动游戏的核心在于人机交互,其实质就是通过响应用户的输入来播放动画或者改变动画。Phaser没有DOM结构的概念,我们无法直接使用DOM事件,必须依赖Phaser自身的API。下面,我们在上一篇内容的基础上学习在Phaser中如何响应用户操作。

Phaser基本的交互事件主要分为两大类:触屏事件和键盘事件。

第一类:触屏事件

屏幕添加单手指触屏事件

1
2
3
4
5
6
7
8
9
game.input.onTap.add(onTap, this);  //监听点击
game.input.onDown.add(onDown, this); //监听手指按下
game.input.onUp.add(onUp, this); //监听手指放开
game.input.onHold.add(onHold, this); //监听手指长按放开,3s

function onTap(pointer, doubleTap) {}
function onDown(pointer) {}
function onUp(pointer) {}
function onHold(pointer) {}

参数pointer记录手势的坐标等信息,onTap第二个参数doubleTap表示是否为双击事件。

屏幕添加多手指触屏事件

Phaser假设人都有10只手指,只要有一只手指触屏,以下代码都能触发一次onDown,并通过pointer参数返回的id字段按照按下的顺序标记手指。

1
2
3
4
5
game.input.onDown.add(onDown, this);

function onDown(pointer){
console.log(pointer)
}

我们也可以在render函数中打印手指触屏的实时信息

1
2
3
4
game.debug.pointer(game.input.pointer1);
game.debug.pointer(game.input.pointer2);
...
game.debug.pointer(game.input.pointer10);

然而,Phaser本身默认只能监听最多两只手指的触屏事件,每需要监听多一只手指的触屏事件,都需要手动在create中如下所示增加一条手指触屏监听,所以,最多能再增加8条。但是,由于IOS本身的机制问题,只能最多监听5只手指的触屏事件,Phaser官方对此表示没有办法。Note: on iOS as soon as you use 6 fingers you’ll active the minimise app gesture - and there’s nothing we can do to stop that, sorry

1
game.input.addPointer();

扫描二维码,预览体验效果:

物体添加交互事件

每一个sprite包含很多事件,都在events对象下面,如生命周期监听、交互监听,其中常用的交互监听事件有onInputOver(鼠标经过)、onInputOut(鼠标移开)、onInputDown(手指按下)、onInputUp(手指松开)、onDragStart(拖拽开始)、onDragStop(拖拽结束)、onDragUpdate(拖拽中)。这些事件的回调中返回的参数如下所示:

事件 参数 说明
onInputOver (sprite) (当前sprite)
onInputOut (sprite) (当前sprite)
onInputDown (sprite, pointer) (当前sprite, 当前手指触屏信息)
onInputUp (sprite, pointer) (当前sprite, 当前手指触屏信息)
onDragStart (sprite, pointer) (当前sprite, 当前手指触屏信息)
onDragStop (sprite, pointer) (当前sprite, 当前手指触屏信息)
onDragUpdate (sprite, pointer, dragX, dragY, snapPoint, fromStart) (当前sprite, 当前手指触屏信息, 拖拽点x坐标, 拖拽点y坐标, 吸附点坐标, 是否第一次DragUpdate)

举例,我们给艾斯添加点击事件:

1
2
hero.inputEnabled = true;
hero.events.onInputDown.add(clickedHero, this);
1
2
3
4
function clickedHero(sprite, pointer){
console.log(sprite)
console.log(pointer)
}

我们给艾斯添加拖拽事件:enableDrag中的参数true代表使物体中心与手指触屏点重合,false代表不重合。

1
2
3
4
5
6
7
hero.inputEnabled = true;
hero.input.enableDrag(false);

// Drag events
hero.events.onDragStart.add(dragStart);
hero.events.onDragUpdate.add(dragUpdate);
hero.events.onDragStop.add(dragStop);
1
2
3
4
5
function dragStart(sprite, pointer) {}
function dragUpdate(sprite, pointer, dragX, dragY, snapPoint, fromStart) {

}
function dragStop(sprite, pointer) {}

在drag事件里面onDragUpdate比较复杂,参数多达6个,其中有个涉及到非常强大的吸附功能的参数就是吸附点坐标snapPoint,该参数需要物体开启enableSnap吸附才能返回吸附点,吸附函数如下:

enableSnap(snapX, snapY, onDrag, onRelease, snapOffsetX, snapOffsetY)

参数 类型 是否必选 默认值 说明
snapX number 吸附单位宽度
snapY number 吸附单位高度
onDrag boolean true 拖拽的时候是否吸附
onRelease boolean false 拖拽释放的时候是否吸附
snapOffsetX number 0 吸附到吸附单位的左边距
snapOffsetY number 0 吸附到吸附单位的上边距
1
2
// 以64x64作为吸附单位,拖拽和释放都吸附
hero.input.enableSnap(64, 64, true, true);
1
2
// 以64x64作为吸附单位,但只有在释放的时候才会吸附
hero.input.enableSnap(64, 64, false, true);

扫描二维码,分别拖拽箱子和艾斯,体验两种吸附的区别:

拼图游戏中,常用这种吸附功能。

第二类:键盘事件

方向盘cursors事件监听

如果游戏只需要用到方向键和三个常用特殊按键Ctrl/,Shift/Alt,那么可以最简单的创建方向盘对象,在create中创建方向键对象:

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

在update中实时监测方向键按下的情况,每一个方向键下面都带3个特殊按键的监测,分别是Ctrl(ctrlKey),Shift(shiftKey),Alt(altKey)。触发组合按键效果从操作习惯上约定,在特殊按键先按下的前提下才能生效。

注意:如下代码中上下键和左右键分两条if语句和合成一条if语句是有区别的,前者可以四面八方,后者只能四个方向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (cursors.left.isDown) {
if (cursors.left.shiftKey) {
hero.x -= 3
} else {
hero.x -= 1
}
} else if (cursors.right.isDown) {
if (cursors.right.shiftKey) {
hero.x += 3
} else {
hero.x += 1
}
}

if (cursors.up.isDown) {
hero.y -= 1
} else if (cursors.down.isDown) {
hero.y += 1
}

键盘keyboard事件监听

如果游戏用到了键盘上非常用特殊按键,也可以监听整个键盘事件,监听某个按键按下代码如下,键盘下所有按键关键字都放在Phaser.Keyboard下,可自行打印查看

1
2
3
4
// update函数中监听
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
// do something...
}

鼠标mouse事件监听

鼠标最基本的四个按键是左键(leftButton)、中键(middleButton)、右键(rightButton)、滚轮(wheel)、可能有前进键(forwardButton)、后退键(backButton)。

在update函数中我们可以实时监测除滚轮滑动外的事件:

1
2
3
4
// 左键按下
if (game.input.mousePointer.middleButton.isDown) {
console.log('mouse middle button clicked!')
}

而滚轮事件要在create函数中监听滚动返回mouseWheelCallback:

1
2
// 在create函数中:
game.input.mouse.mouseWheelCallback = mouseWheel;
1
2
3
function mouseWheel(event) {
console.log(game.input.mouse.wheelDelta);
}

game.input.mouse.wheelDelta,返回1表示滚轮下滚,返回-1表示滚轮上滚。

但经测试发现,除滚轮外的其他鼠标按键事件存在兼容性问题,需谨慎使用,不出现区分三种按键的游戏形式,尽量使用鼠标按下事件统一代替。

掌握这两类基础的交互事件外,基本可以满足大多数的游戏需要。另外Phaser还有一些比较特殊的操作方式,最典型的就是操纵杆joystick,需要另外引入joystick插件,有兴趣的可以自行研究。官方demo

Homework

在上一节课作业的基础:

1、给box添加拖拽功能,并只在释放的时候吸附,吸附单位为64x64;

2、实现点击艾斯,打印当前点击元素和触屏信息;

3、实现操作键盘,艾斯可以上下左右位移。