LaunchScreen.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import { _decorator, Component, Node, director, assetManager, ProgressBar, Label, Sprite, SpriteFrame, resources } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. // 微信小游戏API类型声明
  4. declare global {
  5. interface Window {
  6. wx?: {
  7. loadSubpackage?: (options: {
  8. name: string;
  9. success?: () => void;
  10. fail?: (err: any) => void;
  11. }) => any;
  12. };
  13. }
  14. const wx: {
  15. loadSubpackage?: (options: {
  16. name: string;
  17. success?: () => void;
  18. fail?: (err: any) => void;
  19. }) => any;
  20. } | undefined;
  21. }
  22. @ccclass('LaunchScreen')
  23. export class LaunchScreen extends Component {
  24. @property(ProgressBar)
  25. progressBar: ProgressBar = null;
  26. @property(Label)
  27. progressLabel: Label = null;
  28. @property(Sprite)
  29. backgroundSprite: Sprite = null;
  30. @property(SpriteFrame)
  31. launchBackground: SpriteFrame = null;
  32. private totalAssets = 0;
  33. private loadedAssets = 0;
  34. start() {
  35. console.log('[LaunchScreen] 启动页开始初始化');
  36. // 设置启动页背景
  37. this.setupBackground();
  38. // 开始预加载游戏资源
  39. this.preloadGameAssets();
  40. }
  41. /**
  42. * 设置启动页背景
  43. */
  44. private setupBackground() {
  45. if (this.backgroundSprite && this.launchBackground) {
  46. this.backgroundSprite.spriteFrame = this.launchBackground;
  47. console.log('[LaunchScreen] 启动页背景设置完成');
  48. }
  49. }
  50. /**
  51. * 预加载游戏资源
  52. */
  53. private async preloadGameAssets() {
  54. try {
  55. console.log('[LaunchScreen] 开始预加载游戏资源');
  56. // 更新进度显示
  57. this.updateProgress(0, '正在加载游戏资源...');
  58. // 预加载game-level分包
  59. await this.loadSubpackage('game-level');
  60. // 预加载完成,跳转到游戏场景
  61. this.loadGameScene();
  62. } catch (error) {
  63. console.error('[LaunchScreen] 资源预加载失败:', error);
  64. this.updateProgress(0, '资源加载失败,请重试');
  65. }
  66. }
  67. /**
  68. * 加载分包
  69. */
  70. private loadSubpackage(bundleName: string): Promise<void> {
  71. return new Promise((resolve, reject) => {
  72. console.log(`[LaunchScreen] 开始加载分包: ${bundleName}`);
  73. // 检查是否在微信小游戏环境
  74. if (typeof wx !== 'undefined' && wx && wx.loadSubpackage) {
  75. // 微信小游戏分包加载
  76. const loadTask = wx.loadSubpackage({
  77. name: bundleName,
  78. success: () => {
  79. console.log(`[LaunchScreen] 微信分包 ${bundleName} 加载成功`);
  80. // 分包加载成功后,再加载bundle
  81. this.loadBundleAfterSubpackage(bundleName, resolve, reject);
  82. },
  83. fail: (err) => {
  84. console.error(`[LaunchScreen] 微信分包 ${bundleName} 加载失败:`, err);
  85. // 微信分包加载失败时,尝试直接加载bundle作为降级方案
  86. console.log(`[LaunchScreen] 尝试直接加载bundle作为降级方案`);
  87. this.loadBundleAfterSubpackage(bundleName, resolve, reject);
  88. }
  89. });
  90. // 监听分包加载进度
  91. if (loadTask && loadTask.onProgressUpdate) {
  92. loadTask.onProgressUpdate((res) => {
  93. const progress = res.progress || 0;
  94. this.updateProgress(progress, `正在下载分包... ${progress}%`);
  95. });
  96. }
  97. } else {
  98. // 非微信环境,直接加载bundle
  99. console.log(`[LaunchScreen] 非微信环境,直接加载bundle`);
  100. this.loadBundleAfterSubpackage(bundleName, resolve, reject);
  101. }
  102. });
  103. }
  104. /**
  105. * 分包下载完成后加载bundle
  106. */
  107. private loadBundleAfterSubpackage(bundleName: string, resolve: Function, reject: Function) {
  108. assetManager.loadBundle(bundleName, (err, bundle) => {
  109. if (err) {
  110. console.error(`[LaunchScreen] Bundle ${bundleName} 加载失败:`, err);
  111. // 如果bundle加载失败,尝试跳过分包直接进入主场景
  112. console.log(`[LaunchScreen] Bundle加载失败,尝试跳过分包加载`);
  113. this.skipSubpackageAndLoadMainScene(resolve, reject);
  114. return;
  115. }
  116. console.log(`[LaunchScreen] Bundle ${bundleName} 加载成功`);
  117. // 预加载分包中的场景
  118. bundle.preloadScene('GameLevel', (finished: number, total: number) => {
  119. const progress = finished / total;
  120. this.updateProgress(progress * 100, `正在加载游戏场景... ${Math.floor(progress * 100)}%`);
  121. }, (err) => {
  122. if (err) {
  123. console.error('[LaunchScreen] GameLevel场景预加载失败:', err);
  124. // 场景预加载失败时,也尝试跳过分包
  125. this.skipSubpackageAndLoadMainScene(resolve, reject);
  126. return;
  127. }
  128. console.log('[LaunchScreen] GameLevel场景预加载完成');
  129. this.updateProgress(100, '加载完成!');
  130. resolve();
  131. });
  132. });
  133. }
  134. /**
  135. * 更新加载进度
  136. */
  137. private updateProgress(progress: number, message: string) {
  138. if (this.progressBar) {
  139. this.progressBar.progress = progress / 100;
  140. }
  141. if (this.progressLabel) {
  142. this.progressLabel.string = message;
  143. }
  144. console.log(`[LaunchScreen] ${message} (${progress.toFixed(1)}%)`);
  145. }
  146. /**
  147. * 跳过分包加载,直接进入主场景的降级方案
  148. */
  149. private skipSubpackageAndLoadMainScene(resolve: Function, reject: Function) {
  150. console.log('[LaunchScreen] 执行降级方案:跳过分包,尝试加载主场景');
  151. // 尝试加载主场景(如果存在的话)
  152. director.loadScene('First', (err) => {
  153. if (err) {
  154. console.error('[LaunchScreen] 主场景加载也失败:', err);
  155. this.updateProgress(0, '游戏加载失败,请刷新重试');
  156. reject(err);
  157. } else {
  158. console.log('[LaunchScreen] 成功加载主场景作为降级方案');
  159. this.updateProgress(100, '加载完成(降级模式)');
  160. resolve();
  161. }
  162. });
  163. }
  164. /**
  165. * 跳转到游戏场景
  166. */
  167. private loadGameScene() {
  168. console.log('[LaunchScreen] 准备跳转到GameLevel场景');
  169. // 延迟一秒后跳转,让用户看到加载完成的提示
  170. this.scheduleOnce(() => {
  171. // 使用分包中的场景
  172. const bundle = assetManager.getBundle('game-level');
  173. if (bundle) {
  174. bundle.loadScene('GameLevel', (err, scene) => {
  175. if (err) {
  176. console.error('[LaunchScreen] GameLevel场景加载失败:', err);
  177. // 如果分包场景加载失败,尝试加载主场景
  178. this.loadFallbackScene();
  179. return;
  180. }
  181. console.log('[LaunchScreen] 正在切换到GameLevel场景');
  182. director.runScene(scene);
  183. });
  184. } else {
  185. console.error('[LaunchScreen] game-level分包未找到,尝试加载主场景');
  186. this.loadFallbackScene();
  187. }
  188. }, 1.0);
  189. }
  190. /**
  191. * 加载降级场景
  192. */
  193. private loadFallbackScene() {
  194. console.log('[LaunchScreen] 尝试加载降级场景');
  195. director.loadScene('First', (err) => {
  196. if (err) {
  197. console.error('[LaunchScreen] 降级场景加载失败:', err);
  198. this.updateProgress(0, '游戏启动失败,请刷新页面重试');
  199. } else {
  200. console.log('[LaunchScreen] 成功加载降级场景');
  201. }
  202. });
  203. }
  204. }