feat: aetherbind, first source generator

This commit is contained in:
redglow
2026-07-18 17:05:03 +02:00
parent 4ce99d9486
commit aae9c083d9
69 changed files with 210 additions and 156 deletions
+63
View File
@@ -0,0 +1,63 @@
using Godot;
using GodotHostTest.AetherBind;
using GodotHostTest.Interfaces;
using OwofGames.AetherBind;
using R3;
namespace GodotHostTest.Game.Target;
[Injected]
public partial class Target : Node2D, ITarget
{
private readonly Subject<Unit> _hit = new();
private readonly Subject<Unit> _timedOut = new();
[Export] public required Area2D CollisionArea;
[Export] public required Sprite2D Image;
[Export] public double TimeOutDurationInSeconds;
[Export] public required Timer TimeOutTimer;
[Inject] private IValueGetter<ITargetCollector> _targetCollector = null!;
public Observable<Unit> TimedOut => _timedOut.AsObservable();
public Observable<Unit> Hit => _hit.AsObservable();
public void Enable()
{
Image.Visible = true;
CollisionArea.Monitoring = true;
TimeOutTimer.Start(TimeOutDurationInSeconds);
}
public override void _Ready()
{
_targetCollector.Value.NewTarget(this);
}
public override void _ExitTree()
{
_timedOut.Dispose();
_hit.Dispose();
}
// todo: hook to collision
private void OnHit()
{
Disable();
TimeOutTimer.Stop();
_hit.OnNext(Unit.Default);
}
private void Disable()
{
Image.Visible = false;
CollisionArea.Monitoring = false;
}
private void OnTimeout()
{
Disable();
_timedOut.OnNext(Unit.Default);
}
}
+1
View File
@@ -0,0 +1 @@
uid://bv2hat41dyxiv
+61
View File
@@ -0,0 +1,61 @@
using System.Collections.Generic;
using Godot;
using GodotHostTest.Helpers;
using GodotHostTest.Interfaces;
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 double TimeBetweenSpawns;
[Export] public required Timer Timer;
public void NewTarget(ITarget target)
{
_availableTargets.Add(target);
target.Hit.Merge(target.TimedOut).Select(_ => target).Subscribe(MakeTargetAvailable).AddTo(this);
}
public Observable<ITarget> TargetSpawned => _targetSpawned.AsObservable();
public override void _Ready()
{
Spawn();
Timer.Start(TimeBetweenSpawns);
}
private void MakeTargetAvailable(ITarget target)
{
_availableTargets.Add(target);
}
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();
}
}
+1
View File
@@ -0,0 +1 @@
uid://cxfrtglku2gfa