iceBucketChallenge
README | 中文
项目介绍
iceBucketChallenge:类似打地鼠类的冰桶挑战游戏(ps:素材均来自网络),基于egret白鹭游戏引擎开发,主要分为2个大页面,用EUI build相应的页面,用tween来控制动画,ts控制交互。
项目演示
项目功能结构
项目运行
$ egret build xxx(项目名)
$ egret startserver xxx(项目名) -a
项目搭建教程
该游戏比较简单,就随便记录一下大概步骤
1.EUI build页面
游戏最直观呈现的就是页面,egret给我们提供了一个wing的编辑器(个人感觉和vscode超级像),wing方便我们对图片和组件进行拖拽和build,具体就不再赘述这里的教程,参考官网即可快速入门 —— EUI入门手册
记住要点:拖拖拖点点点即可
示例图:
2.tween制作动画
这里主要使用tween缓动来控制人头上下出没的动画(简单来说:控制‘地鼠’的出没)
mask遮罩
在做人头出没的时候,用到遮罩
img.mask = g.getChildAt(0);
为什么要这么使用?下面慢慢说。
什么是遮罩?
遮罩是游戏中非常常见的一个视觉处理手段。简单来说:所谓的遮罩就是指定一个显示对象哪些部分可以显示,哪些部分不可以显示。
推荐一个直观的实践办法
光看文字,应该会觉得一头雾水,可以尝试在代码中这么玩一下:改变rect的高度和宽度,观察这时候人头出没时的效果
,这样可以最直观的了解到遮罩的意思。
3.发布游戏
当整个游戏制作完成后,我们需要将它进行发布,这里只涉及H5方面发布。
一句命令行而已的事:
$ egret publish xxx(项目名)
打包成功后,会出现一个bin-release的文件夹
然后把我框出来的1903....这个文件夹里面的东西,拖到服务器上,然后对应访问,就可以啦。
敲黑板划重点
如果说,我们平时在自我测试环节,起一个本地服务,然后手机在同一个网络下访问本机ip地址就可以
这样应该会比较方便,简单介绍一下这个步骤:
简单的http服务
首先安装http-server模块。
$ npm i -g http-server
运行发布完成的包
$ cd bin-release/web/190311152632
$ ls
index.html js manifest.json resource
$ hs -p 8088
Starting up http-server, serving ./
Available on:
http://127.0.0.1:8088
http://192.168.1.100:8088
Hit CTRL-C to stop the server
最后一级文件夹名字其实是时间戳。
这样我们便可以在pc浏览器或者手机浏览器中查看游戏了。
项目细究
踩过的小坑
在开发中,我因为1个小错误,导致进度卡壳了一会儿,这里记录一下,以防下次重犯:
- eui中的布局
egret核心显示类
需要重新梳理一下这些类,以便下次写的时候,有点混
类 | 描述 |
---|---|
DisplObject | 显示对象基类,所有显示对象均继承自此类 |
DisplObjectContainer | 显示对象容器接口,所有显示对象容器均实现此接口 |
Bitmap | 位图,用来显示图片 |
Shape | 用来显示矢量图,可以用里面的方法绘制矢量图形 |
TextField | 文本类 |
BitmapText | 位图文本类 |
Sprite | 带有矢量绘制功能的显示容器 |
Stage | 舞台类 |
这里面的startscene,使用继承sprite,而没用displaObjeContainer,在这里简单列出它们之间的继承关系:
egret.Sprite -> egret.DisplayObjectContainer -> egret.DisplayObject
同时,提一点:shape与sprite的diff:
- shape:显示对象,一般用于绘制图形
- sprite:显示容器,在此基础上可以添加子容器 + 显示对象,一般用于create可以装载content的游戏层或者游戏对象
http://blog.sina.com.cn/s/blog_6b80d2ca0102vjx4.html
egret中事件处理
我们在游戏中涉及到按钮的一些交互效果,比如:点击开始游戏,进入游戏页面;点击Rank icon,弹出rank的弹框。
以上这些都会涉及倒egret的事件处理,我先简单罗列事件处理的一个基本流程:
- step1: 注册侦听器listener
- step2:发送事件
- step3:侦听事件
- step4:移除事件侦听器
这里我用startScene中点击开始游戏的事件处理,做一个简单事例:
startscene .ts:
// init fn
private init(){
...
// 注册listener
rank_btn.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.rank_btnCallback, this);
...
}
// start_btnCallback fn
private start_btnCallback(evt:egret.TouchEvent):void {
...
// 派发事件
let event:GameEvent = new GameEvent(GameEvent.GAME_GO);
this.dispatchEvent(event);
...
}
main.ts:
private createGameScene() {
....
//侦听事件
startScene.addEventListener(GameEvent.GAME_GO, this.go, this);
startScene.addEventListener(GameEvent.GAME_BLEED, this.startrank, this);
}
private go(){
// 手动回收侦听器
this.removeEventListener(GameEvent.GAME_GO, this.go, this);
this.removeChildren();
...
}
注意:这里存在一个问题:
在显示对象容器里的子显示对象上增加了事件侦听器(addEventListener),如果通过父级显示对象的removeChild移除了这个容器,那么有必要在egret.Event.REMOVED_FROM_STAGE事件里手动删除所有子对象注册的事件侦听器吗(removeEventListener)?还是说引擎会自动处理?
答案是:如果没有引用的话就会回收,但是为了保证一定回收最好手动移除,不然可能造成内存泄露
egret中的默认事件类型包括Focus(焦点)、Geolocation(定位)、HTTPS、IOError、Motion(手势)、Orientation(旋转与方向)、Progress、StageOrientation、Text、Timer、Touch
egret中的事件机制是一套比较标准的事件处理架构。
简单来说,数据的提供者只需要在意发出数据对象,以及确保数据对象是egret.event类或者子类的实例即可,这种数据对象,也就是事件event
。
下面梳理2个概念:
- event dispatcher:事件发送者
- event listener:事件侦听者
默认值写法:
bulles: boolean = false
file1:const
file2:boy
1.生成事件对象
let dateEvent: dataevent = new DateEvent(dateEvent.date)
2.发送请求时间
dispatchevent
file3:girl
getDate fn: evt:DateEvent
file4:main
项目源码
代码中写了很多注释,基本都能看懂就不再赘述啦~