import { _decorator, Component, Label, Tween, tween, v3 } from "cc"; import { Logger } from "./Logger"; const { ccclass, property } = _decorator; /*初始化加载界面*/ interface LoadingTask { progress: number; tips?: string; callback?: () => void | Promise; } @ccclass("LoadingUI") export class LoadingUI extends Component { @property(Label) public progressLabel: Label = null!; @property(Label) public tipLabel: Label = null!; private _currentProgress = 0; private _isLoading = false; private _progressTween: Tween | null = null; private _taskQueue: LoadingTask[] = []; private _currentTaskIndex = 0; /** * 开始加载流程 * @param initialProgress 初始进度 (0-100) * @example 调用事例: * this.loadingUI.startLoading(); //添加所有加载任务 this.loadingUI.addTask(10, '资源加载中...', () => { PlayerData.ins().initialize(); PlatformSystem.initialize(); SettingData.ins().initialize(); }); this.loadingUI.addTask(30, '加载音乐资源...', async () => { await AudioManager.initialize(); }); this.loadingUI.addTask(40, '加载关卡数据...', async () => { await LevelsResData.ins().initialize(); await LevelsResData.instance.preLoadAllMap(); }); this.loadingUI.addTask(20, '预加载场景...', async () => { await SceneManager.initialize(); }); //执行所有任务完成后会自动调用finishLoading() await this.loadingUI.executeTasks(); */ public startLoading(initialProgress: number = 0) { if (this._isLoading) { Logger.warn("Loading is already in progress"); return; } this.node.active = true; this._isLoading = true; this._currentProgress = initialProgress; this._updateProgressDisplay(this._currentProgress); } /** * 添加一个加载任务 * @param progress 该任务增加的进度值 (0-100) * @param tips 提示文本 * @param callback 任务回调函数,可以是异步的 */ public addTask(progress: number, tips?: string, callback?: () => void | Promise) { this._taskQueue.push({ progress, tips, callback }); } /** * 执行所有加载任务 */ public async executeTasks() { if (!this._isLoading) { Logger.warn("Loading has not started yet"); return; } for (this._currentTaskIndex = 0; this._currentTaskIndex < this._taskQueue.length; this._currentTaskIndex++) { const task = this._taskQueue[this._currentTaskIndex]; //更新提示文本 if (task.tips) { this.tipLabel.string = task.tips; } //执行任务回调 if (task.callback) { try { const result = task.callback(); if (result instanceof Promise) { await result; } } catch (error) { Logger.error("Loading task failed:", error); } } //更新进度 await this._updateProgress(this._currentProgress + task.progress); } //所有任务完成后自动完成加载 await this.finishLoading(); } /** * 直接设置进度(带动画) * @param targetProgress 目标进度 (0-100) * @param duration 动画持续时间 (秒) */ public async setProgress(targetProgress: number, duration: number = 0.3) { if(!this._isLoading) { Logger.warn("Loading has not started yet"); return; } await this._updateProgress(targetProgress, duration); } /** * 完成加载(自动跳转到100%) */ public async finishLoading(isHide: boolean = false) { if(!this._isLoading) { Logger.warn("Loading has not started yet"); return; } await this._updateProgress(100, 0.5); this._isLoading = false; //延迟隐藏 await new Promise(resolve => setTimeout(resolve, 500)); if(isHide){this.node.active = false;} //重置状态 this._reset(); } private _reset() { this._currentProgress = 0; this._taskQueue = []; this._currentTaskIndex = 0; if (this._progressTween) { this._progressTween.stop(); this._progressTween = null; } } private async _updateProgress(targetProgress: number, duration: number = 0.3) { //确保进度在0-100范围内 targetProgress = Math.min(100, Math.max(0, targetProgress)); // 如果不需要动画,直接设置 if (duration <= 0) { this._currentProgress = targetProgress; this._updateProgressDisplay(this._currentProgress); return; } //使用Tween实现平滑过渡 return new Promise((resolve) => { if (this._progressTween) { this._progressTween.stop(); } const startProgress = this._currentProgress; this._progressTween = tween({ progress: startProgress }) .to(duration, { progress: targetProgress }, { onUpdate: (target) => { this._currentProgress = Math.floor(target.progress); this._updateProgressDisplay(this._currentProgress); }, onComplete: () => { this._currentProgress = targetProgress; this._updateProgressDisplay(this._currentProgress); this._progressTween = null; resolve(); } }) .start(); }); } private _updateProgressDisplay(progress: number) { this.progressLabel.string = `${progress}%`; } }