本文中phaser具体版本
phaser2:2.8.1
phaser3:3.17.0

一、实现效果
二、实现细节
三、项目总结
四、参考文档

一、实现效果



源码地址(phaser2&phaser3):https://github.com/jinglecjy/phaser-dadishu/
体验地址:https://jinglecjy.github.io/phaser-dadishu/ver-phaser2/dist/

二、实现细节

这个demo其实是之前学习phaser2的时候做的,现在用来改成phaser3,刚好可以接触一下新的API变动有多大。
按照游戏实现的逻辑顺序,下面捋一捋用到的Phaser3 API,同时也与Phaser2 API进行简单对比。

第一步:初始化游戏new Phaser.Game

初始化画布参数,包括画布宽高,渲染方式,并将其插入dom结构中。phaser3中用scenes替代了phaser2中的states,为了避免与state machines概念混淆。
游戏中的一个scene是一个独立的场景,拥有自己的独立资源,包括相机系统、显示列表、更新步骤、事件处理、物理系统等等。游戏一次只能执行一个scene,一个场景通过多个钩子函数来维护,包括init、preload、create、update等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
conf = {
width: 750,
height: 750/window.innerWidth*window.innerHeight,
type: Phaser.AUTO, // 渲染方法
parent: 'container', // 将包含游戏画布的dom元素
backgroundColor: '#f9c04c',
scale: {
mode: Phaser.Scale.FIT // 缩放模式,此处按比例调整画布大小,相当于contain
},
scene: { // 初始化场景,游戏最开始状态
init: function(){
// 当场景开始时第一个执行,可以用于初始化变量或重定向到其他场景
},
preload: function(){
// 第二个执行的函数,预加载游戏资源,不会在这里创建对象
},
create: function(){
// 当preload完成之后执行,preload的资源加载完成,可以在这里创建对象
},
update: function(){
// 画布更新,在游戏的每一帧都执行
},
// ...... 其他函数
}
}
game = new Phaser.Game(conf); // phaser 2:http://phaser.io/docs/2.6.2/Phaser.Game.html
game = new Phaser.Game(750, 750/window.innerWidth*window.innerHeight, Phaser.AUTO, 'container',
{ // 初始化场景,游戏最开始状态
init: function(){
// 当场景开始时第一个执行,可以用于初始化变量或重定向到其他场景
},
preload: function(){
// 第二个执行的函数,预加载游戏资源,不会在这里创建对象
},
create: function(){
// 当preload完成之后执行,preload的资源加载完成,可以在这里创建对象
},
update: function(){
// 画布更新,在游戏的每一帧都执行
},
// ...... 其他函数
})

第二步:预加载资源

预加载资源操作一般在preload函数中执行,这一部分的API,phaser2和phaser3基本一致,不过phaser3对游戏对象结构进行了修改,phaser2中是树状结构,游戏中所有对象都来自于根对象Phaser.Game,对象也拥有自己的子对象。phaser3中将这些对象拆解出来,游戏对象Phaser.Game不包含其他对象组,且对象组不具有任何的位置或者属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// phaser3: https://photonstorm.github.io/phaser3-docs/Phaser.Loader.LoaderPlugin.html
preload: function () {
console.log("start loading ...");
this.numbersJson = require('../json/numbers.json'); // loader挂载在Phaser.Scene下
this.load.image('bg', './img/holes-bg.png');
this.load.image('hamster', './img/hamster.png');
this.load.image('hammer', './img/hammer.png');
this.load.image('lightning', './img/lightning.png');
this.load.atlas('sprite_numbers', './img/numbers.png', this.numbersJson);
this.load.on('complete', loadProgress); function (loader, finishedNum) {
console.log(`${finishedNum}个资源加载完毕,可以开始游戏了!`);
$(".cjy_panel .start_btn").click(function () {
// 移除开始界面
$(".cjy_panel").hide();
customGame.scene.start('play');
})
}
}
// phaser2: http://phaser.io/docs/2.6.2/Phaser.Loader.html
preload: function 大专栏  phaser2->3:来个打地鼠试水 () {
console.log("start loading ...");
this.numbersJson = require('../json/numbers.json');
console.log(window.customGame) // 这些属性在Phaser3中已被移除,需要通过初始化配置
window.customGame.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
window.customGame.stage.backgroundColor = '#f9c04c'; // loader挂载在Phaser.game下
window.customGame.load.image('bg', './img/holes-bg.png');
window.customGame.load.image('hamster', './img/hamster.png');
window.customGame.load.image('hammer', './img/hammer.png');
window.customGame.load.image('lightning', './img/lightning.png');
window.customGame.load.atlasJSONHash('sprite_numbers', './img/numbers.png', '', this.numbersJson);
window.customGame.load.onLoadComplete.add(loadProgress, this);
function () {
console.log('资源加载完毕,可以开始游戏啦!')
$(".cjy_panel .start_btn").click(function () {
console.log("开始游戏!");
// 移除开始界面
$(".cjy_panel").hide();
customGame.state.start('play');
})
}
}

第三步:创建对象

创建对象操作一般在create函数中执行,这一部分的API基本一致,差别与load相似,都是由于修改了整体数据结构导致的。

1
2
3
4
5
6
7
// phaser3: https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.GameObjectCreator.html
// 对象的创建
this.hammer = this.add.sprite(hammerx, hammery, 'hammer').setOrigin(0, 0.8); // phaser2: http://phaser.io/docs/2.6.2/Phaser.GameObjectFactory.html
this.hammer = customGame.add.sprite(hammerx, hammery, 'hammer');
this.hammer.anchor.setTo(0, 0.8);

第四步:动画

phaser2和phaser3都提供了内置tween动画供开发者使用,相比较于phaser2,phaser3中的tween动画配置更加灵活丰富,具体完整的配置项列表可以参照官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// phaser3: https://photonstorm.github.io/phaser3-docs/Phaser.Tweens.TweenManager.html
this.tweens.add({
targets: [this.hammer],
angle: 45,
duration: 50,
callbackScope: this,
ease: 'Linear'
}) // phaser2: http://phaser.io/docs/2.6.2/Phaser.Tween.html
var rotateTween = customGame.add.tween(this.hammer);
rotateTween.to({
angle: 45
}, 50, Phaser.Easing.Cubic.In, true);

第五步:交互行为

phaser本身没有dom概念,所有的交互都需要依赖phaser自身的API,通过Phaser.Input统一管理所有的input事件。当交互发生时,与之交互的Phaser.Game对象将向下分发事件,phaser3可以在scene/gameObject中监听该事件,不同的位置监听事件其作用域不同,优先级也不同,优先级较高的事件处理器可阻止向低优先级事件传递(stop propagation)。

1
2
3
4
5
6
7
// phaser3: https://photonstorm.github.io/phaser3-docs/Phaser.Input.Events.html
this.input.on('pointerdown', onTap, this);
function onTap(pointer,currentlyOver) { ... } // phaser2: http://phaser.io/docs/2.6.2/Phaser.Input.html
customGame.input.onTap.add(onTap, this);
function onTap(pointer, doubleTap) { ... }

第六步:计时器

1
2
3
4
5
6
7
8
9
10
11
// phaser3: https://photonstorm.github.io/phaser3-docs/Phaser.Time.TimerEvent.html
this.time.addEvent({
loop: true,
delay: 1000,
callback: timerFn,
callbackScope: this
}) // phaser2: http://phaser.io/docs/2.6.2/Phaser.Timer.html#loop
customGame.time.events.loop(Phaser.Timer.SECOND, this.timerFn, this); //利用时钟对象来重复产生管道
customGame.time.events.start();

三、项目总结

一些可以改进优化的细节:

  • 【前端】资源预加载与游戏过程应当在同一个scene中,之前没捋清楚逻辑,把这两个步骤拆开了
  • 【交互】疯狂点击页面会出现很多个小锤子,短时间内多次点击应该只响应一次
  • 【交互】打到地鼠时的反馈感加强,比如地鼠有晕眩动效/音效提示/+1效果等等
  • 【玩法】地鼠出现时间越来越快
  • 【玩法】主角多样化,除了地鼠还可以有炸弹/手拿礼物的地鼠/其他道具,分数不同

phaser2上手较快,API简单,官方文档示例比较丰富,值得继续探索,后续会试水一下物理引擎。phaser3是正在开发的版本,相较于phaser2 API变化较多,文档完善度不够,基本上是查源码猜API。试水过程可以感受到phaser3对API设计重新考量,比如用对象来代替原有的基本数据类型作为函数参数,可读性和灵活性更佳。另外,phaser3增强了camera的功能,新增了对Matter.js物理引擎的支持,对2D骨骼动画的支持等等,此处不进行赘述,详细的可以查看phaser官网的具体公告,或者是参考文章 全新Phaser3游戏引擎特性一览(来自凹凸实验室)
关于自学:个人觉得phaser API的学习方法最直观的是在控制台打印一下,尤其是对于初学者来说,对于其中的结构没有清晰的认识,直接看文档容易混乱,具体使用也可以参照官方示例
彩虹屁结束之后,不得不说,如果是项目实际使用,建议还是使用稳定版本phaser2,简单的小游戏还是够用的。

六、参考文档

  1. Phaser官网:http://phaser.io/
  2. Phaser2 API文档:http://phaser.io/docs/2.6.2/index
  3. Phaser3 API文档:https://photonstorm.github.io/phaser3-docs/
  4. Phaser3官方示例:https://labs.phaser.io/
  5. 全新Phaser3游戏引擎特性一览:https://aotu.io/notes/2018/12/23/phaser3/

phaser2->3:来个打地鼠试水的更多相关文章

  1. POJ 2502 - Subway Dijkstra堆优化试水

    做这道题的动机就是想练习一下堆的应用,顺便补一下好久没看的图论算法. Dijkstra算法概述 //从0出发的单源最短路 dis[][] = {INF} ReadMap(dis); for i = 0 ...

  2. 大众点评试水O2O新模式:实体店试穿,扫描二维码付款 现场取货

    在餐饮美食行业取得不错的成绩之后,大众点评将触角延伸到了线下的传统商铺,开始涉足线下商品的 O2O 团购.和传统的线上下单,线下消费的 O2O 模式不同.大众点评的 O2O 团购用户,可在店内试穿后通 ...

  3. Json.Net6.0入门学习试水篇

    原文:Json.Net6.0入门学习试水篇 前言 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.简单地说,JSON 可以将 JavaScript 对象中 ...

  4. 第一回:Scrapy的试水

    前言:今天算是见到Scrapy的第二天,之前只是偶尔查了查,对于这个框架的各种解释,我-----都-----看------不------懂----,没办法,见面就是刚. 目的:如题,试水 目标:< ...

  5. CSharpGL(49)试水OpenGL软实现

    CSharpGL(49)试水OpenGL软实现 CSharpGL迎来了第49篇.本篇内容是用C#编写一个OpenGL的软实现.暂且将其命名为SoftGL. 目前已经实现了由Vertex Shader和 ...

  6. UITableView(自定义cell)试水心得

    初次试水自定义cell的UITableView 实现目标      最终实现结果   界面复原度:98% 未能完全复刻的地方:下半部分的tableview与头部的控件间距上的误差 原因:在做table ...

  7. 微博试水卖车社交电商怎样令4S“颤抖”?

        微博对社交电商的探索一直在深入,年初.微博上线了"支付"产品.从而使社交产业链实现了闭环,随后,微博又尝试售卖多种商品,不断扩大移动电商的试水范围,近期微博大规模汽车销售收 ...

  8. CentOS7 docker试水

    CentOS 7.0,无外网直接访问权限,有一台代理服务器. 首先安装docker-ce,参考http://blog.51cto.com/aaronsa/2056882 除非特殊说明,以下操作都用ro ...

  9. 【试水CAS-4.0.3】第07节_CASclient配置单点登录

    完整版见https://jadyer.github.io/2015/07/26/sso-cas-client-login/ 本文源代码下载:http://download.csdn.net/detai ...

随机推荐

  1. Junit单元测试、反射、注解

    Junit单元测试: * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码的.关注程序具体的执行流程. * Junit使用:白盒测试 * 步 ...

  2. maven中scope属性有哪些

    compile,缺省值,适用于所有阶段,会随着项目一起发布. provided,类似compile,期望JDK.容器或使用者会提供这个依赖.如servlet.jar. runtime,只在运行时使用, ...

  3. 14 微服务电商【黑马乐优商城】:day03-springcloud(Hystix,Feign)

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...

  4. Debian8.8同步时间

    1.安装ntpdate 2.设置当前年月   如:sudo date -s 2017-05-18 3.同步:sudo ntpdate /usr/sbin/ntpdate time.nist.gov

  5. [概率DP]相逢是温厚

    题意 有\(n\)场比赛,他每次等概率地选择一场,选择的比赛可能有没ac过的题,他一定会ac这次比赛中的某一道,并说我好菜啊.如果全ac过了,也会说我好菜啊.求期望说多少次我好菜啊. 注意题目中每场题 ...

  6. 计量经济与时间序列_ADF单位根检验步骤

    1 ADF检验也叫扩展的迪克富勒检验,主要作用是检测序列的平稳性,也是最常用检测序列平稳性的检验方法. 2 何为:平稳性?单位根?(略),见这部分随便的其他内容有讲解.是建模对数据的先决条件. 3 A ...

  7. ionic3 发布订阅者模式实现

    在ionic3 中实现订阅发布模式,需要用到Events. Events下面有三个方法 events.subscribe()  订阅 events.publish()  发布 events.unsub ...

  8. day08-内置函数和匿名函数

    1. 1)网络编程只能是二进制.2)照片和视频也是以二进制储存. 3)html网页爬取到的也是二进制编码. 2. 非常重要的4个内置函数:zip ,filter,map,sorted 1)zip: 例 ...

  9. POJ3276 Face The Right Way 开关问题

    ①每个K从最左边进行考虑 ②f[i]=[i,i+k-1]是否进行反转:1代表是,0代表否 ③∑ (i)(i=i+1-K+1) f[j]=∑ (i-1)(i=i-K+1) f[j]+f[i]-f[i-K ...

  10. sql查询语句解析过程--根据网络资料整理

    查询语句: (8)SELECT(9)DISTINCT(11)<TopNum> <selectlist> (1)FROM<left_table> (3)<joi ...