CocosCreator游戏开发框架(一):是什么 && 为什么

写在前面


从微信小游戏出生(2018年初)到现在,已经使用CocosCreator一年多了(之前做手游主要是cocos2d-x+lua),趁着这段时间有空,想着整理出一个基于CocosCreator游戏开发框架

这个框架主要是将我在开发过程中觉得好用的结构和模式、插件,以及在论坛上和博客上参考大神们的教程和想法(有些是直接拿来用),整合在一起的。一方面想提高开发效率,另一方面大家发现问题及时提出及时讨论,慢慢优化和改进。

框架工程是否跟游戏工程分开

在开始之前,因为这个问题纠结了好久。框架工程跟游戏工程分离,框架工程作为一个独立代码库,仅仅作为游戏工程的子模块,这样代码库可以统一管理。

我上个项目就是这样做的,但是你会发现,把框架模块单独拿出来给下一个项目复用,里面有一些耦合了游戏工程的代码。如果要每个成员在紧张的游戏开发过程中保持清醒,去保持框架模块的独立性,肯定是一个蛋疼的过程。

后来阅读了两篇文章(关于游戏设计模式的)之后,确定了该框架仅仅作为一个“纯净”的基础框架,每开一个新项目就拷贝过去,然后根据游戏的需求自己去调整。

两篇文章的链接在下面,有兴趣的可以了解下,不扯远了,准备进入正题!

【游戏设计模式】之一 序言:架构,性能与游戏

为什么在游戏开发中我不喜欢用MVC系列模式了




正文


目录细分和规划

如下图:
project_dir

  • animClip:存放动画文件(.anim)
  • font:存放字体文件
  • prefab:存放不需要动态加载的预制体
  • texture:存放用于贴图资源
  • texture/ui_common:存放公用的ui资源图集文件。
  • texture/ui_module:每个功能/模块单独用到的资源打包后的图集文件,比如main场景单独用到的打包一起,然后mian场景勾选自动释放资源,切换场景时就会自动释放没用的资源(前提是没有被其他的地方引用到)。
  • resources:存放一切需要用于动态加载(cc.load.loadRes)的资源

为什么有些资源放在resources里面,有些放到外面?

先看官网的解释:
resource_desc

总结一下:

1、resources文件夹中的资源可以跟它外部的其他资源,相互引用,所以放哪,问题不大。
2、只有放在resources文件夹的资源才能用cc.loader.loadRes动态加载。
3、构建时,resources文件夹中的所有资源连同它们关联依赖的resources文件夹外部的资源,都会被导出,并且项目中无用的资源将会在构建的过程中自动剔除。
4、resources文件夹的资源,会增大包体和settings.js的大小,JSON的自动合并策略也将受到影响,无法尽可能将零碎的JSON合并起来。




框架模块介绍


# 配置表模块

直接在现有的插件excel-killer的基础上做了小调整。

  • 相关目录(可以根据需求自己改动,相关文件:packages/excel-killer/panel/index.js)

plugins-excel/excel:存放excel表

plugins-excel/excel-ouput: 存放执行插件后的js输出文件

assets/script/data/config: 执行插件后,会自动把js文件从plugins-excel/excel-ouput拷贝到此目录


  • 如何使用
let cfgman = require('CfgMan');
console.log(cfgman[1].name);  // 小明



# 数据模块

  • 目录结构

IDataModel.ts:数据模块基类,主要功能:读取数据表、读写本地缓存数据、网络数据交互


  • 本地缓存数据接口

LoadStorage():将该模块的本地缓存数据读取到内存

Query(sKey: string, defaultValue: any = null):访问指定键名的值

Set(sKey: string, value: string | number):设置指定键名的值

Save():保存内存数据到缓存文件


  • 网络数据交互接口

sendProtocolMsg(msg):发送协议到服务端

registerListeners():注册网络监听事件,需要在getMessageListeners()定义需要监听的协议和方法

// AccountModel.ts
getMessageListeners() {
    return {
        // key:消息名,value:执行函数
        ['G2C_Login']: (msg) => { this.G2C_LoginSuccess(msg) },
    }
}



# UI模块

  • 目录结构

UIMng:UI管理器,用于打开、关闭UI

UIBase:UI界面基类,在这里可以定义一些通用方法,供子类调用或者继承

UIHelp:UI工具类,封装一系列UI相关的功能方法


  • 如何使用(配合自动化插件)

1、新建一个场景或者prefab

2、选中,然后到工具栏:扩展 -> auto-ui

  • export操作:将prefab节点树的结构自动导出到ts文件(目标文件夹:assets/script/data/autoui)
export default class auto_notice extends cc.Component {
	notice: cc.Node;
	background: cc.Node;
	title: cc.Node;
	content: cc.Node;
	btnClose: cc.Node;
	public static URL:string = "db://assets/resources/prefab/notice/notice.prefab"

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
		this.notice = this.node
		this.background = this.notice.getChildByName("background");
		this.title = this.notice.getChildByName("title");
		this.content = this.notice.getChildByName("content");
		this.btnClose = this.notice.getChildByName("btnClose");

	}
    start() {}

    // update (dt) {}
}

以后,你想要使用ui节点,就不需要各种getChildByName,或者搞个property在编辑器拖,所有的节点都导出在一个ts文件,然后作为一个组件添加到UI文件中,你只需要this.ui[节点名称]即可访问。

  • create-script操作:自动生成UI模板TS文件

3、将第2步create-script操作生成的UI脚本文件,在编辑器拖到prefab的根节点作为组件

4、UI的基本操作都封装在UIHelp中

UIHelp.ShowUI(UINotice);    // 打开ui
UIHelp.CloseUI(UINotice);   // 关闭ui
UIHelp.SetLabel(this.ui.title, '测试公告标题'); // 修改label节点文本

  • TODO

1、后续补充关闭UI清除相关无用资源

2.、目前的插件代码太乱,后面会尝试整理


  • 这里说一下对于UI的一些想法和见解

1、MVC模式。在框架中,每一个功能创建一个model类继承IDataModel,用于处理数据(配置表、本地数据、网络数据)。新建的prefab就是view,挂载在prefab的脚本组件就是controller,在controller实现功能逻辑。

2、很多人在用CocosCreator开发时,经常会往节点上挂脚本,往按钮上绑定事件(看过好多github上的项目都是这样)。但我个人是很不建议这样做的,正常的团队开发合作中都是分工明确的,比如你在编辑器中用按钮绑定事件,难道美术修改的时候还要关心代码么。而且任意节点都可以挂脚本,这个真的有点“灾难性”,我要找在这个脚本在哪里用到的时候还要去编辑器一个个找么(可能有其他快速查找的方法,我不知道的,请指点一下)。

3、所以我是比较支持,能用代码实现的尽量用代码实现,脚本文件能挂在根节点(方便找)的尽量挂在根节点。




# 网络模块

数据协议用Protobufjs,网络协议用WebSocket

CocosCreator使用protobufjs,具体教程点这里

  • 目录结构

ProtoBuf.ts:对protobufjs的修改和封装

ProtoLoader.ts:用于加载proto文件

Message.ts:proto msg的基类,并将msg缓存起来

ProtoMessage.ts:插件根据proto文件生成的代码

Socket.ts:WebSocket/WxSocket的具体实现

SocketDelegate.ts:Socket代理类,根据具体平台创建socket,提供统一回调接口供具体Socket调用

Network.ts:网络的逻辑实现,跟用户打交道,连接网络、关闭网络、登录流程、断网、重连都可以在这里处理




# 日志模块

  • 增加开关配置,每个大功能可以有一个开关,每个开发人员可以有一个开关,按需定义
export const LOG_TAG = {
    SOCKET: { desc: 'LOG_SOCKET', isOpen: true },
    TEST: { desc: 'LOG_TEST', isOpen: false },
}

  • 使用
Log.log(LOG_TAG.SOCKET, 'socketprint');
Log.warn('warn');
Log.error('error');

log方法第一个参数为开关分类,warn和error没有,因为我认为一般调试打印用log方法就够了,如果你用warn或error,肯定是需要所有人都知道的。




# 事件模块

EventMng.ts:事件分发我偷懒了,直接new一个cc.EventTarget来用,目前没有发现其他问题。




# 其他

GameController.ts:游戏全局控制类,比较杂的不知道放哪的可以看看能不能放这里

GameDataCenter.ts:管理游戏各个模块数据

global.d.ts:用于扩展基础模块

utils文件夹:用于存放一些工具类





最后


这篇文章讲的主要是框架有什么东西,有些地方为何要这么设计,githu工程点这里

看完有点懵逼?没关系,下篇文章是:CocosCreator游戏开发框架(二):怎么用

我会在框架的基础上快速开发一个简单的客户端登陆系统,帮助大家快速上手。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章