资源加载逻辑修改
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 1m16s

This commit is contained in:
TJH 2025-12-30 12:26:22 +08:00
parent 13bde0b065
commit 9ad38a43b5
11 changed files with 630 additions and 666 deletions

View File

@ -28,13 +28,6 @@ export class SysGift extends Component {
onLoad(): void {
this.hideAll();
let sp_win = this.info.getChildByName("sysgift_win")
sp_win.getComponent(LocalizedSprite).fetchRender();
let scale = 116 / sp_win.getComponent(Sprite).spriteFrame.width;
sp_win.setScale(scale, scale, scale);
}
hideAll() {
@ -53,9 +46,10 @@ export class SysGift extends Component {
let txt_spin_num = this.info.getChildByName("count")
txt_spin_num.getComponent(Label).string = (frb.Ongoing.Frn.toLocaleString())
let sp_win = this.info.getChildByName("sysgift_win")
let txt_win = this.info.getChildByName("win")
let scale = 116 / sp_win.getComponent(Sprite).spriteFrame.width;
sp_win.setScale(scale, scale, scale);
let num = Math.round(frb.Ongoing.Fra * 100 + 1e-6) / 100;
txt_win.getComponent(Label).string = num.toLocaleString('en-US', {

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
import { _decorator, Component, SpriteFrame, Sprite, resources } from 'cc';
import { _decorator, Component, Sprite } from 'cc';
import { I18nManager } from '../manager/I18nManager';
const { ccclass, property, executeInEditMode } = _decorator;
const { ccclass, property } = _decorator;
@ccclass('LocalizedSprite')
export class LocalizedSprite extends Component {
@ -15,90 +15,21 @@ export class LocalizedSprite extends Component {
this.updateSprite();
}
fetchRender() {
if (!this.sprite) {
this.sprite = this.getComponent(Sprite);
}
if (this.sprite) {
this.updateSprite();
} else {
console.warn(`LocalizedSprite: No Sprite component found on node ${this.node.name}`);
this.loadDefaultSprite();
}
}
public updateSprite() {
if (!this.sprite || !this.spriteName) return;
if (!I18nManager.instance.ready) return;
let cacheKey = `${I18nManager.instance.currentLanguage}_${this.spriteName}`;
let cachedFrame = I18nManager.instance.spriteFrameCache.get(cacheKey);
const currentLanguage = I18nManager.instance.currentLanguage;
const cacheKey = `${currentLanguage}_${this.spriteName}`;
// 从I18nManager获取缓存的SpriteFrame
const cachedFrame = I18nManager.instance.spriteFrameCache.get(cacheKey);
if (cachedFrame) {
this.setNewSpriteFrame(cachedFrame);
return;
}
// 如果缓存中没有从resources加载
const spritePath = `i18nSprite/${currentLanguage}/${this.spriteName}/spriteFrame`;
resources.load(spritePath, SpriteFrame, (err, spriteFrame) => {
if (err) {
console.warn(`Failed to load sprite: ${spritePath}`, err);
this.loadDefaultSprite();
return;
}
if (spriteFrame) {
// 添加到I18nManager的缓存中
I18nManager.instance.spriteFrameCache.set(cacheKey, spriteFrame);
this.setNewSpriteFrame(spriteFrame);
}
});
}
private loadDefaultSprite() {
const defaultPath = `i18nSprite/en/${this.spriteName}/spriteFrame`;
const cacheKey = `en_${this.spriteName}`;
// 从I18nManager获取默认语言的缓存
const cachedFrame = I18nManager.instance.spriteFrameCache.get(cacheKey);
if (cachedFrame) {
this.setNewSpriteFrame(cachedFrame);
return;
}
resources.load(defaultPath, SpriteFrame, (err, spriteFrame) => {
if (err) {
console.error('Failed to load default sprite:', err);
return;
}
if (spriteFrame) {
// 添加到I18nManager的缓存中
I18nManager.instance.spriteFrameCache.set(cacheKey, spriteFrame);
this.setNewSpriteFrame(spriteFrame);
}
});
}
private setNewSpriteFrame(newFrame: SpriteFrame) {
if (this.sprite) {
this.sprite.spriteFrame = newFrame;
this.sprite.spriteFrame = cachedFrame;
}
}
public setSpriteName(name: string) {
this.spriteName = name;
this.updateSprite();
}
onDestroy() {
// 只清理当前组件的引用
if (this.sprite) {
this.sprite.spriteFrame = null;
}
this.sprite = null;
updateSpriteForPreload(language: string) {
this.sprite = this.getComponent(Sprite);
let cacheKey = `${language}_${this.spriteName}`;
let cachedFrame = I18nManager.instance.spriteFrameCache.get(cacheKey);
this.sprite.spriteFrame = cachedFrame;
}
}

View File

@ -1,296 +1,236 @@
import { _decorator, Component, Node, ProgressBar, Label, Button, view, VideoPlayer, UITransform, AssetManager, tween, ResolutionPolicy, game, director, Director, sys, macro, JsonAsset } from 'cc';
import { _decorator, Component, Node, ProgressBar, Label, UITransform, tween, JsonAsset } from 'cc';
import { callGameApi, getIsRB7, getLanguage, initReqAddr } from './comm';
import { GameDataManager } from './manager/GameDataManager';
import { ResManager } from './manager/ResManager';
import { AudioManager } from './manager/AudioManager';
import { NodePoolManager } from './manager/NodePoolManager';
import { DEBUG } from 'cc/env';
import { initErrorManager } from './manager/ErrorManager';
import { I18nManager } from './manager/I18nManager';
import { LocalizedSprite } from './i18n/LocalizedSprite';
import { initErrorManager } from './manager/ErrorManager';
let { ccclass, property } = _decorator;
@ccclass('LoadingUI')
export class LoadingUI extends Component {
//test
@property(Node)
BG: Node = null;
@property(Node)
LoadingUINode: Node = null;
@property(ProgressBar)
progressBar: ProgressBar = null;
@property(Label)
progressLabel: Label = null;
@property(Label)
loadingTipLabel: Label = null;
@property(Label)
retryTipLabel: Label = null;
@property(Button)
startBtn: Button = null;
@property(Label)
startBtnLabel: Label = null;
@property(Node)
GameNode: Node = null;
@property(JsonAsset)
languageJson: JsonAsset = null;
private _networkComplete = false;
private _retryCount = 0;
private readonly MAX_RETRY = 5;
private INITIAL_PROGRESS = 0.3;
private _instanceGameNode = null;
import { AudioManager } from './manager/AudioManager';
import { GameDataManager } from './manager/GameDataManager';
import { ResManager } from './manager/ResManager';
import { NodePoolManager } from './manager/NodePoolManager';
// 新增动画
private maskUITransform: UITransform = null;
private lightNode: Node = null;
const { ccclass, property } = _decorator;
@ccclass('Loading')
export class Loading extends Component {
// UI组件
@property(Node) progressNode: Node = null;
@property(ProgressBar) progressBar: ProgressBar = null;
@property(Label) progressLabel: Label = null;
@property(Label) loadingLabel: Label = null;
@property(Node) maskSpineNode: Node = null;
@property(Node) lightSpineNode: Node = null;
@property(Node) startBtnNode: Node = null;
@property(Node) LoadingUINode: Node = null;
@property(Node) rb7Logo: Node = null;
@property(JsonAsset) languageJson: JsonAsset = null;
// 加载状态
private isNetworkReady = false;
private readonly PROGRESS_ANIMATION_DURATION = 0.3;
// 进度条阶段
private readonly PROGRESS_INIT = 0.2; // 初始化完成
private readonly PROGRESS_NETWORK = 0.5; // 网络请求完成
private readonly PROGRESS_RESOURCE = 0.9; // 资源加载完成
private readonly PROGRESS_COMPLETE = 1.0; // 完全加载完成
// 游戏节点
private gameContainer: Node = null;
private gameNode: Node = null;
protected async onLoad() {
// initErrorManager();
// 初始显示状态
this.initUI();
this.LoadingUINode.active = false;
}
async start() {
try {
initReqAddr();
this.node.getChildByName('Logo').active = getIsRB7();
await I18nManager.instance.init(getLanguage(), this.languageJson);
let language = getLanguage();
if (getLanguage() == 'zh') {
this.node.getChildByPath("Mask/LoadingUINode/logo_zh").active = true;
this.node.getChildByPath("Mask/LoadingUINode/logo_en").active = false;
} else {
this.node.getChildByPath("Mask/LoadingUINode/logo_zh").active = false;
this.node.getChildByPath("Mask/LoadingUINode/logo_en").active = true;
}
initErrorManager();
await I18nManager.instance.ensureI18nSprite(language, '2');
this.node.getChildByPath('Mask/LoadingUINode/msg').getComponent(LocalizedSprite).updateSpriteForPreload(language);
this.node.getChildByPath('Mask/LoadingUINode/msg').active = true;
await I18nManager.instance.init(language, this.languageJson);
I18nManager.instance.updateSceneRenderers();
// this.LoadingUINode.getChildByName("bg").getComponent(LocalizedSprite).fetchRender();
this.LoadingUINode.active = true;
// 更新进度条到 0.4
this.updateProgress(0.4);
this.initializeUI();
// 初始化完成进度条到20%
this.updateProgress(this.PROGRESS_INIT);
try {
await this.initializeSystem();
AudioManager.instance.init();
game.setFrameRate(61);
// this.checkStartLoading();
// 开始网络请求
this.initNetwork();
this.updateLoadingText('AID_LOADING');
// 延迟一下让用户看到进度条开始
this.scheduleOnce(() => {
this.startNetworkLoading();
}, 0.2);
} catch (error) {
console.error('Network initialization failed:', error);
this.handleError(error);
// this.handleError(error);
}
}
private initUI() {
this.BG.active = true;
this.startBtn.node.active = false;
this.maskUITransform = this.LoadingUINode.getChildByName('mask').getComponent(UITransform);
this.lightNode = this.LoadingUINode.getChildByName('light');
this.updateProgress(this.INITIAL_PROGRESS);
}
private async initNetwork() {
/** 初始化系统 */
private async initializeSystem() {
this.rb7Logo.active = getIsRB7();
// if (DEBUG) {
// await getTestToken('nova006', 'faketrans');
// }
}
/** 初始化UI */
private initializeUI() {
this.startBtnNode.active = false;
this.gameContainer = this.node.getChildByPath('Mask/GameNode')
// 初始化进度条为0
this.updateProgress(0);
}
/** 开始网络加载 */
private async startNetworkLoading() {
this.updateLoadingText('AID_LOADING');
try {
// 更新进度条到 0.6
this.updateProgress(0.6);
this.loadingTipLabel.string = I18nManager.instance.t('AID_LOADING');
this.retryTipLabel.string = '';
let gameInfo = await callGameApi("gameinfo", {});
if (!gameInfo) throw new Error('Get game info failed');
GameDataManager.instance.gameInfo = gameInfo;
this.isNetworkReady = true;
// 更新进度条到 0.8
this.updateProgress(0.8);
// 网络请求完成进度条到50%
this.updateProgress(this.PROGRESS_NETWORK);
this._networkComplete = true;
await GameDataManager.instance.preloadFrameTypeCache();
await GameDataManager.instance.preloadSymbolCache();
this.checkStartLoading();
// 稍微延迟一下让用户看到进度变化
this.scheduleOnce(() => {
this.startResourceLoading();
}, 0.3);
} catch (error) {
console.error('Network initialization failed:', error);
this.handleError(error);
}
}
private checkStartLoading() {
if (this._networkComplete) {
this.LoadingUINode.active = true;
this.startLoadingGameBundle();
}
}
private async startLoadingGameBundle() {
try {
// 显示加载UI
this.loadingTipLabel.string = I18nManager.instance.t('AID_LOADING');
this.retryTipLabel.string = '';
this.startBtn.node.active = false;
/** 开始资源加载 */
private async startResourceLoading() {
if (!this.isNetworkReady) return;
// 从 0.8 开始加载
let startProgress = 0.8;
// this.updateLoadingText('Loading More...');
this.startBtnNode.active = false;
// 使用新的合并函数加载 Bundle 和预制体
this._instanceGameNode = await ResManager.instance.loadPrefabFromBundle(
this.gameNode = await ResManager.instance.loadPrefabFromBundle(
'Game',
'prefabs/SlotScene',
'SlotScene',
(finished: number, total: number) => {
if (total <= 0) return;
let bundleProgress = finished / total;
// 将加载进度映射到 0.8-1 的范围
let mappedProgress = startProgress + (bundleProgress * (1 - startProgress));
this.updateProgress(mappedProgress);
if (total > 0) {
// 资源加载进度从50%到90%
const resourceProgress = finished / total;
const currentProgress = this.PROGRESS_NETWORK +
(resourceProgress * (this.PROGRESS_RESOURCE - this.PROGRESS_NETWORK));
this.updateProgress(currentProgress);
}
}
);
this.updateProgress(1);
// 资源加载完成进度条到90%
this.updateProgress(this.PROGRESS_RESOURCE);
// 延迟一下然后完成最后的10%
this.scheduleOnce(() => {
this.finishLoading();
}, 0.2);
}
/** 完成加载 */
private finishLoading() {
// this.updateLoadingText('Loading More...');
// 最后10%快速完成
this.updateProgress(this.PROGRESS_COMPLETE);
// 0.5秒后显示开始按钮
this.scheduleOnce(() => {
this.onLoadComplete();
} catch (error) {
console.error('Loading error:', error);
this.handleError(error);
}
}, 0.5);
}
/** 更新进度条 */
private updateProgress(progress: number) {
// 使用 tween 使进度条更新更平滑
tween(this.progressBar)
.to(0.2, { progress: progress }, {
.to(this.PROGRESS_ANIMATION_DURATION, { progress }, {
easing: 'smooth',
onUpdate: (target: any, ratio: number) => {
this.progressLabel.string = `${Math.floor(target.progress * 100)}%`;
this.maskUITransform.width = target.progress * 494;
this.lightNode.setPosition(target.progress * 496 - 274, -612, 0);
onUpdate: (target: any) => {
const currentProgress = target.progress;
this.progressLabel.string = `${Math.floor(currentProgress * 100)}%`;
this.maskSpineNode.getComponent(UITransform).setContentSize(currentProgress * 509, 100);
this.lightSpineNode.setPosition(currentProgress * 509 - 278, -612, 0)
}
})
.start();
}
/** 更新加载文本 */
private updateLoadingText(key: string) {
this.loadingLabel.string = `${I18nManager.instance.t(key)}...`;
}
/** 加载完成 */
private onLoadComplete() {
// 开始游戏
this.scheduleOnce(() => {
this.loadingTipLabel.string = '';
this.retryTipLabel.string = '';
this.startBtn.node.active = true;
this.startBtnLabel.string = I18nManager.instance.t('AID_GET_STARTED');
this.hideProgressUI();
this.showStartButton();
}
/** 隐藏进度UI */
private hideProgressUI() {
this.loadingLabel.string = '';
this.progressBar.node.active = false;
this.progressLabel.node.active = false;
this.maskUITransform.node.active = false;
this.lightNode.active = false;
}, 0.3);
this.maskSpineNode.active = false;
this.lightSpineNode.active = false;
}
private handleError(error: Error) {
this._retryCount++;
this.loadingTipLabel.string = '';
if (this._retryCount <= this.MAX_RETRY) {
// 自动重试
switch (this._retryCount) {
case 1:
this.retryTipLabel.string = I18nManager.instance.t('AID_NETWORK_RETRY_1');
break
case 2:
this.retryTipLabel.string = I18nManager.instance.t('AID_NETWORK_RETRY_2');
break
case 3:
this.retryTipLabel.string = I18nManager.instance.t('AID_NETWORK_RETRY_3');
break
case 4:
this.retryTipLabel.string = I18nManager.instance.t('AID_NETWORK_RETRY_4');
break
case 5:
this.retryTipLabel.string = I18nManager.instance.t('AID_NETWORK_RETRY_5');
break
}
this.scheduleOnce(() => {
if (!this._networkComplete) {
this.initNetwork();
} else {
this.startLoadingGameBundle();
}
}, 2);
} else {
// 显示重试按钮
this.loadingTipLabel.string = I18nManager.instance.t('AID_LOADING');
this.retryTipLabel.string = '';
this.startBtn.node.active = true;
this.progressBar.node.active = false;
this.progressLabel.node.active = false;
this.maskUITransform.node.active = false;
this.lightNode.active = false;
this.startBtnLabel.string = I18nManager.instance.t('AID_ERROR_RETRY_BUTTON');
}
/** 显示开始按钮 */
private showStartButton() {
this.startBtnNode.active = true;
}
/** 开始游戏 */
// private startGame() {
// if (!this.gameContainer) {
// console.error('Game container not found');
// return;
// }
// this.gameContainer.addChild(this.gameNode);
// // this.node.destroy();
// }
/** 按钮点击事件 */
onStartBtnClick() {
if (this.startBtnLabel.string === I18nManager.instance.t('AID_ERROR_RETRY_BUTTON')) {
// 重试逻辑
this._retryCount = 0;
this.startBtn.node.active = false;
this.progressBar.node.active = true;
this.progressLabel.node.active = true;
this.maskUITransform.node.active = true;
this.lightNode.active = true;
if (!this._networkComplete) {
this.initNetwork();
} else {
this.startLoadingGameBundle();
}
} else if (this.startBtnLabel.string === I18nManager.instance.t('AID_GET_STARTED')) {
this.node.getChildByName('Logo').active = false;
// 确保 GameNode 存在
if (!this.GameNode) {
throw new Error('GameNode is not set');
}
this.rb7Logo.active = false;
// 添加到场景
this.GameNode.addChild(this._instanceGameNode);
this.gameContainer.addChild(this.gameNode);
// 隐藏加载界面
this.LoadingUINode.destroy();
}
}
onDestroy() {
this.unscheduleAllCallbacks();
tween(this.progressBar).stop();
AudioManager.instance.destroy();
NodePoolManager.instance.clearAll();
}
// UNKNOWN = 0, // 未知平台
// WINDOWS = 1, // Windows
// LINUX = 2, // Linux
// MACOS = 3, // macOS
// ANDROID = 4, // Android
// IOS = 5, // iOS
// MOBILE_BROWSER = 6, // 移动端浏览器
// DESKTOP_BROWSER = 7,// 桌面端浏览器
// WECHAT_GAME = 8, // 微信小游戏
// BAIDU_MINI_GAME = 9,// 百度小游戏
// XIAOMI_QUICK_GAME = 10,// 小米快游戏
// ALIPAY_MINI_GAME = 11, // 支付宝小游戏
// BYTEDANCE_MINI_GAME = 12,// 字节跳动小游戏
// OPPO_MINI_GAME = 13,// OPPO小游戏
// VIVO_MINI_GAME = 14,// vivo小游戏
// HUAWEI_QUICK_GAME = 15,// 华为快游戏
// COCOSPLAY = 16, // Cocos Play
// LINKSURE_MINI_GAME = 17,// 连尚小游戏
// QTT_MINI_GAME = 18 // 趣头条小游戏
}

View File

@ -1,53 +1,91 @@
import { resources, JsonAsset, director, SpriteFrame, Sprite, Node, SpriteAtlas, sp } from 'cc';
import { LocalizedSprite } from '../i18n/LocalizedSprite';
import { resources, JsonAsset, director, SpriteFrame, SpriteAtlas, sp } from 'cc';
export class I18nManager {
private static _instance: I18nManager = null;
private static _instance: I18nManager;
spriteFrameCache: Map<string, SpriteFrame> = new Map();
spineCache: Map<string, sp.SkeletonData> = new Map();
_sfTasks = new Map<string, Promise<SpriteFrame>>();
languageData: Record<string, any> = {};
currentLanguage: string = 'en';
ready: boolean = false;
static get instance() {
if (this._instance) {
return this._instance;
}
this._instance = new I18nManager();
return this._instance;
return this._instance || (this._instance = new I18nManager());
}
private constructor() { }
// yield/await 风格:谁都可以 await且只加载一次
ensureI18nSprite(lang: string, name: string): Promise<SpriteFrame> {
const key = `${lang}_${name}`;
const path = `i18nSprite/${lang}/${name}/spriteFrame`;
const cached = this.spriteFrameCache.get(key);
if (cached) return Promise.resolve(cached);
const pending = this._sfTasks.get(key);
if (pending) return pending;
const task = new Promise<SpriteFrame>((resolve, reject) => {
resources.load(path, SpriteFrame, (err, sf) => {
this._sfTasks.delete(key);
if (err || !sf) return reject(err);
this.spriteFrameCache.set(key, sf);
resolve(sf);
});
});
this._sfTasks.set(key, task);
return task;
}
/**
*
* @param language
*
* @param language
* @param languageJson JSON资源
*/
public async init(language: string = 'en', languageJson: JsonAsset): Promise<void> {
public async init(language: string = 'en', languageJson: JsonAsset = null): Promise<void> {
this.currentLanguage = language;
try {
if (languageJson) {
this.languageData = languageJson.json;
// 预加载并缓存图片资源
await this.preloadSpriteFrames();
await this.preloadSpriteFrameAltas();
await this.preloadSpineAssets(); // 新增预加载 spine 资源
this.ready = true;
} catch (error) {
}
}
getIsReady() {
return this.ready;
}
/**
*
*/
private async preloadSpriteFrames(): Promise<void> {
const imageNames = [
'loadingBg',
// 预加载资源(目前资源列表为空,可根据需要添加)
let okSprite = await this.preloadAssets('spriteFrame', [
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'29',
'30',
'98',
'99',
'Buy_5',
'sysgift_completed',
'sysgift_continue',
'sysgift_fbs',
@ -56,93 +94,72 @@ export class I18nManager {
'sysgift_symbols',
'sysgift_total',
'sysgift_win',
];
]);
let okAtlas = await this.preloadAssets('atlas', []);
let okSpine = await this.preloadAssets('spine', []);
for (const name of imageNames) {
const path = `i18nSprite/${this.currentLanguage}/${name}/spriteFrame`;
const cacheKey = `${this.currentLanguage}_${name}`;
if (!this.spriteFrameCache.has(cacheKey)) {
await new Promise<void>((resolve) => {
resources.load(path, SpriteFrame, (err, spriteFrame) => {
if (!err && spriteFrame) {
this.spriteFrameCache.set(cacheKey, spriteFrame);
this.ready = okSprite && okAtlas && okSpine;
} catch (error) {
console.error('I18nManager init failed:', error);
}
}
/**
*
* @param type
* @param names
*/
private async preloadAssets(type: 'spriteFrame' | 'atlas' | 'spine', names: string[]): Promise<boolean> {
let results = await Promise.all(names.map(name => this.loadAsset(type, name)));
return results.every(ok => ok);
}
/**
*
* @param type
* @param name
*/
private loadAsset(type: 'spriteFrame' | 'atlas' | 'spine', name: string): Promise<boolean> {
return new Promise(resolve => {
let cacheKey = `${this.currentLanguage}_${name}`;
if (type === 'spriteFrame') {
let path = `i18nSprite/${this.currentLanguage}/${name}/spriteFrame`;
resources.load(path, SpriteFrame, (err, asset) => {
if (!err && asset) {
this.spriteFrameCache.set(cacheKey, asset);
resolve(true);
} else {
console.warn(`[i18n] spriteFrame load failed: ${path}`, err?.message || err);
resolve(false);
}
resolve();
});
});
}
}
}
private async preloadSpriteFrameAltas(): Promise<void> {
const altasNames = [
`FreeSpinINOUT_${this.currentLanguage}`,
`BuyFeature_${this.currentLanguage}`,
`Others_${this.currentLanguage}`,
`SymbolsInfo_${this.currentLanguage}`,
]
for (const altasName of altasNames) {
const atlasPath = `i18nSprite/${this.currentLanguage}/${altasName}`;
// 加载图集并缓存其中的多个 SpriteFrame
await new Promise<void>((resolve) => {
resources.load(atlasPath, SpriteAtlas, (err, atlas) => {
} else if (type === 'atlas') {
let path = `i18nSprite/${this.currentLanguage}/${name}`;
resources.load(path, SpriteAtlas, (err, atlas) => {
if (!err && atlas) {
const spriteFrames = atlas.getSpriteFrames();
spriteFrames.forEach((frame, index) => {
let name = frame.name;
const cacheKey = `${this.currentLanguage}_${name}`;
this.spriteFrameCache.set(cacheKey, frame);
atlas.getSpriteFrames().forEach(frame => {
this.spriteFrameCache.set(`${this.currentLanguage}_${frame.name}`, frame);
});
resolve(true);
} else {
console.warn(`[i18n] atlas load failed: ${path}`, err?.message || err);
resolve(false);
}
});
} else if (type === 'spine') {
let path = `i18nSpine/${this.currentLanguage}/${name}`;
resources.load(path, sp.SkeletonData, (err, asset) => {
if (!err && asset) {
this.spineCache.set(cacheKey, asset);
resolve(true);
} else {
console.warn(`[i18n] spine load failed: ${path}`, err?.message || err);
resolve(false);
}
});
}
resolve();
});
});
}
}
// 添加预加载 Spine 资源的方法
private async preloadSpineAssets(): Promise<void> {
const spineNames = [
`WinWinWin_${this.currentLanguage}`,
];
for (const name of spineNames) {
const path = `i18nSprite/${this.currentLanguage}/${name}`;
const cacheKey = `${this.currentLanguage}_${name}`;
if (!this.spineCache.has(cacheKey)) {
await new Promise<void>((resolve) => {
resources.load(path, sp.SkeletonData, (err, spineData) => {
if (!err && spineData) {
this.spineCache.set(cacheKey, spineData);
}
resolve();
});
});
}
}
}
setSpriteFrame(node: Node, name: string) {
// 先尝试从缓存获取
const cacheKey = `${this.currentLanguage}_${name}`;
const cachedFrame = this.spriteFrameCache.get(cacheKey);
if (cachedFrame) {
const sprite = node.getComponent(Sprite);
if (sprite) {
sprite.spriteFrame = cachedFrame;
return;
}
}
// 如果缓存中没有,则使用原有逻辑
let spriteNode = node.getComponent(LocalizedSprite);
if (spriteNode) {
spriteNode.setSpriteName(name);
}
}
/**
@ -159,17 +176,21 @@ export class I18nManager {
/**
*
* @param key
* @returns
*/
public t(key: string): string {
const translation = this.languageData[this.currentLanguage]?.[key];
if (!translation) {
return key; // Return the key itself if translation is not found
return this.languageData[this.currentLanguage]?.[key] || key;
}
return translation;
public getSpriteFrame(spriteName: string): SpriteFrame {
let cacheKey = `${this.currentLanguage}_${spriteName}`;
let cachedFrame = this.spriteFrameCache.get(cacheKey);
return cachedFrame;
}
/**
*
*
*
*/
public updateSceneRenderers(): void {
if (!this.ready) {
@ -178,41 +199,23 @@ export class I18nManager {
}
let scene = director.getScene();
if (!scene || !scene.isValid) return;
if (!scene?.isValid) return;
const rootNodes = director.getScene()?.children || [];
const allLocalizedLabels: any[] = [];
const allLocalizedSprites: any[] = [];
// 收集所有本地化组件
let allLocalizedLabels = [];
let allLocalizedSprites = [];
rootNodes.forEach(node => {
scene.children.forEach(node => {
allLocalizedLabels.push(...node.getComponentsInChildren('LocalizedLabel'));
allLocalizedSprites.push(...node.getComponentsInChildren('LocalizedSprite'));
});
allLocalizedLabels.forEach(label => {
if (label.node.active) {
label.updateLabel();
}
});
allLocalizedSprites.forEach(sprite => {
if (sprite.node.active) {
sprite.updateSprite();
// 更新所有激活的本地化组件
[...allLocalizedLabels, ...allLocalizedSprites].forEach(component => {
if (component.node.active) {
// 调用对应的更新方法
component.updateLabel?.() || component.updateSprite?.();
}
});
}
}
// // 供插件查询当前语言使用
// const win = window as any;
// win._languageData = {
// get language() {
// return I18nManager.instance.currentLanguage;
// },
// init(lang: string) {
// I18nManager.instance.init(lang);
// },
// updateSceneRenderers() {
// I18nManager.instance.updateSceneRenderers();
// },
// };

View File

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

View File

@ -11,7 +11,7 @@
"6c48a": {
"importer": "texture",
"uuid": "fc4357cf-5f55-416c-b94a-b412108a32a7@6c48a",
"displayName": "logo",
"displayName": "logo_en",
"id": "6c48a",
"name": "texture",
"userData": {
@ -35,7 +35,7 @@
"f9941": {
"importer": "sprite-frame",
"uuid": "fc4357cf-5f55-416c-b94a-b412108a32a7@f9941",
"displayName": "logo",
"displayName": "logo_en",
"id": "f9941",
"name": "spriteFrame",
"userData": {

View File

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -11,7 +11,7 @@
"6c48a": {
"importer": "texture",
"uuid": "51ffde0b-ff7a-4e4e-b639-b58e4b55b73f@6c48a",
"displayName": "logo",
"displayName": "logo_zh",
"id": "6c48a",
"name": "texture",
"userData": {
@ -35,7 +35,7 @@
"f9941": {
"importer": "sprite-frame",
"uuid": "51ffde0b-ff7a-4e4e-b639-b58e4b55b73f@f9941",
"displayName": "logo",
"displayName": "logo_zh",
"id": "f9941",
"name": "spriteFrame",
"userData": {