Files
2026-07-29 11:05:27 +02:00

69 lines
1.8 KiB
C#

using System.Collections.Generic;
using Godot;
using GodotHostTest.Helpers;
using GodotHostTest.Interfaces;
using OwofGames.AetherBind;
using R3;
namespace GodotHostTest.Game.Target;
public partial class TargetSpawner : Node2D, ITargetCollector, ITargetSpawner
{
private readonly List<ITarget> _availableTargets = [];
private readonly Subject<ITarget> _targetSpawned = new();
[Export] public required Timer Timer;
[Inject] private ILevel _level = null!;
[Inject] private ITargetEventBus _targetEventBus = null!;
/// <inheritdoc />
public void NewTarget(ITarget target)
{
// record the target as available
_availableTargets.Add(target);
// whenever the target gets disabled, mark it as available again
target.Hit.Merge(target.TimedOut)
.Select(_ => target)
.Subscribe(_availableTargets.Add)
.AddTo(this);
}
public Observable<ITarget> TargetSpawned => _targetSpawned.AsObservable();
public override void _Ready()
{
// inform the target event bus that there's a new target spawner
_targetEventBus.NewTargetSpawner(this);
// spawn every total seconds (and immediately spawn something at ready)
Timer.Start(_level.TimeBetweenSpawns.TotalSeconds);
Spawn();
}
private void OnTimer()
{
Spawn();
}
private void Spawn()
{
// pick a random target
var randomIndex = GD.RandRange(0, _availableTargets.Count - 1);
var target = _availableTargets[randomIndex];
_availableTargets.RemoveAt(randomIndex);
// enable it
target.Enable();
// notify that a target has been spawned
_targetSpawned.OnNext(target);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_targetSpawned.Dispose();
}
}