audioManager.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { util } from './util';
  2. import { _decorator, Component, Node, AudioClip, sys, AudioSource, game, director } from "cc";
  3. import { StorageManager } from "./storageManager";
  4. import { resourceUtil } from "./resourceUtil";
  5. import { lodash } from './lodash';
  6. const { ccclass, property } = _decorator;
  7. interface AudioData {
  8. source: AudioSource;
  9. isMusic: boolean;
  10. }
  11. interface AudioDataMap {
  12. [name: string]: AudioData;
  13. }
  14. @ccclass("AudioManager")
  15. export class AudioManager {
  16. private _persistRootNode: Node = null!;
  17. private _audioSources: AudioSource[] = [];
  18. static _instance: AudioManager;
  19. dictWeaponSoundIndex: any = {};
  20. static get instance() {
  21. if (this._instance) {
  22. return this._instance;
  23. }
  24. this._instance = new AudioManager();
  25. return this._instance;
  26. }
  27. musicVolume: number = 0.8;
  28. soundVolume: number = 1;
  29. audios: AudioDataMap = {};
  30. arrSound: AudioData[] = [];
  31. init() {
  32. if (this._persistRootNode) return; //避免切换场景初始化报错
  33. this._persistRootNode = new Node('audio');
  34. director.getScene()!.addChild(this._persistRootNode);
  35. game.addPersistRootNode(this._persistRootNode)
  36. this.musicVolume = this.getAudioSetting(true) ? 0.8 : 0;
  37. this.soundVolume = this.getAudioSetting(false) ? 1 : 0;
  38. }
  39. private _getAudioSource(clip: AudioClip) {
  40. let result: AudioSource | undefined;
  41. for (let i = 0; i < this._audioSources.length; ++i) {
  42. let audioSource = this._audioSources[i];
  43. if (!audioSource.playing) {
  44. result = audioSource;
  45. break;
  46. }
  47. }
  48. if (!result) {
  49. result = this._persistRootNode.addComponent(AudioSource);
  50. this._audioSources.push(result);
  51. }
  52. result.node.off(AudioSource.EventType.ENDED);
  53. result.clip = clip;
  54. result.currentTime = 0;
  55. return result;
  56. }
  57. getAudioSetting(isMusic: boolean) {
  58. let state;
  59. if (isMusic) {
  60. state = StorageManager.instance.getGlobalData('music');
  61. } else {
  62. state = StorageManager.instance.getGlobalData('sound');
  63. }
  64. // console.log('Config for [' + (isMusic ? 'Music' : 'Sound') + '] is ' + state);
  65. return !state || state === 'true' ? true : false;
  66. }
  67. /**
  68. * 播放音乐
  69. * @param {String} name 音乐名称可通过constants.AUDIO_MUSIC 获取
  70. * @param {Boolean} loop 是否循环播放
  71. */
  72. playMusic(name: string, loop: boolean) {
  73. let path = 'audio/music/' + name;
  74. //微信特殊处理,除一开场的音乐,其余的放在子包里头
  75. // if (name !== 'click') {
  76. // path = path; //微信特殊处理,除一开场的音乐,其余的放在子包里头
  77. // }
  78. resourceUtil.loadRes(path, AudioClip, (err: any, clip: any) => {
  79. let source = this._getAudioSource(clip);
  80. let tmp: AudioData = {
  81. source,
  82. isMusic: true,
  83. };
  84. this.audios[name] = tmp;
  85. source.volume = this.musicVolume;
  86. source.loop = loop;
  87. source.play();
  88. });
  89. }
  90. /**
  91. * 播放音效
  92. * @param {String} name 音效名称可通过constants.AUDIO_SOUND 获取
  93. * @param {Boolean} loop 是否循环播放
  94. */
  95. playSound(name: string, loop: boolean = false) {
  96. if (!this.soundVolume) {
  97. return;
  98. }
  99. //音效一般是多个的,不会只有一个
  100. let path = 'audio/sound/';
  101. // if (name !== 'click') {
  102. // path = path; //微信特殊处理,除一开场的音乐,其余的放在子包里头
  103. // }
  104. resourceUtil.loadRes(path + name, AudioClip, (err: any, clip: any) => {
  105. let source = this._getAudioSource(clip);
  106. let tmp: AudioData = {
  107. source,
  108. isMusic: false,
  109. };
  110. this.arrSound.push(tmp);
  111. if (loop) {
  112. this.audios[name] = tmp;
  113. }
  114. source.volume = this.soundVolume;
  115. source.loop = loop;
  116. source.play();
  117. source.node.on(AudioSource.EventType.ENDED, () => {
  118. lodash.remove(this.arrSound, (obj: AudioData) => {
  119. return obj.source === tmp.source;
  120. });
  121. });
  122. });
  123. }
  124. stop(name: string) {
  125. if (this.audios.hasOwnProperty(name)) {
  126. let audio = this.audios[name];
  127. audio.source.stop();
  128. }
  129. }
  130. stopAll() {
  131. for (const i in this.audios) {
  132. if (this.audios.hasOwnProperty(i)) {
  133. let audio = this.audios[i];
  134. audio.source.stop();
  135. }
  136. }
  137. }
  138. getMusicVolume() {
  139. return this.musicVolume;
  140. }
  141. setMusic(flag: number) {
  142. this.musicVolume = flag;
  143. for (let item in this.audios) {
  144. if (this.audios.hasOwnProperty(item) && this.audios[item].isMusic) {
  145. // this.changeState(item, flag);
  146. let audio = this.audios[item];
  147. audio.source.volume = this.musicVolume;
  148. }
  149. }
  150. }
  151. //看广告时先将音乐暂停
  152. pauseAll() {
  153. console.log("pause all music!!!");
  154. for (let item in this.audios) {
  155. if (this.audios.hasOwnProperty(item)) {
  156. let audio = this.audios[item];
  157. audio.source.pause();
  158. }
  159. }
  160. }
  161. resumeAll() {
  162. for (let item in this.audios) {
  163. if (this.audios.hasOwnProperty(item)) {
  164. let audio = this.audios[item];
  165. audio.source.play();
  166. }
  167. }
  168. }
  169. openMusic() {
  170. this.setMusic(0.8);
  171. StorageManager.instance.setGlobalData('music', 'true');
  172. }
  173. closeMusic() {
  174. this.setMusic(0);
  175. StorageManager.instance.setGlobalData('music', 'false');
  176. }
  177. openSound() {
  178. this.setSound(1);
  179. StorageManager.instance.setGlobalData('sound', 'true');
  180. }
  181. closeSound() {
  182. this.setSound(0);
  183. StorageManager.instance.setGlobalData('sound', 'false');
  184. }
  185. setSound(flag: number) {
  186. this.soundVolume = flag;
  187. for (let item in this.audios) {
  188. if (this.audios.hasOwnProperty(item) && !this.audios[item].isMusic) {
  189. // this.changeState(item, flag);
  190. let audio = this.audios[item];
  191. audio.source.volume = this.soundVolume;
  192. }
  193. }
  194. for (let idx = 0; idx < this.arrSound.length; idx++) {
  195. let audio = this.arrSound[idx];
  196. audio.source.volume = this.soundVolume;
  197. }
  198. }
  199. stopSingleSound(name: string) {
  200. if (this.audios.hasOwnProperty(name) && !this.audios[name].isMusic) {
  201. let audio = this.audios[name];
  202. audio.source.stop();
  203. }
  204. }
  205. }