Concurrent audio limit and volume limiter

This commit is contained in:
MaddoScientisto 2025-04-05 18:46:20 +02:00
commit a533f93361
11 changed files with 162 additions and 6 deletions

View file

@ -19,6 +19,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003Ff1d69ec2da76ccf9bc8a75c8e0fdca9a7ba1adf8c8c9d5047e2fa5991c02eca_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APlayerMovement_005FScriptMethods_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003F4af4702ac4bbb9ab7299554c41beea2bf703b4a_003FPlayerMovement_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AScriptManagerBridge_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FDecompilerCache_003Fdecompiler_003F4fd22cd129a84c16b5d8004b467c426f518800_003F3a_003Fc456f450_003FScriptManagerBridge_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStringName_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb9315b94b9124600ad99083b1bc65e44584a00_003Faa_003Fd6996970_003FStringName_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelpers_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FSourcesCache_003Fbb2a94dce7ca55a596694df58d3ca91c6d9c9c9c9813775e4d1abd0f91dc59_003FThrowHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVariantUtils_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FDecompilerCache_003Fdecompiler_003F4fd22cd129a84c16b5d8004b467c426f518800_003F38_003Fb04c4423_003FVariantUtils_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector2_002Ecs_002Fl_003AC_0021_003FUsers_003FMaddo_003FAppData_003FLocal_003FJetBrains_003FShared_003FvAny_003FDecompilerCache_003Fdecompiler_003F08f0ea1144634eedbe3a87b9762ef1dd4bd200_003F85_003F367e08bf_003FVector2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View file

@ -9,8 +9,11 @@ BulletScene = ExtResource("1_bca33")
BulletSpeed = 0.0
Direction = Vector2(1, 0)
BulletDamage = 8.0
LifeTime = 1.0
LifeTime = 0.4
DestroyOnCollision = false
Owner = 0
DamageType = 4
Controllable = false
Grazeable = false
GrazeValue = 1.0
TimeModifiers = null

View file

@ -1,7 +1,8 @@
[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://clblu7fse2pjy"]
[sub_resource type="AudioEffectLimiter" id="AudioEffectLimiter_0f13h"]
resource_name = "Limiter"
[sub_resource type="AudioEffectHardLimiter" id="AudioEffectHardLimiter_0f13h"]
resource_name = "HardLimiter"
ceiling_db = -10.0
[resource]
bus/1/name = &"Music"
@ -16,7 +17,7 @@ bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = 0.0
bus/2/send = &"Master"
bus/2/effect/0/effect = SubResource("AudioEffectLimiter_0f13h")
bus/2/effect/0/effect = SubResource("AudioEffectHardLimiter_0f13h")
bus/2/effect/0/enabled = true
bus/3/name = &"Voice"
bus/3/solo = false

View file

@ -6,6 +6,7 @@
[node name="AutoclearingExplosionBullet" type="Node2D"]
script = ExtResource("1_5c773")
Timeout = 0.4
BulletResource = ExtResource("2_d2d24")
EmitOnStart = true
EmitCoolDown = 10.0

View file

@ -1,8 +1,9 @@
[gd_scene load_steps=5 format=3 uid="uid://h11o0et1y54v"]
[gd_scene load_steps=6 format=3 uid="uid://h11o0et1y54v"]
[ext_resource type="Script" uid="uid://dsa4b75hdig8p" path="res://Scripts/Bullet.cs" id="1_f0epf"]
[ext_resource type="SpriteFrames" uid="uid://lh1q76788ixw" path="res://Resources/Sprites/explosion_proc_1.tres" id="2_wng0j"]
[ext_resource type="AudioStream" uid="uid://ds84e0m5l4i5d" path="res://SFX/404752__owlstorm__retro-video-game-sfx-explode-3.wav" id="3_wng0j"]
[ext_resource type="Script" uid="uid://dwnqgkuj6bgay" path="res://Scripts/Misc/LimitedAudioPlayer.cs" id="4_0imfi"]
[sub_resource type="CircleShape2D" id="CircleShape2D_jxptd"]
radius = 28.0179
@ -35,6 +36,10 @@ autoplay = true
max_distance = 300.0
bus = &"Effects"
area_mask = 8
script = ExtResource("4_0imfi")
AudioName = &"EXPLOSION"
ReparentOnCreation = true
Duration = 0.55
[connection signal="area_entered" from="." to="." method="_on_area_entered"]
[connection signal="body_entered" from="." to="." method="_on_body_entered"]

View file

@ -1,8 +1,9 @@
[gd_scene load_steps=5 format=3 uid="uid://b1qnfiuokpvsr"]
[gd_scene load_steps=6 format=3 uid="uid://b1qnfiuokpvsr"]
[ext_resource type="Texture2D" uid="uid://cybpmpb0d8yva" path="res://Sprites/Projectile.png" id="1_2eu87"]
[ext_resource type="Script" uid="uid://dsa4b75hdig8p" path="res://Scripts/Bullet.cs" id="1_jvxw3"]
[ext_resource type="AudioStream" uid="uid://cjg8r7bthkfsy" path="res://SFX/Laser_shoot 11.wav" id="3_8bitv"]
[ext_resource type="Script" uid="uid://dwnqgkuj6bgay" path="res://Scripts/Misc/LimitedAudioPlayer.cs" id="4_jxgah"]
[sub_resource type="CircleShape2D" id="CircleShape2D_jxptd"]
radius = 2.23607
@ -30,6 +31,8 @@ stream = ExtResource("3_8bitv")
autoplay = true
bus = &"Effects"
area_mask = 8
script = ExtResource("4_jxgah")
AudioName = &"ICE_BULLET"
[connection signal="area_entered" from="." to="." method="_on_area_entered"]
[connection signal="body_entered" from="." to="." method="_on_body_entered"]

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using Cirno.Scripts;
using Cirno.Scripts.Components.FSM;
using Cirno.Scripts.Misc;
using Cirno.Scripts.Resources;
using Godot.Collections;
using Cirno.Scripts.Utils;
@ -60,6 +61,8 @@ public partial class GameManager : Node2D
public delegate void PlayerRespawnedEventHandler();
public Vector2 LastCheckpointPosition { get; set; }
private AudioManager _audioManager;
[Export]
public Node2D PlayerParentNode { get; set; }
@ -76,6 +79,9 @@ public partial class GameManager : Node2D
GlobalState.Instance.SaveGame();
}
_audioManager = new AudioManager();
this.AddChild(_audioManager);
_hud = GetNodeOrNull<Hud>("HUD");
if (_hud == null) GD.Print("No HUD in scene.");

View file

@ -0,0 +1,52 @@
using System.Collections.Generic;
using Godot;
namespace Cirno.Scripts.Misc;
public partial class AudioManager : Node2D
{
public static AudioManager Instance { get; private set; }
[Export]
public int ConcurrentSounds { get; set; } = 3;
private Dictionary<string, int> _audioDict = new Dictionary<string, int>();
public override void _Ready()
{
Instance = this;
}
public bool CanPlay(string audioName)
{
var item = _audioDict.TryGetValue(audioName, out int amount);
if (item) return amount < ConcurrentSounds;
_audioDict.Add(audioName, 0);
return true;
}
public bool Play(string audioName)
{
if (!CanPlay(audioName)) return false;
if (!_audioDict.ContainsKey(audioName))
{
_audioDict.Add(audioName, 0);
}
_audioDict[audioName] += 1;
return true;
}
public void Stop(string audioName)
{
if (_audioDict.ContainsKey(audioName))
{
_audioDict[audioName] -= 1;
if (_audioDict[audioName] < 0)
{
_audioDict[audioName] = 0;
}
}
}
}

View file

@ -0,0 +1 @@
uid://ci2px8dicc0xx

View file

@ -0,0 +1,82 @@
using Godot;
namespace Cirno.Scripts.Misc;
public partial class LimitedAudioPlayer : AudioStreamPlayer2D
{
[Export] public StringName AudioName { get; private set; }
[Export] public bool ReparentOnCreation { get; private set; } = false;
[Export] public float Duration { get; private set; } = -1;
private bool _finished = false;
private double _timer = 0;
public override void _Ready()
{
if (ReparentOnCreation)
{
CallDeferred(MethodName.ReparentDeferred);
}
if (Duration >= 0)
{
}
// Check if it can play
if (IsAutoplayEnabled())
{
TryPlay();
}
this.Finished += OnFinished;
}
public override void _Process(double delta)
{
if (Duration >= 0 && IsPlaying())
{
_timer += delta;
if (_timer >= Duration)
{
this.Stop();
}
}
}
private void ReparentDeferred()
{
this.Reparent(GameManager.Instance.BulletsContainer);
}
public override void _ExitTree()
{
this.Finished -= OnFinished;
if (!_finished)
{
AudioManager.Instance.Stop(AudioName);
}
}
public void TryPlay()
{
if (!AudioManager.Instance.Play(AudioName))
{
this.SetVolumeDb(-100);
return;
}
else
{
this.SetVolumeDb(0);
}
}
private void OnFinished()
{
AudioManager.Instance.Stop(AudioName);
_finished = true;
}
}

View file

@ -0,0 +1 @@
uid://dwnqgkuj6bgay