上一节咱们介绍了加载场景,并利用加载好的资源,丰富了开始界面。如今点击屏幕后还是一片黑暗,那么,这一节咱们就来完成游戏最核心的场景——play。咱们要作的是一个接苹果的游戏,为此咱们会加入物理引擎,会使用一些过渡动画以及监听触摸事件等等。html
几乎每个游戏框架都必须具有一个甚至多个物理引擎供开发使用,使用物理引擎能够实现例如碰撞、加减速运动、摩擦力等效果。Phaser很是人性化,提供了3个物理引擎供开发者使用,每一个引擎各有本身的特色。下面来简单介绍一下:html5
最简单快速的物理引擎,由于只支持AABB式的碰撞,计算速度最快,实现简单的物理碰撞、接触、重力等效果最佳。web
关于AABB下面有几个连接可让你去理解,全称是Axis-Aligned Bounding Box
,直译就是轴对称盒
。例如一张星星的图片,尽管边上不少透明的部分,但若是使用AABB来计算碰撞的话,则会用一个矩形将星星框住,这样计算起来很是方便,但精度就比较低。如此一来咱们也能够想到,用Arcade构建的body是不能够发生形变的。算法
相关概念:segmentfault
若是说Arcade是小而精,P2引擎则是大而全了。各类物理模型都可实现,诸如多边形、弹簧、摩擦力、碰撞物体的材质、反弹系数等等均可以实现。尽管在性能上有必定消耗,毕竟要作更多复杂的运算,但为了效果,咱们也很经常使用P2,做者引进P2也是因为它的全面。框架
至于Ninja,则是比较专一精确的多种模式的碰撞检测。例如凹凸面的碰撞、平面和球的碰撞等等。日常比较少用,有兴趣的能够查看官方示例,另外,做者给出引进Ninja的理由是:dom
It's a really nice little physics system, supporting AABB and Circle vs. Tile collision, with lots of defs for sloping, convex and concave tile types. But that's all it does, it's not trying to be anything more really.
Stack Exchange - Game Development上关于Phaser三个引擎的介绍
Difference between Arcade, P2 and Ninja physics in PhaserPhaser做者写的,关于物理引擎的介绍:
Explaining Phaser 2's multiple physics systems
咦?为何没有上面没有提到Box2D?很遗憾,这个引擎是收费的,40刀,若是没有特别大的需求,估计也用不上。
添加背景
添加主角
添加分数
播放背景音乐
背景音乐的使用:
// 建立背景音乐实例 var bgMusic = game.add.audio('bgMusic'); // 循环播放 bgMusic.loopFull();
注意:
场景的布置和开始场景差很少,在开始场景中咱们添加了背景音乐。会有人问,为何不进入游戏就自动播放,是由于移动端的浏览器,必需要用户操做才能播放音频。
Safari HTML5 Audio and Video Guide
Warning: To prevent unsolicited downloads over cellular networks at the user’s expense, embedded media cannot be played automatically in Safari on iOS—the user always initiates playback.
另外可参考:
segmentfault上的讨论:HTML5的audio标签设置了autoplay属性在手机端出现的问题
示例代码:https://jsfiddle.net/Vincent_...
监听滑动事件
移动主角位置
主要使用的就是input的addMoveCallback方法:
// 监听滑动事件 game.input.addMoveCallback(function(pointer, x, y, isTap) { if (!isTap) man.x = x; });
第四个参数很是有用,能够判断是否为点击事件,若是是点击就不移动主角。
示例代码:https://jsfiddle.net/Vincent_...
很快你就会发觉在PC上主角一直跟着鼠标移动,根本没法停下来!
其实缘由也很简单,在PC端,Phaser的move事件对应的是mousemove
;在移动端,对应的是touchmove
。这两个事件有什么区别?主要区别就是touchmove必须手指触摸屏幕并滑动才会触发,而mousemove则不须要点住鼠标,只须要移动鼠标就会触发。
因而,咱们来修改一下代码:
// 是否正在触摸 var touching = false; // 监听按下事件 game.input.onDown.add(function() { touching = true; }); // 监听离开事件 game.input.onUp.add(function() { touching = false; }); // 监听滑动事件 game.input.addMoveCallback(function(pointer, x, y, isTap) { if (!isTap && touching) man.x = x; });
Good!加入了触摸标记之后,咱们监听了按下和离开事件,在PC端和移动端的表现一致了!
示例代码:https://jsfiddle.net/Vincent_...
细心的你多测试了几下,这时候发现了一个很是诡异的状况,当开始点击的时候,不是点在主角身上,主角就会瞬移过去!不难理解,由于咱们是直接设置主角的x坐标,等于触摸位置的x坐标的。若是开始时x坐标不在主角身上,就会在一瞬间移动到手指的位置。
因而,咱们又来修改一下代码,很是简单的一个方法:
// 监听按下事件 game.input.onDown.add(function(pointer) { // 要判断是否点住主角,避免瞬移 if (Math.abs(pointer.x - man.x) < man.width / 2) touching = true; });
上述代码的意思就是,开始触摸的位置必须在主角的最左边到最右边的x坐标范围内,才算做开始触摸,不然不算。
Excellent!如今能够为所欲为地操控你的主角了!
示例代码:https://jsfiddle.net/Vincent_...
这里用到了Phaser的group,实际上能够理解成是一个数组,只不过更形象,组的经常使用方法:
add/addChild/addChildAt - 建立成员
countDead/countLiving - 统计成员
forEach/forEachAlive/forEachDead - 遍历成员
remove/removeAll/removeChildAt - 删除成员
create - 建立成员
bringToTop - 整个组的元素的图层提到最上层
另外组自己也有x,y等属性,也就是说,整个组的成员均可以根据组的偏移值而一块儿偏移!另外组还提供了不少丰富的方法,活用组能够达到事半功倍的效果。
// 添加苹果组 var apples = game.add.group(); var green = apples.create(50, 0, 'green'); var red = apples.create(150, 0, 'red'); var yellow = apples.create(250, 0, 'yellow');
示例代码:https://jsfiddle.net/Vincent_...
上面咱们看到有三种苹果,那么下面咱们来实现:每隔一段时间,随机建立三种苹果中的一种,而且摆放到不一样的位置。
为此咱们用到Phaser的timer,用于建立定时任务。会有人问为何不用setInterval,setTimeout这些,是由于Phaser只要焦点离开了页面,就会自动暂停游戏,包括定时任务也会暂停,而setInterval和setTimeout则不会。
通常会用到add
和loop
两个方法,分别对应setTimeout和setInterval:
咱们修改一下代码:
// 添加苹果组 var apples = game.add.group(); // 苹果类型 var appleTypes = ['green', 'red', 'yellow']; var appleTimer = game.time.create(true); appleTimer.loop(1000, function() { var x = Math.random() * game.world.width; var y = Math.random() * game.world.height; var type = appleTypes[Math.floor(Math.random() * appleTypes.length)]; apples.create(x, y, type); }); appleTimer.start();
如今每隔1秒就会在屏幕随机位置出现一个苹果了,并且种类是随机的。
示例代码:https://jsfiddle.net/Vincent_...
这里就要使用到物理引擎了,考虑到接苹果的游戏对碰撞精度要求不是很高,咱们选择使用Arcade,也就是Phaser默认的物理引擎。
关键代码:
// 开启物理引擎 game.physics.startSystem(Phaser.Physics.Arcade); game.physics.arcade.gravity.y = 300;
// 设置苹果加入物理运动 game.physics.enable(apple);
因而,咱们继续修改上面的代码:
// 添加苹果组 var apples = game.add.group(); // 苹果类型 var appleTypes = ['green', 'red', 'yellow']; var appleTimer = game.time.create(true); appleTimer.loop(1000, function() { var x = Math.random() * game.world.width; var type = appleTypes[Math.floor(Math.random() * appleTypes.length)]; var apple = apples.create(x, 0, type); // 设置苹果大小 var appleImg = game.cache.getImage(type); apple.width = game.world.width / 8; apple.height = apple.width / appleImg.width * appleImg.height; // 设置苹果加入物理运动 game.physics.enable(apple); }); appleTimer.start(); // 开启物理引擎 game.physics.startSystem(Phaser.Physics.Arcade); game.physics.arcade.gravity.y = 300;
Perfect!如今满天苹果都会有了重力,加速掉向地上了。
示例代码:https://jsfiddle.net/Vincent_...
这一节内容比较多,咱们首先布置了游戏场景,加入了背景音乐。而后实现了对主角的操做,最后实现了苹果的随机掉落。通过这一节,万事俱备只欠东风,下一节咱们就来完成这个游戏的剩余逻辑,好比接苹果加分,接到炸弹或苹果掉到地上游戏结束,还有加入更丰富的音效。
游戏截图: