From 0152111f7c0efd895d376e4c0caaf9027549c865 Mon Sep 17 00:00:00 2001 From: dgflash Date: Sat, 4 Jul 2026 16:52:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=A8=A1=E6=9D=BF=E7=9A=84?= =?UTF-8?q?=E5=BA=9F=E5=BC=83=E6=96=B9=E6=B3=95=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=B1=A0=E5=9C=A8=E5=89=94=E9=99=A4Spine?= =?UTF-8?q?=E5=BA=93=E5=90=8E=E7=9A=84=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/core/common/audio/AudioManager.ts | 254 +++++++++--------- assets/module/common/CCBusiness.ts | 124 --------- assets/module/common/GameComponent.ts | 136 +--------- assets/module/common/part/GamePartNodePool.ts | 2 +- 4 files changed, 129 insertions(+), 387 deletions(-) diff --git a/assets/core/common/audio/AudioManager.ts b/assets/core/common/audio/AudioManager.ts index bd49499..3a9c044 100644 --- a/assets/core/common/audio/AudioManager.ts +++ b/assets/core/common/audio/AudioManager.ts @@ -1,127 +1,127 @@ -import type { AudioClip } from 'cc'; -import { Component } from 'cc'; -import { oops } from '../../Oops'; -import type { AudioEffect } from './AudioEffect'; -import { AudioEffectPool } from './AudioEffectPool'; -import { AudioEffectType } from './AudioEnum'; -import { AudioMusic } from './AudioMusic'; -import type { IAudioData, IAudioParams } from './IAudio'; - -/** - * 音频管理 - * @help https://gitee.com/dgflash/oops-framework/wikis/pages?sort_id=12037893&doc_id=2873565 - * @example - // 模块功能通过 oops.audio 调用 - oops.audio.playMusic("audios/nocturne"); - */ -export class AudioManager extends Component { - /** 背景音乐管理对象 */ - music: AudioMusic = null!; - /** 音效管理对象 */ - effect: AudioEffectPool = new AudioEffectPool(); - - /** 音乐管理状态数据 */ - private data: { [node: string]: IAudioData } = {}; - - /** - * 播放背景音乐 - * @param clip AudioClip 实例 - * @param params 音效参数 - */ - playMusic(clip: AudioClip, params?: IAudioParams) { - this.music?.play(clip, params); - } - - /** - * 播放音效 - * @param clip AudioClip 实例 - * @param params 音效参数 - */ - playEffect(clip: AudioClip, params?: IAudioParams): AudioEffect | null { - return this.effect?.play(clip, params) ?? null; - } - - /** 回收音效播放器 */ - putEffect(ae: AudioEffect) { - this.effect?.put(ae); - } - - /** 恢复当前暂停的音乐与音效播放 */ - resumeAll() { - this.music?.resume(); - this.effect?.resume(); - } - - /** 暂停当前音乐与音效的播放 */ - pauseAll() { - this.music?.pause(); - this.effect?.pause(); - } - - /** 停止当前音乐与音效的播放 */ - stopAll() { - this.music?.stop(); - this.effect?.stop(); - } - - /** 保存音乐音效的音量、开关配置数据到本地 */ - save() { - oops.storage.set('OopsFrameworkAudio', this.data); - } - - /** 本地加载音乐音效的音量、开关配置数据并设置到游戏中 */ - load() { - this.music = new AudioMusic(); - this.music.parent = this.node; - - this.data = oops.storage.getJson('OopsFrameworkAudio'); - if (this.data) { - this.setState(); - } - else { - this.setStateDefault(); - } - } - - private setState() { - //@ts-ignore - this.music.data = this.data; - //@ts-ignore - this.effect.data = this.data; - } - - /** 默认音乐配置数据 */ - private setStateDefault() { - this.data = {}; - for (const key in AudioEffectType) { - //@ts-ignore - const value = AudioEffectType[key]; - if (typeof value === 'string') { - this.data[value] = { switch: true, volume: 1 }; - switch (value) { - case AudioEffectType.Music: - //@ts-ignore - this.music.data = this.data; - this.music.setSwitch(true); - this.music.setVolume(1); - break; - default: - //@ts-ignore - this.effect.data = this.data; - this.effect.setSwitch(true, value); - this.effect.setVolume(1, value); - break; - } - } - } - this.save(); - } - - /** 组件销毁时停止所有音频 */ - onDestroy() { - this.stopAll(); - this.effect?.release(); - this.music = null!; - this.data = null!; - } -} +import type { AudioClip } from 'cc'; +import { Component } from 'cc'; +import { oops } from '../../Oops'; +import type { AudioEffect } from './AudioEffect'; +import { AudioEffectPool } from './AudioEffectPool'; +import { AudioEffectType } from './AudioEnum'; +import { AudioMusic } from './AudioMusic'; +import type { IAudioData, IAudioParams } from './IAudio'; + +/** + * 音频管理 + * @help https://gitee.com/dgflash/oops-framework/wikis/pages?sort_id=12037893&doc_id=2873565 + * @example + // 模块功能通过 oops.audio 调用 + oops.audio.playMusic("audios/nocturne"); + */ +export class AudioManager extends Component { + /** 背景音乐管理对象 */ + music: AudioMusic = null!; + /** 音效管理对象 */ + effect: AudioEffectPool = new AudioEffectPool(); + + /** 音乐管理状态数据 */ + private data: { [node: string]: IAudioData } = {}; + + /** + * 播放背景音乐 + * @param clip AudioClip 实例 + * @param params 音效参数 + */ + playMusic(clip: AudioClip, params?: IAudioParams) { + this.music?.play(clip, params); + } + + /** + * 播放音效 + * @param clip AudioClip 实例 + * @param params 音效参数 + */ + playEffect(clip: AudioClip, params?: IAudioParams): AudioEffect | null { + return this.effect?.play(clip, params) ?? null; + } + + /** 回收音效播放器 */ + putEffect(ae: AudioEffect) { + this.effect?.put(ae); + } + + /** 恢复当前暂停的音乐与音效播放 */ + resumeAll() { + this.music?.resume(); + this.effect?.resume(); + } + + /** 暂停当前音乐与音效的播放 */ + pauseAll() { + this.music?.pause(); + this.effect?.pause(); + } + + /** 停止当前音乐与音效的播放 */ + stopAll() { + this.music?.stop(); + this.effect?.stop(); + } + + /** 保存音乐音效的音量、开关配置数据到本地 */ + save() { + oops.storage.set('OopsFrameworkAudio', this.data); + } + + /** 本地加载音乐音效的音量、开关配置数据并设置到游戏中 */ + load() { + this.music = new AudioMusic(); + this.music.parent = this.node; + + this.data = oops.storage.getJson('OopsFrameworkAudio'); + if (this.data) { + this.setState(); + } + else { + this.setStateDefault(); + } + } + + private setState() { + //@ts-ignore + this.music.data = this.data; + //@ts-ignore + this.effect.data = this.data; + } + + /** 默认音乐配置数据 */ + private setStateDefault() { + this.data = {}; + for (const key in AudioEffectType) { + //@ts-ignore + const value = AudioEffectType[key]; + if (typeof value === 'string') { + this.data[value] = { switch: true, volume: 1 }; + switch (value) { + case AudioEffectType.Music: + //@ts-ignore + this.music.data = this.data; + this.music.setSwitch(true); + this.music.setVolume(1); + break; + default: + //@ts-ignore + this.effect.data = this.data; + this.effect.setSwitch(true, value); + this.effect.setVolume(1, value); + break; + } + } + } + this.save(); + } + + /** 组件销毁时停止所有音频 */ + onDestroy() { + this.stopAll(); + this.effect?.release(); + this.music = null!; + this.data = null!; + } +} diff --git a/assets/module/common/CCBusiness.ts b/assets/module/common/CCBusiness.ts index fc1661c..dd00068 100644 --- a/assets/module/common/CCBusiness.ts +++ b/assets/module/common/CCBusiness.ts @@ -1,4 +1,3 @@ -import type { ListenerFunc, ListenerFuncTyped } from '../../core/common/event/EventMessage'; import { GamePartEvent } from './part/GamePartEvent'; import { GamePartRegistry, GamePartKey, createPart } from './GamePartRegistry'; import type { CCEntity } from './CCEntity'; @@ -43,127 +42,4 @@ export class CCBusiness { // 清空实体引用,避免循环引用导致的内存泄漏 this._ent = null; } - - //#region ========== 兼容旧版本 API 如果是新项目可以把注释包起来的代码都删除 ========== - - /** - * 注册全局事件(强类型) - * @deprecated 请使用 this.event.watch() - * @param event 事件名(枚举) - * @param listener 处理事件的侦听器函数 - * @param object 侦听函数绑定的this对象 - */ - watch(event: K, listener: ListenerFuncTyped, object: any): void { - this.event.watch(event, listener, object); - } - - /** - * 监听一次事件,事件响应后,该监听自动移除(强类型) - * @deprecated 请使用 this.event.watchOnce() - * @param event 事件名(枚举) - * @param listener 事件触发回调方法 - * @param object 侦听函数绑定的this对象 - */ - watchOnce(event: K, listener: ListenerFuncTyped, object: any): void { - this.event.watchOnce(event, listener, object); - } - - /** - * 移除全局事件(强类型) - * @deprecated 请使用 this.event.unwatch() - * @param event 事件名(枚举) - * @param listener 处理事件的侦听器函数(可选) - * @param object 侦听函数绑定的this对象(可选) - */ - unwatch(event: K, listener?: ListenerFuncTyped, object?: any): void { - this.event.unwatch(event, listener, object); - } - - /** - * 触发强类型全局事件 - * @deprecated 请使用 this.event.emit() - * @param event 事件名(枚举) - * @param data 事件数据 - */ - emit(event: K, data?: OopsFramework.TypedEventMap[K]): void { - this.event.emit(event, data); - } - - /** - * 触发强类型异步全局事件(严格类型检查) - * @deprecated 请使用 this.event.emitAsync() - * @param event 事件名(枚举) - * @param data 事件数据(必须完全匹配类型定义) - */ - emitAsync(event: K, data: OopsFramework.TypedEventMap[K]): Promise { - return this.event.emitAsync(event, data); - } - - /** - * 注册全局事件 - * @deprecated 请使用 this.event.on() - * @param event 事件名 - * @param listener 处理事件的侦听器函数 - * @param object 侦听函数绑定的this对象 - */ - on(event: string, listener: ListenerFunc, object: object) { - this.event.on(event, listener, object); - } - - /** - * 监听一次事件,事件响应后,该监听自动移除 - * @deprecated 请使用 this.event.once() - * @param event 事件名 - * @param listener 事件触发回调方法 - * @param object 侦听函数绑定的this对象 - */ - once(event: string, listener: ListenerFunc, object: object) { - this.event.once(event, listener, object); - } - - /** - * 移除全局事件 - * @deprecated 请使用 this.event.off() - * @param event 事件名 - * @param listener 处理事件的侦听器函数(可选) - * @param object 侦听函数绑定的this对象(可选) - */ - off(event: string, listener?: ListenerFunc, object?: object) { - this.event.off(event, listener, object); - } - - /** - * 触发全局事件 - * @deprecated 请使用 this.event.dispatchEvent() - * @param event 事件名 - * @param args 事件参数 - */ - dispatchEvent(event: string, ...args: unknown[]) { - this.event.dispatchEvent(event, ...args); - } - - /** - * 触发全局事件,支持同步与异步处理 - * @deprecated 请使用 this.event.dispatchEventAsync() - * @param event 事件名 - * @param args 事件参数 - */ - dispatchEventAsync(event: string, ...args: unknown[]): Promise { - return this.event.dispatchEventAsync(event, ...args); - } - - /** - * 批量设置全局事件 - * @deprecated 请使用 this.event.setEvent() - * @example - * this.setEvent("onGlobal"); - * this.dispatchEvent("onGlobal", "全局事件"); - * - * onGlobal(event: string, args: unknown) { console.log(args) }; - */ - protected setEvent(...args: string[]) { - this.event.setEvent(...args); - } - - //#endregion } diff --git a/assets/module/common/GameComponent.ts b/assets/module/common/GameComponent.ts index 7399098..d742e52 100644 --- a/assets/module/common/GameComponent.ts +++ b/assets/module/common/GameComponent.ts @@ -1,10 +1,6 @@ -import type { Asset, EventKeyboard, Node, Sprite, __private } from 'cc'; +import type { Node } from 'cc'; import { Component, _decorator } from 'cc'; -import type { AudioEffect } from '../../core/common/audio/AudioEffect'; -import type { IAudioParams } from '../../core/common/audio/IAudio'; import type { ListenerFunc, ListenerFuncTyped } from '../../core/common/event/EventMessage'; -import type { AssetType, CompleteCallback, Paths, ProgressCallback } from '../../core/common/loader/ResLoader'; -import { resLoader } from '../../core/common/loader/ResLoader'; import { oops } from '../../core/Oops'; import type { GamePartAudio } from './part/GamePartAudio'; import type { GamePartButton } from './part/GamePartButton'; @@ -162,134 +158,4 @@ export class GameComponent extends Component { return this.nodes.createPrefabNode(path, bundleName); } //#endregion - - //#region 资源加载管理(兼容旧版本) - /** @deprecated 请使用 this.res.getRes() */ - getRes(path: string, type?: __private.__types_globals__Constructor | null, bundleName?: string): T | null { - return this.res.get(path, type, bundleName); - } - - /** @deprecated 请使用 this.res.load() */ - async load(bundleName: string, paths: Paths | AssetType, type?: AssetType): Promise { - return this.res.load(bundleName, paths, type); - } - - /** @deprecated 请使用 this.res.loadAny() */ - loadAny(bundleName: string | string[], paths: string[] | ProgressCallback, onProgress?: ProgressCallback | CompleteCallback, onComplete?: CompleteCallback): void { - this.res.loadAny(bundleName, paths, onProgress, onComplete); - } - - /** @deprecated 请使用 this.res.loadDir() */ - loadDir(bundleName: string, dir: string, type: AssetType, onProgress: ProgressCallback, onComplete: CompleteCallback): void; - loadDir(bundleName: string, dir: string, onProgress: ProgressCallback, onComplete: CompleteCallback): void; - loadDir(bundleName: string, dir: string, onComplete?: CompleteCallback): void; - loadDir(bundleName: string, dir: string, type: AssetType, onComplete?: CompleteCallback): void; - loadDir(dir: string, type: AssetType, onProgress: ProgressCallback, onComplete: CompleteCallback): void; - loadDir(dir: string, onProgress: ProgressCallback, onComplete: CompleteCallback): void; - loadDir(dir: string, onComplete?: CompleteCallback): void; - loadDir(dir: string, type: AssetType, onComplete?: CompleteCallback): void; - loadDir( - bundleName: string, - dir?: string | AssetType | ProgressCallback | CompleteCallback, - type?: AssetType | ProgressCallback | CompleteCallback, - onProgress?: ProgressCallback | CompleteCallback, - onComplete?: CompleteCallback, - ): void { - this.res.loadDir(bundleName, dir, type, onProgress, onComplete); - } - - /** @deprecated 请使用 this.res.setSprite() */ - async setSprite(target: Sprite, path: string, bundle: string = resLoader.defaultBundleName): Promise { - return this.res.setSprite(target, path, bundle); - } - //#endregion - - //#region 音频播放管理(兼容旧版本) - /** @deprecated 请使用 await this.audio.playMusic() */ - async playMusic(url: string, params?: IAudioParams): Promise { - return this.audio.playMusic(url, params); - } - - /** @deprecated 请使用 await this.audio.playEffect() */ - playEffect(url: string, params?: IAudioParams): Promise { - return this.audio.playEffect(url, params); - } - //#endregion - - //#region 游戏逻辑事件(兼容旧版本) - /** @deprecated 请使用 this.button.setButton() */ - protected setButton(bindRootEvent = true): void { - this.button.bind(bindRootEvent); - } - - /** @deprecated 请使用 this.event.setEvent() */ - protected setEvent(...args: string[]): void { - this.event.setEvent(...args); - } - - /** @deprecated 请使用 this.keyboard.setKeyboard() */ - setKeyboard(on: boolean): void { - if (on) { - this.keyboard.setKeyboard(true, { - onKeyDown: this.onKeyDown.bind(this), - onKeyUp: this.onKeyUp.bind(this), - onKeyPressing: this.onKeyPressing.bind(this) - }); - } - else { - this.keyboard.setKeyboard(false); - } - } - - /** @deprecated 请使用 this.keyboard.setKeyboard() 传入 callbacks */ - protected onKeyDown(event: EventKeyboard): void { } - - /** @deprecated 请使用 this.keyboard.setKeyboard() 传入 callbacks */ - protected onKeyUp(event: EventKeyboard): void { } - - /** @deprecated 请使用 this.keyboard.setKeyboard() 传入 callbacks */ - protected onKeyPressing(event: EventKeyboard): void { } - - /** @deprecated 请使用 this.event.setGameShow() */ - protected setGameShow(): void { - this.event.setGameShow(this.onGameShow.bind(this)); - } - - /** @deprecated 请使用 this.event.setGameHide() */ - protected setGameHide(): void { - this.event.setGameHide(this.onGameHide.bind(this)); - } - - /** @deprecated 请使用 this.event.setGameResize() */ - protected setGameResize(): void { - this.event.setGameResize(this.onGameResize.bind(this)); - } - - /** @deprecated 请使用 this.event.setGameFullScreen() */ - protected setGameFullScreen(): void { - this.event.setGameFullScreen(this.onGameFullScreen.bind(this)); - } - - /** @deprecated 请使用 this.event.setGameOrientation() */ - protected setGameOrientation(): void { - this.event.setGameOrientation(this.onGameOrientation.bind(this)); - } - - /** @deprecated 请配合 setGameShow() 使用 */ - protected onGameShow(): void { } - - /** @deprecated 请配合 setGameHide() 使用 */ - protected onGameHide(): void { } - - /** @deprecated 请配合 setGameResize() 使用 */ - protected onGameResize(): void { } - - /** @deprecated 请配合 setGameFullScreen() 使用 */ - protected onGameFullScreen(): void { } - - /** @deprecated 请配合 setGameOrientation() 使用 */ - protected onGameOrientation(): void { } - //#endregion - - //#endregion } diff --git a/assets/module/common/part/GamePartNodePool.ts b/assets/module/common/part/GamePartNodePool.ts index 9de6878..fcb8ec9 100644 --- a/assets/module/common/part/GamePartNodePool.ts +++ b/assets/module/common/part/GamePartNodePool.ts @@ -171,7 +171,7 @@ export class GamePartNodePool extends GamePartBase { /** 获取 IAutoRelease 组件(查找或自动添加) */ private _getAutoRelease(node: Node): IAutoRelease | null { - const spine = node.getComponent(sp.Skeleton); + const spine = sp && node.getComponent(sp.Skeleton); if (spine) return node.addComponent(SpineEffectAutoRelease); const anim = node.getComponent(Animation); if (anim) return node.addComponent(AnimationEffectAutoRelease);