Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / manager / SoundManager.cs
@小李xl 小李xl on 11 Jun 2023 6 KB 完善音效
  1. using System;
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 音频总线 区分不同的声音 添加声音效果 目前只有背景音乐 和音效 两个bus
  7. /// </summary>
  8. public enum BUS
  9. {
  10. BGM = 0,
  11. SFX = 1
  12. }
  13.  
  14. /// <summary>
  15. /// 声音管理 背景音乐管理 音效
  16. /// </summary>
  17. public partial class SoundManager
  18. {
  19. private static Stack<AudioPlayer2D> _streamPlayer2DStack = new Stack<AudioPlayer2D>();
  20. private static Stack<AudioPlayer> _streamPlayerStack = new Stack<AudioPlayer>();
  21.  
  22. /// <summary>
  23. /// 2D音频播放节点
  24. /// </summary>
  25. private partial class AudioPlayer2D : AudioStreamPlayer2D
  26. {
  27. private float _delayTimer = -1;
  28. public override void _Ready()
  29. {
  30. Finished += OnPlayFinish;
  31. }
  32.  
  33. /// <summary>
  34. /// 延时播放
  35. /// </summary>
  36. public void DelayPlay(float time)
  37. {
  38. _delayTimer = time;
  39. }
  40.  
  41. /// <summary>
  42. /// 停止播放, 并回收节点
  43. /// </summary>
  44. public void StopPlay()
  45. {
  46. Stop();
  47. OnPlayFinish();
  48. }
  49. public override void _Process(double delta)
  50. {
  51. if (_delayTimer > 0)
  52. {
  53. _delayTimer -= (float)delta;
  54. if (_delayTimer <= 0)
  55. {
  56. Play();
  57. }
  58. }
  59. }
  60. private void OnPlayFinish()
  61. {
  62. _delayTimer = -1;
  63. RecycleAudioPlayer2D(this);
  64. }
  65. }
  66.  
  67. /// <summary>
  68. /// 音频播放节点
  69. /// </summary>
  70. private partial class AudioPlayer : AudioStreamPlayer
  71. {
  72. public override void _Ready()
  73. {
  74. Finished += OnPlayFinish;
  75. }
  76.  
  77. /// <summary>
  78. /// 停止播放, 并回收节点
  79. /// </summary>
  80. public void StopPlay()
  81. {
  82. Stop();
  83. OnPlayFinish();
  84. }
  85. private void OnPlayFinish()
  86. {
  87. GetParent().RemoveChild(this);
  88. Stream = null;
  89. Playing = false;
  90. RecycleAudioPlayer(this);
  91. }
  92. }
  93.  
  94. /// <summary>
  95. /// 播放声音 用于bgm
  96. /// </summary>
  97. /// <param name="soundName">bgm路径</param>
  98. /// <param name="volume">音量</param>
  99. public static AudioStreamPlayer PlayMusic(string soundName, float volume = 0.5f)
  100. {
  101. var sound = ResourceManager.Load<AudioStream>(soundName);
  102. var soundNode = GetAudioPlayerInstance();
  103. GameApplication.Instance.GlobalNodeRoot.AddChild(soundNode);
  104. soundNode.Stream = sound;
  105. soundNode.Bus = Enum.GetName(typeof(BUS), 0);
  106. soundNode.VolumeDb = volume;
  107. soundNode.Play();
  108. return soundNode;
  109. }
  110.  
  111. /// <summary>
  112. /// 添加并播放音效 用于音效
  113. /// </summary>
  114. /// <param name="soundName">音效文件路径</param>
  115. /// <param name="volume">音量 (0 - 1)</param>
  116. public static AudioStreamPlayer PlaySoundEffect(string soundName, float volume = 1f)
  117. {
  118. var sound = ResourceManager.Load<AudioStream>(soundName);
  119. var soundNode = GetAudioPlayerInstance();
  120. GameApplication.Instance.GlobalNodeRoot.AddChild(soundNode);
  121. soundNode.Stream = sound;
  122. soundNode.Bus = Enum.GetName(typeof(BUS), 1);
  123. soundNode.VolumeDb = Mathf.LinearToDb(Mathf.Clamp(volume, 0, 1));
  124. soundNode.Play();
  125. return soundNode;
  126. }
  127.  
  128. /// <summary>
  129. /// 在指定的节点下播放音效 用于音效
  130. /// </summary>
  131. /// <param name="soundName">音效文件路径</param>
  132. /// <param name="pos">发声节点所在全局坐标</param>
  133. /// <param name="volume">音量 (0 - 1)</param>
  134. /// <param name="target">挂载节点, 为null则挂载到房间根节点下</param>
  135. public static AudioStreamPlayer2D PlaySoundEffectPosition(string soundName, Vector2 pos, float volume = 1f, Node2D target = null)
  136. {
  137. var sound = ResourceManager.Load<AudioStream>(soundName);
  138. var soundNode = GetAudioPlayer2DInstance();
  139. if (target != null)
  140. {
  141. target.AddChild(soundNode);
  142. }
  143. else
  144. {
  145. GameApplication.Instance.GlobalNodeRoot.AddChild(soundNode);
  146. }
  147. soundNode.GlobalPosition = pos;
  148. soundNode.Stream = sound;
  149. soundNode.Bus = Enum.GetName(typeof(BUS), 1);
  150. soundNode.VolumeDb = Mathf.LinearToDb(Mathf.Clamp(volume, 0, 1));
  151. soundNode.Play();
  152. return soundNode;
  153. }
  154.  
  155. /// <summary>
  156. /// 在指定的节点下延时播放音效 用于音效
  157. /// </summary>
  158. /// <param name="soundName">音效文件路径</param>
  159. /// <param name="pos">发声节点所在全局坐标</param>
  160. /// <param name="delayTime">延时时间</param>
  161. /// <param name="volume">音量 (0 - 1)</param>
  162. /// <param name="target">挂载节点, 为null则挂载到房间根节点下</param>
  163. public static AudioStreamPlayer2D PlaySoundEffectPositionDelay(string soundName, Vector2 pos, float delayTime, float volume = 1f, Node2D target = null)
  164. {
  165. var sound = ResourceManager.Load<AudioStream>(soundName);
  166. var soundNode = GetAudioPlayer2DInstance();
  167. if (target != null)
  168. {
  169. target.AddChild(soundNode);
  170. }
  171. else
  172. {
  173. GameApplication.Instance.GlobalNodeRoot.AddChild(soundNode);
  174. }
  175. soundNode.GlobalPosition = pos;
  176. soundNode.Stream = sound;
  177. soundNode.Bus = Enum.GetName(typeof(BUS), 1);
  178. soundNode.VolumeDb = Mathf.LinearToDb(Mathf.Clamp(volume, 0, 1));
  179. soundNode.DelayPlay(delayTime);
  180. return soundNode;
  181. }
  182.  
  183. /// <summary>
  184. /// 获取2D音频播放节点
  185. /// </summary>
  186. private static AudioPlayer2D GetAudioPlayer2DInstance()
  187. {
  188. if (_streamPlayer2DStack.Count > 0)
  189. {
  190. return _streamPlayer2DStack.Pop();
  191. }
  192.  
  193. var inst = new AudioPlayer2D();
  194. inst.AreaMask = 0;
  195. return inst;
  196. }
  197.  
  198. /// <summary>
  199. /// 获取音频播放节点
  200. /// </summary>
  201. private static AudioPlayer GetAudioPlayerInstance()
  202. {
  203. if (_streamPlayerStack.Count > 0)
  204. {
  205. return _streamPlayerStack.Pop();
  206. }
  207.  
  208. return new AudioPlayer();
  209. }
  210.  
  211. /// <summary>
  212. /// 回收2D音频播放节点
  213. /// </summary>
  214. private static void RecycleAudioPlayer2D(AudioPlayer2D inst)
  215. {
  216. var parent = inst.GetParent();
  217. if (parent != null)
  218. {
  219. parent.RemoveChild(inst);
  220. }
  221.  
  222. inst.Stream = null;
  223. _streamPlayer2DStack.Push(inst);
  224. }
  225.  
  226. /// <summary>
  227. /// 回收音频播放节点
  228. /// </summary>
  229. private static void RecycleAudioPlayer(AudioPlayer inst)
  230. {
  231. _streamPlayerStack.Push(inst);
  232. }
  233. }