在近期使用CocosCreator(以下简称CC)开发HTML5游戏的工作中,发现公司许多游戏都有着相同的元素,比如倒计时条、结算页面等等。在早期的开发中,我们并没有摸索到复用的办法,只能在不同的游戏项目中从头开始写。随着需求越来越多,重复造轮子肯定不是一个好办法,那么对于CC项目来说,能不能把这些可复用的游戏元素作为组件封装抽离出来呢?经过一番探索,终于找到了解决的办法。
什么是CC组件
以我们在手Q上的“太鼓达人”小游戏为例子,它的倒计时条和结算页面,在其他的小游戏里面也是存在的,仅仅是外观上有所不同,但当中的逻辑处理是一致的。这里的倒计时条和结算页面,都可以理解为组件。
两个组件的逻辑如下:
- 倒计时条可以设置游戏时间,在游戏时间内其填充长度不断缩减;倒计时条右侧会显示所剩时间;在倒计时结束后会执行回调动作。
- 结算页面可以设置等级分值,达到或超过具体的等级分值可以获得星星;星星会按照动画逻辑展示;下方会从0开始对分数进行结算;结算完成后会执行回调动作。
通过这个例子不难理解,一个所谓的CC组件,就是一个包含了逻辑、图片、动画、音频等不同资源的游戏节点。在CC里面,一个节点它长这个样子:
可以看到,编辑器左侧定义了它的结构,中间是它的具体体现,右侧是它的相关属性。
如果我想在其他的项目中复用这个已经定义好的节点,应该怎么做呢?
转化成预制资源
在CC里面,预制资源是非常重要部分,可以把它理解为节点的模板。如果要将一个已经做好的节点抽象成组件,把它变成预制资源会是一个最合适的办法。
当我们在CC编辑器定义好一个节点,给它关联逻辑脚本、静态资源以后,直接把它从编辑器的层级管理器
拖到资源管理器
就可以把它转化为预制资源。但是由于CC内资源的关联是基于资源路径的,所以在抽象一个CC组件出来之前,我们有必要把该组件所有用到的资源都放在一起,以方便以后的复用,否则很可能在其他工程复用的时候会报找不到资源的错误。
新建一个CC工程,清空assets/
目录,然后在里面建立Components/
目录,作为我们存放CC组件的目录。以游戏结果页Result
为例,按照如下目录结构进行初始化,放入必要的资源:
.
├── Resources # 组件静态资源
│ ├── score.png
│ └── star.png
└── Result.ts # 组件脚本
然后在CC编辑器中,通过拖拽的方式给子节点添加图片,最后绑上逻辑脚本Result.ts
:
完成以后,把它拖到资源管理器的assets/Components/Result
目录下成为一个预制资源。
为了让其他用户能够方便地使用这个组件,所以可以为其添加一个demo,里面放置着仅有这个组件的场景和场景所需的脚本。当用户需要了解这个组件时,只需要预览Demo场景即可,而组件的一些方法也可以在Demo脚本中看到。最终目录结构如下:
.
├── Demo # 组件使用Demo
│ ├── Result.fire
│ └── ResultDemo.ts
├── Resources # 组件静态资源
│ ├── score.png
│ └── star.png
├── Result.prefab # 组件节点
└── Result.ts # 组件脚本
如何使用
简单来说,只要把组件库工程的Components/
目录整个复制到目标工程的assets/
目录下,然后把预制资源节点拖到层级管理器去就可以了。当然这样的手动操作不够优雅,所以我们可以借助shell脚本来帮我们简化这个步骤。
在目标工程的根目录下新建一个download.sh
脚本,写入如下内容:
#!/bin/bash
# 先清理一下
echo "Clearing workbench..."
rm -rf ./cocos-components
rm -rf ./assets/Components
# 直接clone组件库工程,取出Components目录,然后删掉组件库工程
echo "Cloning project..."
git clone http://git.xxx.com/cocos-components.git
cp -r ./cocos-components/assets/Components ./assets
rm -rf ./cocos-components
echo "Done!"
以后只需要执行./download.sh
就可以下载到最新的组件库了,非常方便。
组件设计规范
组件的设计应该遵循“黑盒子”原则,它不依赖于其他组件,也不影响其他组件。组件的状态由组件自身保存,如果需要改变组件的状态或行为,应该通过它向外暴露可配置项或接口(通过Cocos Creator的属性检查器修改或者引入组件的脚本实例)。
以Progress
组件为例。
它向外提供了gameDuration
配置项,定义倒计时的时长。另外它也提供了一个setTimeoutCallback()
的方法,用于定义当倒计时结束后的行为。前者可以直接在Cocos Creator的属性检查器里面修改,后者则需要在游戏脚本中通过代码的方式去使用:
import Progress from '../Components/Progress/Progress'
@ccclass
export default class Game extends cc.Component {
start () {
Progress.instance.setTimeoutCallback(() => {
console.log('Test progress timeout callback!')
})
}
}
在定义组件的脚本的时候,要注意为该脚本添加一个名为instance
的静态属性,以供脚本之间的调用:
export default class Progress extends cc.Component {
static instance = null
constructor () {
super()
Progress.instance = this
}
}
此外,搭建组件库必须注意命名规范,这样不管是开发方还是调用方,都可以省去不少的烦恼。
后续优化
CC组件库工程也是一个完整的CC游戏,我们可以在这个游戏里面添加组件菜单,点击菜单就可以加载对应组件的场景,实时预览组件的效果。这个想法也会在之后付诸实践,争取早日开源出来。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。