# 文档说明 **Repository Path**: Mkeyframework/document-description ## Basic Information - **Project Name**: 文档说明 - **Description**: No description available - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-16 - **Last Updated**: 2021-06-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 框架说明 目录结构 - modules:bundle模块文件夹 - xxx:需要配置为bundle - audio: 音乐 - prefabs:预制体(必须要有) - texture:图片 - xxx - resources:动态加载资源文件夹,这个文件夹下面的资源不会被自动卸载,慎用 - scripts:脚本资源文件夹 - scene:场景资源文件夹 每个模块(游戏)必须在modules下面单独**创建一个文件夹,并且配置为bundle**。 每个模块(游戏)必须创建一个场景,并且在对应模块文件夹/prefabs下面创**建同名预制体对象**,切换场景的时候会默认初始化此预制体对象。 场景里面至少需要Canvas->Camera两个节点。 # scene 在创建的场景资源文件上单击鼠标右键,选择**创建->创建SceneCtrl**会自动创建对应的场景控制脚本。 需要动态加载的资源请放在**scenePreload**函数里面的**urls**数组里面,每一个类型单独放一个数组,数组最后一个元素为类型,数组长度必须大于2。示例如下: ```javascript let urls = [ ['prefabs/Lobby', 'prefabs/TestUI', ResType.Prefab], ['texture/icon1', 'texture/icon2', 'texture/icon3', 'texture/icon4', 'texture/icon5', ResType.SpriteFrame], ['audio/bgm', ResType.AudioClip], ] ``` 当需要加载的资源加载完成之后,会调用场景控制脚本里面的**onSceneFinished**函数。 # UICtrl 在创建的UI预制体文件上单机鼠标右键,选择**创建->创建UICtrl**会自动创建对应的控制脚本。 生成的xxxAuto.ts会将所有节点中带有**&**符号的节点取出,在xxxCtrl.ts里面使用this.ui.xxx即可使用该节点。&后面如果跟上类型会返回该Component,没有跟上类型则默认取node。示例如下: ```javascript UI中命名:testBtn& 使用:this.ui.testBtn.on(SystemEvent.EventType.TOUCH_START, () => {}, this); UI中命名:testImg&Sprite 使用:this.ui.testImg.spriteFrame = _spriteFrame; ``` 选择创建Ctrl每次xxxAuto.ts会重新生成,而xxxCtrl.ts不会重新生成(如果要重新生成xxxCtrl.ts,请手动删除原来的脚本)。 如果需要打开动画,请在UI根节点下创建一个名叫**bg**的节点,框架检测到此节点会自动播放打开动画。 关闭页面请调用**this.dead = true**,框架会自动关闭界面并回收资源,请勿使用node.destory()。 加载/获取资源请使用this.loader,使用方法参考ResLoader.ts。 特殊方法: ```javascript // 收到了框架转发消息 onFrameMessage(key: CoreInnerMessageKey, msg: any) onNetMessage(object: MessageObject) ``` 框架转发过来的消息: onFrameMessage(key: CoreInnerMessageKey, msg: any) 根据收到的key判断是否是自己需要的消息,如果是就处理msg内容。 框架转发过来的网络消息: onNetMessage(object: MessageObject) MessageObject包含以下内容: - uid:socketID - mainID:主消息号 - subID:子消息号 - iRoomID:房间号 - properties:消息内容 使用前请判断是自己的socket,并且房间号 === 自己的房间号(非游戏模块消息不用处理这步),然后根据主消息号和子消息号处理对应逻辑,消息处理之后必须要 **return true;** # 常用方法 #### 消息分发 ```javascript /** * @description: 添加消息监听 * @param {string} eventName 消息名字 * @param {any} caller this * @param {Function} func 回调函数 * @return {*} */ addEventListener(eventName: string, caller: any, func: Function) /** * @description: 移除消息监听 * @param {string} eventName 消息名字 * @param {any} caller this * @param {Function} func 回调函数 * @return {*} */ removeEventListener(eventName: string, caller: any, func: Function) /** * @description: 分发消息 * @param {string} eventName 消息名字 * @param {any} data 消息内容 * @return {*} */ dispatchEvent(eventName: string, data: any) ``` #### 资源管理(Resloader) ``` /** * @description: 异步加载资源 * @param {string} url 资源地址 * @param {ResType} type 资源类型 * @return {*} */ async loadResAsync(url : string,type : ResType) : Promise /** * @description: 加载资源 * @param {string} url 资源地址 * @param {ResType} type 资源类型 * @param {ResCallback} callback 回调函数 * @return {*} */ loadRes(url: string, type: ResType, callback: ResCallback) /** * @description: 批量加载资源 * @param {Array} list 资源地址列表(规则见Scene) * @param {Function} complete 完成回调 * @param {function} func 加载进度回调 * @return {*} */ loadArrayRes(list: Array>, complete: Function, func: (err: string, process: number) => void) /** * @description: 获取资源 * @param {string} url 资源地址 * @param {ResType} type 资源类型 * @return {*} */ getRes(url: string, type: ResType) /** * @description: 清理资源 * @param {string} url 资源地址 * @param {ResType} type 资源类型 * @return {*} */ releaseRes(url: string, type: ResType) /** * @description: 清理所有资源 * @param {*} * @return {*} */ release() ``` #### 发送框架消息 ``` // 发送框架消息, 会在每个Ctrl中的onFrameMessage方法收到 App.getInstance().sendFrameMessage(key, data); key需要在Define.ts -> CoreInnerMessageKey中定义 ``` #### 其他方法 见Common.ts #### 发送网络消息 网络消息的类型,消息结构定义在frame->protos->Protos.ts中,如果里面没有定义你自己的模块,就在后面加入自己的定义,请根据已经定义的格式来定义自己的消息,并写上说明。 如果你已经定义好了自己的消息结构,那么就翻到frame->core->framework文件夹下吧,这里已经存在了很多的框架用来发送或者接受一些网络消息。举例说明:FrameLobby.ts->大厅通用消息的处理。例如服务器主动推送过来的一些通用消息,比如背包,个人属性等内容。如果你需要向服务器发送某个消息,也请尽量书写在对应的框架中。然后通过FrameLobby.instance.sendxxx(你的参数)来发送。请参考以下代码: ``` /** * 发送给服务器获取比赛信息的消息 * @param iKindID * @param matchType */ public sendMessageEnterGameMatchInfo(iKindID : number,matchType : MatchType){ let data = new Map(); data.set('iKindID',iKindID); data.set('cbMatchType',matchType); let subID = LobbyMsg.enLobbySubSubPara.LOBBY_CS_ENTER_GAMEKIND_MATCH_INFO_SUB_CMD; let object = MessageObject.Create(this.clientType,this.mainID,subID,0,data); log('发送获取游戏比赛信息的消息:'+iKindID + ','+matchType); ClientManager.instance.sendMessage(object); } ``` ### MessageObject 1.创建一个可以发送给服务器的MessageObject,需要使用以下方法: ``` /** * 创建一个发送给服务器的消息 * @param uid 哪个socket执行发送任务 * @param mainID 主消息号 * @param subID 子消息号 * @param iRoomID 房间ID,没有则为0 * @param properties 你需要发送的数据,Map类型 * @returns new MessageObject */ public static Create(uid:ClientType,mainID:JSonMsgMainPara,subID:number,iRoomID:number = 0,properties? : Map) ``` properties为你需要发送给服务器的数据,请参考上一节中发送网络消息中的生成方式。具体内容由服务器定义,需要你定义到Proto.ts中。 2.当你收到一个服务器消息时,你可以从MessageObject对象中拿出以下数据: ``` /**执行发送或者收到消息的Socket */ uid! : ClientType; /**主消息号 */ mainID! : JSonMsgMainPara; /**子消息号 */ subID! : number; /**房间号 */ iRoomID! : number; /**所有的属性*/ properties! : Map; ``` 你可以根据mainID和subID来判断是否是你需要用到的消息。如果是,并且你处理了这个消息,请返回true。你可以返回false来保证其他框架或者界面收到这条消息。 如果你希望从网络消息中拿到对应的数据,请使用: ``` messageObject.get(key:string) ``` 它可能会undefined,null,或者其他你想要的东西,请做判断,或者根据服务器的要求来处理。 ### 发送消息 当你装好自己的MessaeObject以后,你需要调用: ``` ClientManager.instance.sendMessage(object); ``` 来发送它。服务器的链接已经由框架做了处理,目前还没有处理断线重连等操作,如果发现断线,请重启。 ### 关于异步加载资源 在界面里,很多时候需要动态替换图片等。我们不可能一次性考虑到所有用到的资源,这个时候你可以使用异步加载,请使用以下代码: ``` let res = await this.loader.loadResAsync('texture/baoming/bmjm_imgf_tzs',ResType.SpriteFrame); ``` 其中res可能为null或者ResItem,如果不为null,你将通过: ``` let youWant = res.getRes(); ``` 来获取自己想要的东西,例如上面代码为获取一个SpriteFrame类型的资源来替换掉某张图片的内容。 ### 关于异步加载界面 你可以使用以下方法来异步加载一个ui界面: ``` /** * @description: 实例化一个对象 * @param {string} uiName UI名字 * @param {ModuleID} module 所属模块 * @param {zOrder} order 所属层级 * @param {Boolean} isAddUImanager 是否进入UI管理 * @return {*} */ public static async InstantiateAsync(uiName: string, module = ModuleID.COMMON, order = zOrder.ui, isAddUImanager = true) ``` 请使用await等待加载完毕。会返回一个node给你,这个node就是界面根节点。 ### 表格 每个表格生成的脚本里面有一个getRecordById方法可以根据id获取一行内容 ``` javascript /** * @description: 根据id获取一行内容 * @param {number} id * @return {*} */ getRecordById(id: number) ``` ### HTTP BASEURL 在Define里面 ``` /** * @description: POST * @param {string} url 接口名字 * @param {any} data 要发送的参数 * @param {function} call 结果回调 * @return {*} */ public static POST(url: string, data: any, call: (result: boolean, data: any) => void) ``` 使用方法 ``` Http.POST( '/article/show', { game_kind: 100, page_num: 1, client_id: 1111101 }, (result, data) => { log( result, data); }); ``` ### 帧动画 FrameAnimation ``` /** * @description: 创建一个序列帧动画,默认从0开始 * @param {string} url 除开帧索引的URL地址 * @param {number} end 结束帧 * @param {boolean} loop 是否循环,默认循环 * @param {Function} callback 回调函数, 默认无 * @param {ModuleID} moduleId 资源模块,默认Common * @param {boolean} autoPlay 是否自动播放,默认自动播放 * @param {number} duration 间隔,默认0.1s * @return {*} */ create(url:string, end:number, loop:boolean = true, callback:Function | null = null, moduleId:ModuleID = ModuleID.COMMON, autoPlay:boolean = true, duration:number = 0.1) ``` 在要使用的节点上挂载此脚本,然后调用create方法,示例如下: ``` let fa = this.ui.ani.node.addComponent( FrameAnimation); fa.create( 'texture/loading/jz_icon_', 9); ```