123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- import { AssetManager, assetManager, AudioClip, AudioSource} from "cc";
- import { constants } from "../data/constants";
- import settingData from "../data/settingData";
- /**音乐播放数据结构*/
- export interface IAudioData {
- clip: AudioClip;//音乐片段
- audioSource: AudioSource;//音乐具柄
- path: string //音乐名称路径
- playStatus: boolean //播放状态
- totalTime: number;//音乐总长度时间
- time_id: number;//定时器句柄
- t: number;//统计记时
- }
- class audioManager {
- private static instance: audioManager = null;
- //缓存的音乐片段和音乐具柄一体 是为了 同时播放多个攻击音效
- private cachedAudioArr: Array<IAudioData> = [];
- private bundleAudios: AssetManager.Bundle = null;
- //单例
- public static ins() {
- if (!this.instance) {
- this.instance = new audioManager();
- }
- return this.instance;
- }
- /**
- * 预加载音乐
- */
- public async initialize(): Promise<void> {
- this.bundleAudios = await new Promise((resolve: Function, reject: Function) => {
- assetManager.loadBundle('audios', (err: Error, bundle: AssetManager.Bundle) => {
- if (err) {
- reject(err);
- } else {
- resolve(bundle);
- }
- });
- });
- for (let path of Object.values(constants.audios)) {
- if(path == "") continue;
- let audioClip: AudioClip = await new Promise((resolve: Function, reject: Function) => {
- this.bundleAudios.load(path, AudioClip, (err: Error, clip: AudioClip) => {
- if (err) {
- reject(err);
- } else {
- resolve(clip);
- }
- });
- });
- this.cachedAudioArr.push({
- clip: audioClip,
- audioSource: null,
- path: path ,
- playStatus: false,
- totalTime: audioClip.getDuration(),
- time_id: -1,
- t: 0
- });
- }
- window["youxi"] = {
- SoundManager: {
- pauseAll: () => {
- settingData.data.bg_music_status = false;
- settingData.data.sound_status = false;
- settingData.saveToCache();
- if(settingData.data.bg_music_status){
- this.play(constants.audios.bg_music,true);
- }else{
- this.stop(constants.audios.bg_music);
- }
- },
- resumeAll: () => {
- settingData.data.bg_music_status = true;
- settingData.data.sound_status = true;
- settingData.saveToCache();
- }
- },
- TargetedAds: {
- open: () => {
- },
- clos: () => {
- }
- },
- Fps: {
- setfps: (value) => {
- }
- }
- };
- }
- /**
- * 播放音效 不会两个相同的音乐重复播放 可以停止
- * @param path 播放音乐的路径
- * @param loop 是否循环播放
- * @param s 如果为-1则最大音量立即播放 如果为其他则慢慢音量递增起来播放
- * @returns
- */
- private bgVolumeMax: number = 0.8;
- public play(path: string,loop: boolean = false,s: number = -1): void {
- if(!settingData.data.bg_music_status)return;
- const fun = (audio:IAudioData)=>{
- if(audio.audioSource == null){
- audio.audioSource = this.audioSourceLoop(loop);
- }
- if(audio.playStatus)return;
- audio.audioSource.clip = a.clip;
- if(audio.time_id){
- clearInterval(audio.time_id);
- if(audio.audioSource.playing){
- audio.audioSource.pause();
- }
- }
- audio.audioSource.play();
- if(s == -1){
- audio.audioSource.volume = this.bgVolumeMax;
- }else{
- audio.t = 0;
- audio.audioSource.volume = 0;
- let interval: number = ((1 / s) / 10);
- audio.time_id = setInterval(()=>{
- audio.t += interval;
- let volume: number = audio.t / s;
- if(volume >= this.bgVolumeMax){
- clearInterval(audio.time_id);
- }else{
- audio.audioSource.volume = volume;
- }
- },interval * 1000);
- }
- audio.playStatus = true;
- }
- let a: IAudioData = this.cachedAudioArr.find(e =>e.path == path);
- if(a){
- fun(a);
- }else{
- this.bundleAudios.load(path, AudioClip, (err, clip)=>{
- if (err) {
- console.warn(err);
- }else{
- let data: IAudioData = {
- path: path,
- clip: clip,
- audioSource: null,
- playStatus: false,
- totalTime: clip.getDuration(),
- time_id: -1,
- t: 0
- };
- fun(data);
- }
- });
- }
- }
- /**
- * 单次播放一次的音效 可以停止
- * @param path 音乐路径
- * @param overlap 是否可以重复两个同一个音效连续播放
- * @returns
- */
- public playOneShot(path: string,overlap: boolean = true): void {
- if(!settingData.data.sound_status)return;
- const fun = (audio:IAudioData)=>{
- if(overlap || !audio.playStatus){
- if(audio.audioSource == null){
- audio.audioSource = this.audioSourceLoop(false);
- }
- audio.audioSource.clip = audio.clip;
- audio.audioSource.play();
- audio.audioSource.volume = 1;
- audio.playStatus = true;
- }
- }
- let a: IAudioData = this.cachedAudioArr.find(e =>e.path == path);
- if(a){
- fun(a);
- }else{
- this.bundleAudios.load(path, AudioClip, (err, clip)=>{
- if (err) {
- console.warn(err);
- }else{
- let data: IAudioData = {
- path: path,
- clip: clip,
- audioSource: null,
- playStatus: false,
- totalTime: clip.getDuration(),
- time_id: -1,
- t: 0
- };
- this.cachedAudioArr.push(data);
- fun(data);
- }
- });
- }
- }
- /**
- * 停止播放音效
- * @param path 音效路径名称
- * @param s 为-1立即停止播放 非-1则是慢慢的声音越来越小的停止播放
- * @returns
- */
- public stop(path: string,s: number = -1): void {
- let audio: IAudioData = this.cachedAudioArr.find(e =>e.path == path);
- if(audio){
- if(!audio.audioSource)return;
- if(!audio.audioSource.playing)return;
- if(audio.time_id){
- clearInterval(audio.time_id);
- }
- let audioSource = audio.audioSource;
- if(s == -1){
- audioSource?.pause();
- }else{
- audio.t = 0;
- let interval: number = ((1 / s) / 10);
- audio.time_id = setInterval(()=>{
- if(audioSource){
- audio.t += interval;
- let volume: number = this.bgVolumeMax - audio.t / s;
- if(volume <= 0){
- clearInterval(audio.time_id);
- audioSource?.pause();
- }else{
- audioSource.volume = volume <= 0 ? 0 :volume;
- }
- }
- },interval * 1000);
- }
- audio.playStatus = false;
- }
- }
- /**
- * 加载音效
- * @param loop 是否循环
- */
- public audioSourceLoop(loop: boolean): AudioSource{
- let audioSource: AudioSource = null;
- if(loop){//播放单次的时候具柄
- audioSource = this.getAudioSource(null,true,this.bgVolumeMax)
- }else{//循环播放的时候具柄
- audioSource = this.getAudioSource(null,false,1);
- }
- return audioSource;
- }
- /**
- * 得到一个播放音乐的控制类
- * @param clip 音效片段
- * @param loop 是否循环
- * @param volume 音量
- * @returns 播放类
- */
- public getAudioSource(clip: AudioClip = null, loop: boolean = false, volume: number = 1): AudioSource{
- let audioSource: AudioSource = new AudioSource();
- if(clip){
- audioSource.clip = clip;
- }
- audioSource.loop = loop;
- audioSource.volume = volume;
- return audioSource;
- }
- }
- export default audioManager.ins();
|