69 lines
1.8 KiB
C#
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();
|
|
}
|
|
} |