cc.Class({ extends: cc.BaseClass, properties: { m_updateTipNode: cc.Node, }, ctor: function () { this.m_nNeedUpdate = 0; this.m_updateURL = null; }, // onLoad: function () { // cc.debug.setDisplayStats(false); // FitSize(this.node); // ShowO2I(this.node, 0.5); // this.$('Version@Label').string = ``; // if(!this.m_Loading) this.m_Loading = this.$('loading'); // this.m_Loading.zIndex = 100; // this.m_Loading.active = false; // this.$('ani').active = false; // this.$('Logo').active = false; // window.LoadSetting(); // this.m_StartAni = this.$('StartAni').getComponent(dragonBones.ArmatureDisplay); // if(window.START_ANIMATION == 0){ // this.m_nNeedUpdate = 1; // this.$('ani').active = true; // this.scheduleOnce(this.OnTimer_DelayShowLogo, 0.4); // this.m_StartAni.node.active = false; // }else{ // this.m_StartAni.addEventListener(dragonBones.EventObject.COMPLETE, this.animationEventHandler, this); // this.m_StartAni.node.active = true; // this.m_StartAni.playAnimation('newAnimation', 1); // } // }, onLoad: function () { // 关闭调试统计信息显示(如FPS、DrawCall等) cc.debug.setDisplayStats(false); // 调整当前节点尺寸以适应屏幕大小(假设为自定义函数,用于屏幕适配) FitSize(this.node); // 显示从Out到In的过渡效果,持续0.5秒(假设为自定义动画效果函数) ShowO2I(this.node, 0.5); // 初始化版本号标签并置空(通过自定义选择器获取Label组件) if (cc.sys.OS_ANDROID == cc.sys.os) { this.$('Version@Label').string = window.APP_BOTTOM_VER_ANDROID; }else{ this.$('Version@Label').string = window.APP_BOTTOM_VER_IOS; } this.$('VersionUI@Label').string = ""//window.APP_VERSION_UI; // 初始化加载界面节点 if (!this.m_Loading) this.m_Loading = this.$('loading'); // 获取loading子节点 this.m_Loading.zIndex = 100; // 设置渲染层级 this.m_Loading.active = false; // 默认隐藏加载界面 // 禁用动画节点和Logo节点 this.$('ani').active = false; this.$('Logo').active = false; // 加载游戏设置(假设为全局函数,读取本地存储配置等) window.LoadSetting(); // 获取龙骨动画组件(开场动画) // this.m_StartAni = this.$('StartAni').getComponent(dragonBones.ArmatureDisplay); // 根据启动动画设置执行不同逻辑 if (window.START_ANIMATION == 0) { // 跳过开场动画的情况 this.m_nNeedUpdate = 1; // 标记需要更新状态(具体用途需结合上下文) // this.$('ani').active = true; // 启用备用动画节点 // 延迟0.4秒执行Logo显示(等待备用动画播放) this.scheduleOnce(this.OnTimer_DelayShowLogo, 0.4); // this.m_StartAni.node.active = false; // 隐藏龙骨动画节点 } else { // // 需要播放开场动画的情况 // // 添加动画播放完成事件监听 // this.m_StartAni.addEventListener( // dragonBones.EventObject.COMPLETE, // this.animationEventHandler, // 动画结束回调 // this // 回调上下文 // ); // this.m_StartAni.node.active = true; // 启用龙骨动画节点 // this.m_StartAni.playAnimation('newAnimation', 1); // 播放指定动画(1次) } if (this.m_updateTipNode) { this.m_updateTipNode.active = false; } this._getServerIP(); }, /* 代码逻辑说明: 1. 初始化阶段: - 关闭调试显示 - 屏幕适配处理 - 显示过渡效果 - 初始化界面元素状态 2. 动画流程控制: - 通过全局变量 START_ANIMATION 控制是否播放完整开场动画 - 值为0时: * 跳过龙骨动画 * 启用备用动画节点 * 延迟显示Logo - 其他值时: * 播放龙骨开场动画 * 动画结束后通过 animationEventHandler 处理后续逻辑 3. 注意事项: - $() 可能是自定义节点选择器方法 - FitSize/ShowO2I 应为项目内封装的工具函数 - START_ANIMATION 可能表示首次启动/重复启动状态 - m_nNeedUpdate 可能用于控制后续更新逻辑 */ // start: function () { // g_Launch = this; // g_Login = null; // g_Lobby = null; // g_Table = null; // g_CurScene = this; // }, // animationEventHandler: function (event) { // if (event.type === dragonBones.EventObject.COMPLETE) { // this.m_StartAni.node.active = false; // this.m_nNeedUpdate = 1; // this.OnTimer_DelayShowLogo(); // //this.scheduleOnce(this.OnTimer_DelayShowLogo, 0.4); // } // }, // OnTimer_DelayShowLogo: function() { // this.$('ani').active = true; // this.$('Logo').active = true; // }, // onEnable: function() { // cc.director.on('LocalVersion',this.OnLocalVersion, this); // }, // OnLocalVersion: function(ver) { // if(!ver) return; // window.APP_VERSION = ver; // this.$('Version@Label').string = `v${ver}`; // }, // onDisable: function() { // cc.director.off('LocalVersion',this.OnLocalVersion, this); // }, start: function () { // 初始化全局场景引用 g_Launch = this; // 记录启动场景实例 g_Login = null; // 清空登录场景引用 g_Lobby = null; // 清空大厅场景引用 g_Table = null; // 清空游戏桌引用 g_CurScene = this; // 设置当前活动场景为启动场景 }, /* 动画事件处理回调 */ // animationEventHandler: function (event) { // // 当龙骨动画播放完成时 // if (event.type === dragonBones.EventObject.COMPLETE) { // // this.m_StartAni.node.active = false; // 隐藏开场动画节点 // this.m_nNeedUpdate = 1; // 触发状态更新标志 // this.OnTimer_DelayShowLogo(); // 立即显示Logo // // 原始延迟调用方案(已注释): // // this.scheduleOnce(this.OnTimer_DelayShowLogo, 0.4); // } // }, /* 延迟显示Logo的定时回调 */ OnTimer_DelayShowLogo: function () { this.$('ani').active = true; // 启用过渡动画节点 this.$('Logo').active = true; // 显示主Logo节点 }, /* 组件启用时的生命周期回调 */ onEnable: function () { // 注册本地版本号事件监听 cc.director.on('LocalVersion', this.OnLocalVersion, this); }, /* 处理本地版本号事件 */ OnLocalVersion: function (ver) { if (!ver) return; // 无效版本号直接返回 // 更新全局版本号并显示在UI window.APP_VERSION = ver; // 存储到全局变量 this.$('Version@Label').string = `v${ver}`; // 更新版本号标签 console.log("OnLocalVersion----1", ver) }, /* 组件禁用时的生命周期回调 */ onDisable: function () { // 移除事件监听防止内存泄漏 cc.director.off('LocalVersion', this.OnLocalVersion, this); }, //获取服务器最新IP _getServerIP() { if(window.GAME_TEST)return; this.updateIP = true; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 400)) { console.log("a1.king-mahjong.tw 返回",xhr.responseText); this.updateIP = false; window.UpdateIPRelatedAddresses(xhr.responseText); } }.bind(this); xhr.timeout = 5000; xhr.open("GET", encodeURI('https://a1.king-mahjong.tw'), true); xhr.send(); }, /* 代码逻辑说明: 1. 场景管理: - start() 初始化全局场景引用体系 - 通过重置 g_Login/g_Lobby 等引用确保场景切换的干净状态 - g_CurScene 实现当前场景的集中访问点 2. 动画流程控制: - animationEventHandler 处理开场动画结束事件 - 完成时切换至Logo显示流程 - 原设计使用延迟调用,现改为立即执行(需确认动画衔接是否合理) 3. 版本号管理: - 通过事件机制获取本地版本号 - LocalVersion 事件可能由以下场景触发: * 本地存储读取完成 * 网络请求获取最新版本 * 热更新流程结束 - 版本号显示使用ES6模板字符串格式化 4. 事件管理: - onEnable/onDisable 组成对称的事件监听生命周期 - 防止组件销毁后残留监听导致报错 5. 注意事项: - 全局变量(g_XX)的使用需确保单场景切换时的正确清理 - m_nNeedUpdate 的具体作用需结合更新逻辑分析 - 直接调用 OnTimer_DelayShowLogo() 需确认不需要等待动画残留资源释放 - 版本号标签更新依赖选择器正确指向目标节点 */ // update: function () { // if (this.m_nNeedUpdate > 0) { // this.m_nNeedUpdate--; // } else { // return; // } // this.LoadConfig(); // cc.gPreLoader.Init(function () { // if (cc.sys.isNative) { // this.ShowPrefabDLG("UpdateManager", this.node, function (Js) { // Js.CheckUpdate(function() { this.ShowLogin(); }.bind(this)); // }.bind(this)); // } else { // if (cc.sys.browserType == cc.sys.BROWSER_TYPE_WECHAT || cc.sys.browserType == cc.sys.BROWSER_TYPE_MOBILE_QQ) { // ChangeScene('Lobby'); // } else { // this.ShowLogin(); // } // } // }.bind(this)); // }, update: function () { //获取最新IP if (this.updateIP) { return; } // 更新逻辑控制:仅在 m_nNeedUpdate 有效时执行 if (this.m_nNeedUpdate > 0) { this.m_nNeedUpdate--; // 递减更新计数器 } else { return; // 未达到更新条件时直接退出 } // 加载基础配置文件(假设为游戏核心配置) this.LoadConfig(); // cc.assetManager.loadBundle("21201", "", function (err, bundle) { // if (err) { // console.log('加载bundle错误---', "21201"); // let bundle21201 = cc.assetManager.getBundle('21201'); // console.log('加载bundle---21201', bundle21201); // return console.error(err); // } // console.log('加载bundle成功---21201'); // //console.log('1-----------------',JSON.stringify(bundle)); // console.log('2-----------------', JSON.stringify(bundle._config.paths._map)); // for (let i in bundle._config.paths._map) { // let asset = bundle._config.paths._map[i]; // console.log('3-----------------', asset); // for (let j = 0; j < asset.length; j++) { // console.log('4-----------------', JSON.stringify(asset[j])); // console.log('41-----------------', JSON.stringify(asset[j].ctor)); // console.log('5-----------------', (asset[j].ctor)); // console.log('6-----------------', (asset[j].ctor.toString())); // for (let key in asset[j]) { // if (typeof asset[j][key] === 'function') { // console.log(key + '()'); // } else { // console.log(key + ': ' + asset[j][key]); // } // } // return; // } // } // console.dir(bundle, { depth: null }); // }.bind(this)); // return; // 初始化预加载系统 cc.gPreLoader.Init(function (url) { if (url) { this.m_updateURL = url; if (this.m_updateTipNode) { this.m_updateTipNode.active = true; } } else { this.ShowLogin(); } return; // 平台判断分支 if (cc.sys.isNative) { // 原生平台(iOS/Android)&& window.IS_UPDATE // 显示更新管理弹窗 this.ShowPrefabDLG("UpdateManager", this.node, function (Js) { // 执行更新检查 Js.CheckUpdate(function () { this.ShowLogin(); // 更新完成后显示登录界面 }.bind(this)); }.bind(this)); } else { // Web 平台 // 判断是否在微信/QQ内置浏览器 // if (cc.sys.browserType == cc.sys.BROWSER_TYPE_WECHAT || // cc.sys.browserType == cc.sys.BROWSER_TYPE_MOBILE_QQ) { // ChangeScene('Lobby'); // 特殊浏览器直接进入大厅 // } else { // this.ShowLogin(); // 普通浏览器显示登录界面 // } this.ShowLogin(); } }.bind(this)); // 保持上下文绑定 }, /* 代码逻辑说明: 1. 更新节奏控制: - 通过 m_nNeedUpdate 实现延迟更新机制 - 当外部设置 m_nNeedUpdate = 1 时,实际在下一帧才会执行核心逻辑 - 适用于等待其他初始化完成的场景 2. 核心流程: LoadConfig -> 预加载初始化 -> 平台判断 -> 执行对应流程 3. 平台差异化处理: - 原生平台: * 强制进行热更新检查 * 使用 UpdateManager 弹窗处理更新流程 * 更新完成后自动跳登录 - Web平台: * 微信/QQ浏览器跳过登录直接进大厅(可能利用内置鉴权) * 普通浏览器需要显示登录界面 4. 关键方法说明: - ShowPrefabDLG: 动态加载预制弹窗 * 参数1: 预制体名称 * 参数2: 父节点 * 参数3: 弹窗加载完成回调 - CheckUpdate: 封装的热更新检查方法 - ChangeScene: 场景切换工具方法 5. 注意事项: - 依赖 cc.gPreLoader 预加载系统的正确初始化 - ShowPrefabDLG 需要确保预制体资源的正确加载 - 微信/QQ浏览器逻辑可能需要配套的授权登录机制 - 缺少错误处理逻辑(更新失败、网络异常等情况) - 使用函数式编程需注意闭包内存管理 - bind(this) 的频繁使用可能影响性能 */ // ShowLogin: function () { // this.ShowPrefabDLG("Login", this.node, function () {}.bind(this)); // }, // ShowUpdate: function () { // this.ShowPrefabDLG("UpdateManager", this.node, function (Js) { // Js.StartPreload(true, 0, function(){ // this.ShowLogin(); // }.bind(this)); // }.bind(this)); // }, ShowLogin: function () { // 显示登录界面弹窗 console.log("ShowLogin----") // cc.assetManager.loadBundle('Test', (err, bundle) => { // console.log("bundle",bundle) // bundle.load(`Nutton`, cc.Prefab, function (err, prefab) { // let newNode = cc.instantiate(prefab); // console.log("newNode",newNode,prefab) // this.node.addChild(newNode); // }.bind(this)); // }); // return; this.ShowPrefabDLG( "Login", // 预制体名称:登录界面 this.node, // 父节点:当前场景根节点 function () { // 加载完成回调(空操作) // 可在此处添加登录界面初始化后操作 }.bind(this) // 确保回调函数中的this指向当前组件 ); }, /* 代码逻辑说明: 1. 核心功能:动态加载并显示登录界面 2. 参数说明: - "Login": 预制体资源路径(假设在resources目录) - this.node: 作为弹窗的父节点,确保正确层级 - 空回调:可能用于预留后续扩展 3. 典型使用场景: - 用户手动点击登录按钮 - 自动登录失败时切换至登录界面 */ ShowUpdate: function () { // 显示更新管理器弹窗并启动预加载 this.ShowPrefabDLG( "UpdateManager", // 预制体名称:更新管理器 this.node, // 父节点:当前场景根节点 function (Js) { // 弹窗实例回调 // 启动预加载流程 Js.StartPreload( true, // 参数1:是否显示进度条(假设) 0, // 参数2:预加载阶段标识 function () { this.ShowLogin(); // 预加载完成后显示登录界面 }.bind(this) ); }.bind(this) ); }, /* 代码逻辑说明: 1. 核心流程: 显示更新弹窗 -> 初始化预加载 -> 完成后跳转登录 2. 参数详解: - StartPreload 参数分析: * true: 可能控制是否显示加载进度界面 * 0: 可能表示预加载阶段或资源类型标识 * 回调函数:衔接后续登录流程 3. 功能特点: - 更新管理器的显示与预加载流程解耦 - 通过回调链实现异步操作顺序控制 - 支持可视化更新进度显示 4. 注意事项: - 需要确保UpdateManager预制体实现StartPreload方法 - 参数的具体含义需结合StartPreload实现分析 - 缺少加载失败的重试机制 - 硬编码参数不利于后续维护 */ /* 跨方法关联分析: 1. 流程衔接: ShowUpdate -> StartPreload完成 -> ShowLogin 2. 设计模式: - 模块化:将更新、登录功能封装为独立预制件 - 观察者模式:通过回调函数实现流程控制 3. 改进建议: - 添加加载失败的回调处理 - 使用配置对象代替硬编码参数 - 考虑网络状态检测 - 增加加载过渡动画 */ // //游戏入口 // EnterGameScene:function(){ // // 加载游戏 // if(GameDef && g_ServerListDataLast){ // if(window.LOG_NET_DATA)console.log("地址:", g_ServerListDataLast.szServerAddr+":"+g_ServerListDataLast.wServerPort); // this.m_Loading.active = true; // this.ShowPrefabDLG("UpdateManager", this.m_Loading, function (Js) { // Js.StartPreload(0, g_ServerListDataLast.wKindID, function() { // cc.gPreLoader.LoadRes(`Image_BG_BG${GameDef.BGIndex}`, '' + GameDef.KIND_ID, function(res) { // window.gGameBG = 'loading'; // ChangeScene('Table'); // }.bind(this)); // }.bind(this)); // }.bind(this)); // } // }, // LoadConfig: function() { // cc.share.LoadConfig(); // } //游戏入口 EnterGameScene: function () { // 进入游戏场景主流程 if (GameDef && g_ServerListDataLast) { // 校验游戏配置和服务器数据已加载 // 调试模式下打印服务器连接信息 if (window.LOG_NET_DATA) console.log("地址:", g_ServerListDataLast.szServerAddr + ":" + g_ServerListDataLast.wServerPort); // 显示加载界面 this.m_Loading.active = true; // 加载更新管理器弹窗 this.ShowPrefabDLG("UpdateManager", this.m_Loading, function (Js) { // 启动资源预加载流程 Js.StartPreload( 0, // 参数1:预加载模式(0可能表示基础资源加载) g_ServerListDataLast.wKindID, // 参数2:游戏种类ID function () { // 预加载完成回调 // 加载特定游戏背景资源 cc.gPreLoader.LoadRes( `Image_BG_BG${GameDef.BGIndex}`, // 动态拼接背景图路径 '' + GameDef.KIND_ID, // 资源分类标识 function (res) { // 资源加载完成回调 window.gGameBG = 'loading'; // 设置全局背景状态 ChangeScene('Table'); // 切换到游戏桌场景 }.bind(this) ); }.bind(this) ); }.bind(this)); } }, LoadConfig: function () { cc.share.LoadConfig(); // 可能包含:音效开关、语言包、UI皮肤等全局配置 }, /* 功能扩展建议: 1. 添加加载超时机制: setTimeout(() => { if(!this.resLoaded) showErrorTip(); }, 10000); 2. 实现进度反馈: - 在UpdateManager中暴露加载进度事件 - 在加载界面添加进度条动画 3. 资源加载优化: - 使用cc.resources.load替代直接路径引用 - 添加资源加载失败重试机制 4. 安全校验增强: - 验证服务器地址的合法性 - 添加SSL证书检测(针对HTTPS) */ onclickUpdateJump() { if (this.m_updateURL) { ThirdPartyOpenUrl(this.m_updateURL); } }, });