AudioManager.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /** @format */
  2. import {Data, Mgr} from '../GameControl'
  3. import {GAME_TYPE, LOCAL} from '../enums/Enum'
  4. import {ccUtils} from '../utils/ccUtils'
  5. import Bundle = cc.AssetManager.Bundle
  6. export class AudioManager {
  7. private bgmVolume = 1
  8. private sfxVolume = 1
  9. private bgmAudioID = -1
  10. private bgmAudioClips: any
  11. private sfxAudioClips: any
  12. private sfxAudioClipsLoading: any
  13. private playedAudio = new Map<number, string>()
  14. private curBgmUrl = null
  15. private curSfxUrl = null
  16. public isPlayRandomBgm: boolean = false // 随机播放背景音乐
  17. private curRandom: any = -1 // 随机播放背景索引
  18. private repeatPlayID: any = 0 // 背景音乐循环倒计时
  19. private soundBundle: Bundle = null
  20. public async init() {
  21. cc.audioEngine.stopAll()
  22. cc.audioEngine.uncacheAll()
  23. this.bgmVolume = Mgr.storage.getNumber(LOCAL.bgmVolume, 1)
  24. this.sfxVolume = Mgr.storage.getNumber(LOCAL.sfxVolume, 1)
  25. this.bgmAudioClips = {}
  26. this.sfxAudioClips = {}
  27. this.sfxAudioClipsLoading = {}
  28. this.soundBundle = await ccUtils.getBundleAsync('sound')
  29. return this.soundBundle != null
  30. }
  31. public getUrl(url: string) {
  32. // return `sound/${url}`
  33. return url
  34. }
  35. /**
  36. *
  37. * @param url
  38. * @param isSameStop 再次播放当前音乐是否重新开始 默认重新开始
  39. */
  40. public playBGM(url: string, isSameStop = false) {
  41. this.isPlayRandomBgm = false
  42. this.curRandom = -1
  43. const audioUrl = this.getUrl(url)
  44. if (isSameStop && this.curBgmUrl == audioUrl) {
  45. return
  46. }
  47. this.curBgmUrl = audioUrl
  48. this.stopLastBGM()
  49. if (this.bgmVolume > 0) {
  50. if (this.bgmAudioClips[audioUrl]) {
  51. cc.audioEngine.setMusicVolume(this.bgmVolume)
  52. this.bgmAudioID = cc.audioEngine.playMusic(this.bgmAudioClips[audioUrl], true)
  53. } else {
  54. this.soundBundle.load(audioUrl, cc.AudioClip, (err, audioClip: cc.AudioClip) => {
  55. if (!err) {
  56. this.bgmAudioClips[audioUrl] = audioClip
  57. cc.audioEngine.setMusicVolume(this.bgmVolume)
  58. this.bgmAudioID = cc.audioEngine.playMusic(audioClip, true)
  59. }
  60. })
  61. }
  62. }
  63. }
  64. public playRandomBGM() {
  65. if (this.isPlayRandomBgm) {
  66. return
  67. }
  68. this.isPlayRandomBgm = true
  69. const audioUrl = this.getRandomUrl()
  70. this.curBgmUrl = audioUrl
  71. this.stopLastBGM()
  72. if (this.bgmVolume > 0) {
  73. let callback = () => {
  74. this.bgmAudioID = cc.audioEngine.playMusic(this.bgmAudioClips[audioUrl], false)
  75. const dur = cc.audioEngine.getDuration(this.bgmAudioID)
  76. cc.audioEngine.setMusicVolume(this.bgmVolume)
  77. this.repeatPlayID = setTimeout(() => {
  78. this.isPlayRandomBgm = false
  79. this.playRandomBGM()
  80. }, dur * 1000)
  81. }
  82. if (this.bgmAudioClips[audioUrl]) {
  83. callback()
  84. } else {
  85. this.soundBundle.load(audioUrl, cc.AudioClip, (err, audioClip: cc.AudioClip) => {
  86. if (!err) {
  87. this.bgmAudioClips[audioUrl] = audioClip
  88. callback()
  89. }
  90. })
  91. }
  92. }
  93. }
  94. private getRandomUrl() {
  95. const ram = Math.randomRangeInt(1, 3)
  96. if (ram == this.curRandom) {
  97. // 同一首背景音乐 重新随机
  98. return this.getRandomUrl()
  99. }
  100. this.curRandom = ram
  101. return this.getUrl(`common_bgm${ram}`)
  102. }
  103. public stopLastBGM() {
  104. if (this.repeatPlayID) {
  105. clearTimeout(this.repeatPlayID)
  106. }
  107. if (cc.audioEngine.isMusicPlaying()) {
  108. cc.audioEngine.stopMusic()
  109. }
  110. }
  111. public stopBGM() {
  112. this.curBgmUrl = ''
  113. this.stopLastBGM()
  114. }
  115. public playSFX(url: string, bundle?: Bundle, noStopCurSfx?: boolean, callFuc?: Function) {
  116. let audioUrl = this.getUrl(url)
  117. let audioUrlKey = audioUrl
  118. if (bundle) audioUrlKey += bundle.name
  119. if (this.curSfxUrl && !noStopCurSfx) {
  120. this.stopSFX(this.curSfxUrl)
  121. }
  122. if (!url) return
  123. this.curSfxUrl = url
  124. if (this.sfxVolume > 0) {
  125. if (this.sfxAudioClips[audioUrlKey]) {
  126. const playId = cc.audioEngine.playEffect(this.sfxAudioClips[audioUrlKey], false)
  127. cc.audioEngine.setEffectsVolume(this.sfxVolume)
  128. if (callFuc) {
  129. cc.audioEngine.setFinishCallback(playId, callFuc)
  130. }
  131. this.playedAudio.set(playId, audioUrl)
  132. } else {
  133. if (this.sfxAudioClipsLoading[audioUrlKey]) return
  134. this.sfxAudioClipsLoading[audioUrlKey] = true
  135. let tmp = bundle ? bundle : this.soundBundle
  136. let onCompleteFuc = (err, audioClip: cc.AudioClip) => {
  137. this.sfxAudioClipsLoading[audioUrlKey] = false
  138. if (!err) {
  139. this.sfxAudioClips[audioUrlKey] = audioClip
  140. const playId = cc.audioEngine.playEffect(audioClip, false)
  141. cc.audioEngine.setEffectsVolume(this.sfxVolume)
  142. if (callFuc) {
  143. cc.audioEngine.setFinishCallback(playId, callFuc)
  144. }
  145. this.playedAudio.set(playId, audioUrl)
  146. }
  147. }
  148. tmp.load(audioUrl, cc.AudioClip, onCompleteFuc)
  149. }
  150. }
  151. }
  152. public stopSFX(url: string) {
  153. const audioUrl = this.getUrl(url)
  154. let Ids = this.playedAudio.findKeyByValue(audioUrl)
  155. Ids.forEach(value => {
  156. if (value != -1) {
  157. cc.audioEngine.stop(value)
  158. this.playedAudio.delete(value)
  159. }
  160. })
  161. }
  162. public setSFXVolume(v: number) {
  163. if (this.sfxVolume !== v) {
  164. Mgr.storage.set(LOCAL.sfxVolume, v)
  165. this.sfxVolume = v
  166. }
  167. }
  168. public setBGMVolume(v: number, force = false) {
  169. if (this.bgmAudioID >= 0) {
  170. if (v > 0) {
  171. cc.audioEngine.resume(this.bgmAudioID)
  172. } else {
  173. cc.audioEngine.pause(this.bgmAudioID)
  174. }
  175. }
  176. if (this.bgmVolume !== v || force) {
  177. Mgr.storage.set(LOCAL.bgmVolume, v)
  178. this.bgmVolume = v
  179. if (v > 0 && this.bgmAudioID >= 0) {
  180. cc.audioEngine.setVolume(this.bgmAudioID, v)
  181. }
  182. }
  183. }
  184. public pauseAll() {
  185. cc.audioEngine.pauseAll()
  186. }
  187. public stopAllEffects() {
  188. cc.audioEngine.stopAllEffects()
  189. }
  190. public resumeAll() {
  191. cc.audioEngine.resumeAll()
  192. }
  193. public onViewHide() {
  194. this.playedAudio.forEach((value, key) => {
  195. if (key != -1) {
  196. if (key == this.bgmAudioID) {
  197. cc.audioEngine.pause(key)
  198. } else {
  199. cc.audioEngine.stop(key)
  200. this.playedAudio.delete(key)
  201. }
  202. }
  203. })
  204. }
  205. public onViewShow() {
  206. if (this.bgmAudioID > 0 && this.bgmVolume > 0) {
  207. cc.audioEngine.resume(this.bgmAudioID)
  208. }
  209. }
  210. }