oops-framework框架 之 启动流程(三)

引擎: CocosCreator 3.8.0

环境: Mac

Gitee: oops-game-kit


回顾


上篇博客中我们通过 oops-game-kit 模版构建了基础的项目,另外讲解了下assets目录结构和游戏配置文件的基本使用相关,详情内容可参考:

oops-framework框架 之模版创建项目

oops-framework框架 是由作者dgflash编写,基于CocosCreator3.x而实现的开源框架,为了方便大家更好的学习和使用该框架,作者很贴心准备了各种学习资料:

dgflash-哔哩视频

dgflash CSDN博客

dgflash-cocos论坛

Gitee dgflash项目仓库

注:oops-framework框架QQ群: 628575875

本篇博客将介绍下框架的启动流程和注意事项项目,用于了解和学习框架。


项目启动流程


oops-game-kitoops-framework 的脚本目录下: script/game/initialize 中,此处的代码主要主要项目的启动,主要代码文件有:

  • Initalize.ts 游戏初始化入口,用于加载公共资源和热更新

  • bll/InitRes.ts 用于初始化公共资源,也就是项目启动前加载的必备资源

  • view/LoadingViewComp.ts 游戏动态资源的加载

InitRes.ts 在项目启动时加载的必备资源路径在bundle/common中,资源越少,黑屏时间越短。

LoadingViewComp.ts 动态加载的资源路径在bundle/game 中,资源越多,Loading页面显示时间越长。

注:Loading页面就相当于对资源的预加载,避免游戏启动成功后进入各种页面显示卡顿。

我们分别说明下这几处代码的主要逻辑相关;

Initalize.ts

@ecs.register('Initialize')
export class Initialize extends ecs.Entity {protected init() {// 初始化游戏公共资源this.add(InitResComp);}
}export class EcsInitializeSystem extends ecs.System {constructor() {super();this.add(new InitResSystem());}
}

项目采用的框架是 ECS 框架,也就是:Entity-Component-System(实体-组件-系统)框架。

更多内容可参考: ECS简介

这里我们只需要关注InitResComp即可,它会调用InitRes.ts进行项目启动是公共资源的初始化。


InitRes.ts

此处代码的主体是:

entityEnter(e: Initialize): void {var queue: AsyncQueue = new AsyncQueue();/** 加载远程资源配置 */this.loadBundle(queue);// 加载自定义资源this.loadCustom(queue);// 加载多语言包加载多语言包this.loadLanguage(queue);// 加载公共资源this.loadCommon(queue);// 加载游戏内容加载进度提示界面this.onComplete(queue, e);queue.play();
}

注:AsyncQueue是框架提供的一个异步队列处理,它支持将不同的任务添加到队列中按照顺序执行,在执行结束后通过next()执行下一个任务。

主要做的事情就如上面所说,我们看下大概的实现:

  • loadBundle() 加载Bundle资源配置
private loadBundle(queue: AsyncQueue) {queue.push(async (next: NextFunction, params: any, args: any) => {// 设置默认加载的外部资源包名oops.res.defaultBundleName = oops.config.game.bundleName;// 加载外部资源包if (oops.config.game.bundleEnable) {console.log("启用远程资源运行游戏");let bundleServer = oops.config.game.bundleServer;let bundleVersion = oops.config.game.bundleVersion;await oops.res.loadBundle(bundleServer, bundleVersion);}else {await oops.res.loadBundle(oops.config.game.bundleName);}next();});
}// 框架提供的loadBundle主要用于加载资源包,支持远程和本地加载

框架会根据 resources/config 中的Bundle的配置,设置默认的Bundle名字,后期的资源动态加载都会在该Bundle目录中获取资源。

会根据Bundle配置数据检测:是远程加载还是本地加载Bundle资源相关

注: 框架中的动态资源不要放在resources中,除非您修改此处的默认Bundle名,但这样以后可能会不灵活

注:loadBundle 主要用于加载资源包,框架的底层实现调用的是assetManager.loadBundle


  • loadCustom() 加载自定义资源
/** 加载自定义内容(可选) */
private loadCustom(queue: AsyncQueue) {queue.push(async (next: NextFunction, params: any, args: any) => {// 加载多语言对应字体oops.res.load("language/font/" + oops.language.current, next);});
}

框架此处主要通过oops.res.load 加载了当前多语言的字体文件相关,主要用于后续多语言配置的铺垫。

注: 如果项目没有多语言配置相关,可以注释此处该接口

  • loadLanguage() 加载多语言相关
/** 加载化语言包(可选) */
private loadLanguage(queue: AsyncQueue) {queue.push((next: NextFunction, params: any, args: any) => {// 设置默认语言let lan = oops.storage.get("language");if (lan == null) {lan = "zh";oops.storage.set("language", lan);}// 加载语言包资源oops.language.setLanguage(lan, next);});
}

该接口会根据本地存储数据获取项目的默认语言,并通过setLanguage下载指定语言的内容,主要有:

  1. 对应的文本Json表,由Language Excel表转换而成
  2. 对应的图片纹理资源
  3. 对应的Spine骨骼动画资源

注: 如果项目没有多语言配置相关,可以注释此处该接口

  • loadCommon() 加载公共资源相关
private loadCommon(queue: AsyncQueue) {queue.push((next: NextFunction, params: any, args: any) => {oops.res.loadDir("common", next);});
}

此处的代码主要用于加载bundle/common路径下的资源,资源越小,黑屏时间越短;这块代码是最影响用户体验的地方。

注: 切记,不要在bundle/common路径下放置太多的资源

最后在所有的接口执行完毕后,会通过 onComplete调用 LoadingViewComp 组件的启动,用于加载项目所需要的动态资源。


LoadingViewComp.ts

项目进度条的实现,用于实现加载资源,避免项目不同功能页面显示卡顿的问题。

这里主要做了两件事:

  1. 加载项目数据表相关
private loadCustom() {// 加载游戏本地JSON数据的多语言提示文本this.data.prompt = oops.language.getLangByID("loading_load_json");return new Promise(async (resolve, reject) => {await JsonUtil.loadAsync(TableChapterList.TableName);await JsonUtil.loadAsync(TableCheckPoint.TableName);resolve(null);});
}

注: 多语言的配置表在 InitRes.ts的方法 loadLanguage 中已经加载,此处不需要; InitRes也用于处理热更新相关,如果报错,不进行提前加载,文本内容会显示异常

  1. 加载资源相关
private loadGameRes() {// 加载初始游戏内容资源的多语言提示文本this.data.prompt = oops.language.getLangByID("loading_load_game");// 加载的资源目录、进度回调、完成回调oops.res.loadDir("game", this.onProgressCallback.bind(this), this.onCompleteCallback.bind(this));
}

资源的路径主要在bundle/game中,资源目录和资源数目越多,加载越慢;但此处一般情况下不太影响用户的体验。

在所有的资源加载完成后,会调用如下LoadingViewComp.ts如下接口:

reset(): void {// 获取用户信息的多语言提示文本this.data.prompt = oops.language.getLangByID("loading_load_player");// 进入自定义游戏内容界面oops.gui.open(UIID.GAME_LOGIN);// 关闭加载界面oops.gui.remove(UIID.Loading);
}

注: oops.gui 用于控制不同页面的显示和隐藏相关,这些内容后面再详细介绍。

到这里截止,这是项目启动时候所进行的主要流程。


框架启动流程


oops是以单场景的样式运行项目的,框架以插件的形式存在。

框架提供的日志管理、游戏配置、时间管理、音乐管理、UI管理、资源管理、多语言、网络等模块相关需要在项目启动时完成初始化,我们才能通过Oops.ts调用相对应的模块。

项目启动的场景文件在assets目录中,叫做: main.scene
请添加图片描述

项目的主要启动文件位于root节点下Main.ts文件

// Root负责初始化框架的模块相关
export class Main extends Root {start() {if (DEBUG) profiler.showStats();}protected run() {smc.initialize = ecs.getEntity<Initialize>(Initialize);}protected initGui() {oops.gui.init(UIConfigData);}protected initEcsSystem() {oops.ecs.add(new EcsInitializeSystem());}
}

该文件通过ECS框架主要做的事情:

  1. 获取 Initalize 实体用于调用Initialize.ts 对项目进行初始化
  2. 获取UIConfig 页面配置数据,完成对GUI Layer页面的初始化

继承的Root 主要用于完成框架各种模块的初始化。


Root.ts

它用于作为框架显示层的根结点相关,主要管理两种类型的节点:

  • game 游戏层节点,相当于游戏世界中的地图
  • gui 界面层节点,相当于游戏世界上方显示的UI层

主要逻辑代码:

  1. 通过CocosCreator的生命周期onLoad函数调用 resources/config.json 开始初始化
onLoad() {if (!isInited) {isInited = true;console.log(`Oops Framework v${version}`);this.enabled = false;let config_name = "config";// 动态加载resources/config.json配置文件,进行初始化oops.res.load(config_name, JsonAsset, () => {var config = oops.res.get(config_name);oops.config.btc = new BuildTimeConstants();oops.config.query = new GameQueryConfig();oops.config.game = new GameConfig(config);// 初始化服务器地址oops.http.server = oops.config.game.httpServer; // 设置请求超时时间oops.http.timeout = oops.config.game.httpTimeout;                                    // 初始化本地存储加密key和ivoops.storage.init(oops.config.game.localDataKey,oops.config.game.localDataIv);  // 设置游戏帧率game.frameRate = oops.config.game.frameRate;                                         this.enabled = true;this.init();this.run();});}
}
  1. 调用 init方法完成框架音频管理、屏幕适配、游戏显示隐藏的初始化,主要代码:
protected init() {// 创建持久根节点this.persistRootNode = new Node("PersistRootNode");director.addPersistRootNode(this.persistRootNode);// 创建音频模块oops.audio = this.persistRootNode.addComponent(AudioManager);oops.audio.load();// 创建时间模块oops.timer = this.persistRootNode.addComponent(TimerManager)!;// 多语言相关oops.language = new LanguageManager();// 游戏层节点构建oops.game = new GameManager(this.game);// 界面层节点构建oops.gui = new LayerManager(this.gui);this.initGui();// ECS框架的初始化this.initEcsSystem();oops.ecs.init();// 游戏显示事件game.on(Game.EVENT_SHOW, () => {oops.log.logView("【系统】游戏前台显示");oops.timer.load();     // 平台不需要在退出时精准计算时间,直接暂时游戏时间oops.audio.resumeAll();director.resume();game.resume();oops.message.dispatchEvent(EventMessage.GAME_ENTER);});// 游戏隐藏事件game.on(Game.EVENT_HIDE, () => {oops.log.logView("【系统】游戏切到后台");oops.timer.save();     // 平台不需要在退出时精准计算时间,直接暂时游戏时间oops.audio.pauseAll();director.pause();game.pause();oops.message.dispatchEvent(EventMessage.GAME_EXIT);});// 游戏尺寸修改事件var c_gui = this.gui.addComponent(GUI)!;if (sys.isMobile == false) {screen.on("window-resize", () => {oops.log.logView("【系统】游戏画布尺寸变化");c_gui.resize();oops.message.dispatchEvent(EventMessage.GAME_RESIZE);}, this);screen.on("fullscreen-change", () => {oops.log.logView("【系统】游戏全屏显示");}, this);}screen.on("orientation-change", () => {oops.log.logView("【系统】游戏旋转屏幕");}, this);
}

主要做的事情:

  • 构建常驻根节点,用于初始化音频模块和时间管理模块
  • 构建游戏层、界面层根节点
  • 初始化ECS实体组件系统框架
  • 监听项目的显示和隐藏,以停止或恢复声音等处理
  • 添加GUI屏幕适配组件

注:这里便是框架初始化的主体部分

  1. 在框架完成初始化后,就会调用Main.ts下的run() 方法,对项目进行初始化
protected run() {smc.initialize = ecs.getEntity<Initialize>(Initialize);
}

注: 项目启动的时候黑屏的那段时间也是包含框架初始化逻辑相关的,大家了解即可。

最后,祝大家学习生活工作愉快!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/279567.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt 多元素控件

Qt开发 多元素控件 Qt 中提供的多元素控件有: QListWidgetQListViewQTableWidgetQTableViewQTreeWidgetQTreeView xxWidget 和 xxView 之间的区别 以 QTableWidget 和 QTableView 为例. QTableView 是基于 MVC 设计的控件. QTableView 自身不持有数据. 使用QTableView 的 …

Qt 容器类控件

Group Box 使用 QGroupBox 实现一个带有标题的分组框可以把其他的控件放到里面作为一组&#xff0c;这样看起来能更好看一点. 核心属性 属性说明title分组框的标题alignment分组框内部内容的对齐方式flat是否是 “扁平” 模式checkable是否可选择. 设为 true&#xff0c;则在…

基于nodejs+vue班级管理系统的设计与实现-flask-django-python-php

随着电子技术的普及和快速发展&#xff0c;线上管理系统被广泛的使用&#xff0c;有很多事业单位和商业机构都在实现电子信息化管理&#xff0c;班级管理系统也不例外&#xff0c;由比较传统的人工管理转向了电子化、信息化、系统化的管理。随着互联网技术的高速发展&#xff0…

Unity Toggle处理状态变化事件

Toggle处理状态变化事件&#xff0c;有两个方法。 法一、通过Inspector面板设置 实现步骤&#xff1a; 在Inspector面板中找到Toggle组件的"On Value Changed"事件。单击""按钮添加一个新的监听器。拖动一个目标对象到"None (Object)"字段&am…

【黑马头条】-day01环境搭建SpringBoot-Cloud-Nacos

文章目录 1 环境搭建及简介2 项目介绍2.1 应用2.2 业务说明2.3 技术栈2.4 收获2.5 大纲 3 Nacos准备3.1 安装Nacos 4 初始工程搭建4.1 环境准备4.1.1 导入项目4.1.2 设置本地仓库4.1.3 设置项目编码格式 4.2 全局异常4.2.1 自动装配 4.3 工程主体结构 5 登录功能开发5.1 需求分…

有什么ai写作神器?6个AI智能写作助手分享给你

随着人工智能技术的不断发展&#xff0c;自动生成文章的软件也逐渐成为了写作领域的一项重要工具。下面将介绍国内常用的6款AI写作助手&#xff0c;来看看它们的有什么不一样的地方。 爱制作AI写作 无需下载&#xff0c;直接在线使用&#xff0c;支持手机电脑操作&#xff0c;…

Android14音频进阶:AudioFlinger究竟如何混音?(六十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

Mac版Jmeter安装与使用模拟分布式环境

Mac版Jmeter安装与使用&模拟分布式环境 1 安装Jmeter 1.1 安装Java环境 国内镜像地址&#xff1a;https://repo.huaweicloud.com/java/jdk/11.0.29/jdk-11.0.2_osx-x64_bin.dmg 下载dmg后&#xff0c;双击进行安装。 配置环境变量&#xff1a; # 1 打开环境变量配置文件…

软考 网工 每日学习打卡 2024/3/18

学习内容 第8章 网络安全 本章主要讲解网络安全方面的基础知识和应用技术。针对考试应该掌握诸如数据加密、报文认 证、数字签名等基本理论&#xff0c;在此基础上深入理解网络安全协议的工作原理&#xff0c;并能够针对具体的 网络系统设计和实现简单的安全解决方案。 本章共有…

深入理解Java并发工具包中的CyclicBarrier

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在Java的并发编程世界中&#xff0c;协调和管理多个线程的执行是一项复杂而关键的任务。为了简化这一挑战&#xff0c;Java并发包…

三种简单方法教你手机mp4怎么转换成mp3!

在日常生活中&#xff0c;我们经常会遇到想要将手机上的MP4视频转换为MP3音频的情况。可能是想要提取音频内容&#xff0c;例如歌曲或录音&#xff0c;方便在其他设备上播放或分享&#xff1b;也可能是为了节省手机存储空间&#xff0c;将视频文件转换为更小的音频文件。 无论…

【HTTP完全注解】看了还搞不懂缓存你直接来打我

HTTP缓存 HTTP缓存是一种HTTP的性能优化机制&#xff0c;它是为了提高Web页面加载速度和减轻服务器负载而设计的&#xff0c;通过这种机制&#xff0c;Web浏览器或其他客户端可以存储先前获取的Web资源的副本&#xff0c;并在后续请求相同资源时使用这些副本&#xff0c;而不是…

Java学习笔记21——使用JDBC访问MySQL数据库

JDBC&#xff08;Java Database Connectivity&#xff0c;Java数据库连接&#xff09;是应用程序编程借口&#xff08;API&#xff09;&#xff0c;描述了一套访问关系数据库的标准Java类库。可以在程序中使用这些API&#xff0c;连接到关系数据库&#xff0c;执行SQL语句&…

【技术栈】Redis 中的事务及持久化方式

SueWakeup 个人主页&#xff1a; SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8; 友情提供 目录 相关传送门 1. Redis 中的事务 2. Redis 持久化 2.1 RDB 方式 2.1.1 RDB手动 2.1.2 RDB自动 2.…

跨越时空的纽带:探索Facebook如何连接人与人

引言 Facebook作为全球最大的社交媒体平台之一&#xff0c;已经成为了人们日常生活中不可或缺的一部分。它不仅仅是一个社交网络&#xff0c;更是连接人与人、人与世界的纽带。在这篇文章中&#xff0c;我们将深入探讨Facebook如何跨越时空&#xff0c;连接人与人之间的关系&a…

Flutter 初始WidgetState 简单应用案例分析

本系列文章主要整理Flutter的知识汇总&#xff0c;由浅入深&#xff0c;从Widget的搭建到其中的原理。本文还是围绕Widget在开发中应用和理解。 关于Flutter环境配置和首次创建可以参考前面文章。链接如下&#xff1a; Flutter 安装部署与认识Dart语言 Flutter 使用AndroidS…

Spring Cloud 整合 GateWay

目录 第一章 微服务架构图 第二章 Spring Cloud整合Nacos集群 第三章 Spring Cloud GateWay 第四章 Spring Cloud Alibaba 整合Sentinel 第五章 Spring Cloud Alibaba 整合SkyWalking链路跟踪 第六章 Spring Cloud Alibaba 整合Seata分布式事务 第七章 Spring Cloud 集成Auth用…

多模匹配算法AC算法和单模匹配算法BM

多模匹配算法之AC算法详解 算法概述  Aho-Corasick算法 - 这是一种字典匹配算法,它用于在输入文本中查找字典中的字符串。时间复杂度是线性的。该算法应用有限自动机巧妙地将字符比较转化为了状态转移。  该算法的基本思想 − 在预处理阶段,AC自动机算法建立…

Springboot通过注解+切面实现接口权限校验

Springboot通过注解&#xff0b;切面实现接口权限校验 主要说一下在对接口请求时&#xff0c;如何用注解切面去拦截校验当前登录用户是否有访问权限 1.首先创建注解 HasPermission &#xff0c;跟普通注解创建方式基本一致 Retention(RetentionPolicy.RUNTIME) Target(Element…

小火星露谷管理器 报错:“你似乎没有安装Edge的webview2”

错误 解决办法 你可以到这个地方下载安装webview2 https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/?formMT00IS