diff --git a/scripts/components/ExplosiveComponent.cs b/scripts/components/ExplosiveComponent.cs new file mode 100644 index 0000000..907788a --- /dev/null +++ b/scripts/components/ExplosiveComponent.cs @@ -0,0 +1,81 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +public partial class ExplosiveComponent : Node2D +{ + [Export] public DamageComponent Damage { get; set; } + [Export] public Area2D Area { get; set; } + [Export] public Area2D ExplodeArea { get; set; } + [Export] public PackedScene ExplosionEffect { get; set; } + [Export] public float TimeToExplode { get; set; } = 9f; + + [Signal] public delegate void OnExplosionEventHandler(Node2D body); + + private Timer _timer; + + public override void _Ready() + { + if (Damage != null) + { + GD.PushError("ExplosiveComponent: DamageComponent is not set."); + return; + } + + if (ExplodeArea != null) + { + GD.PushError("ExplosiveComponent: ExplodeArea is not set."); + return; + } + + Area.BodyEntered += OnAreaBodyEntered; + Area.AreaEntered += OnAreaAreaEntered; + } + + private void OnAreaAreaEntered(Area2D area) + { + Explode(); + } + + private void OnAreaBodyEntered(Node2D body) + { + Explode(); + } + + private void PrepareTimer() + { + _timer = new Timer(); + _timer.SetWaitTime(TimeToExplode); + _timer.OneShot = true; + _timer.Autostart = true; + _timer.Timeout += Explode; + AddChild(_timer); + } + + private void Explode() + { + _timer.Stop(); + + if (ExplosionEffect != null) + { + var explosionInstance = ExplosionEffect.Instantiate(); + if (Owner is Node2D root) explosionInstance.SetGlobalPosition(root.GlobalPosition); + GetTree().CurrentScene.AddChild(explosionInstance); + explosionInstance.SetEmitting(true); + } + + var bodies = ExplodeArea.GetOverlappingBodies(); + foreach (var body in bodies) + { + var health = body.GetNodeOrNull("HealthComponent"); + if (Damage != null && health != null) + { + Damage.DealDamage(health); + } + + EmitSignalOnExplosion(body); + } + + Owner.QueueFree(); + } +} \ No newline at end of file diff --git a/scripts/components/FadeAwayComponent.cs b/scripts/components/FadeAwayComponent.cs new file mode 100644 index 0000000..083d384 --- /dev/null +++ b/scripts/components/FadeAwayComponent.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +public partial class FadeAwayComponent : Node +{ + [Export] public Sprite2D Sprite { get; set; } + [Export] public float FadeDuration { get; set; } = 1f; + [Export] public float Speed { get; set; } = 10f; + [Export] public Vector2 Direction { get; set; } = Vector2.Up; + [Export] public Area2D Area { get; set; } + + public override void _Ready() + { + Area.BodyEntered += OnBodyEntered; + } + + private void OnBodyEntered(Node2D body) + { + _ = FadeAway(); + } + + private async Task FadeAway() + { + var tween = CreateTween().SetParallel(true); + tween.TweenProperty(Sprite, "modulate:a", 0f, FadeDuration); + tween.TweenProperty(Sprite, "position", Sprite.Position + (Direction * Speed), FadeDuration); + await ToSignal(tween, Tween.SignalName.Finished); + Owner.QueueFree(); + } +} \ No newline at end of file diff --git a/scripts/components/FireEffectComponent.cs b/scripts/components/FireEffectComponent.cs new file mode 100644 index 0000000..c89e571 --- /dev/null +++ b/scripts/components/FireEffectComponent.cs @@ -0,0 +1,71 @@ +using Godot; +using Mr.BrickAdventures.scripts.Resources; + +namespace Mr.BrickAdventures.scripts.components; + +public partial class FireEffectComponent : Node +{ + [Export] public HealthComponent Health { get; set; } + [Export] public StatusEffectComponent StatusEffectComponent { get; set; } + [Export] public GpuParticles2D FireFX { get; set; } + + private StatusEffectDataResource _data = null; + private bool _shouldDealDamage = false; + private double _timeElapsed = 0f; + + public override void _Ready() + { + if (Health == null) + { + Health = GetNode("HealthComponent"); + } + if (StatusEffectComponent == null) + { + StatusEffectComponent = GetNode("StatusEffectComponent"); + } + + if (Health == null) + { + GD.PushError("FireEffectComponent: HealthComponent is not set."); + return; + } + if (StatusEffectComponent == null) + { + GD.PushError("FireEffectComponent: StatusEffectComponent is not set."); + return; + } + + StatusEffectComponent.EffectApplied += OnEffectApplied; + StatusEffectComponent.EffectRemoved += OnEffectRemoved; + } + + public override void _Process(double delta) + { + if (!_shouldDealDamage || _data == null || Health == null) return; + + _timeElapsed += delta; + if (_timeElapsed >= 1f) + { + Health.DecreaseHealth(_data.DamagePerSecond); + _timeElapsed = 0f; + } + } + + private void OnEffectApplied(StatusEffect statusEffect) + { + if (statusEffect.EffectData.Type != StatusEffectType.Fire) return; + + _data = statusEffect.EffectData; + _shouldDealDamage = true; + FireFX?.SetEmitting(true); + } + + private void OnEffectRemoved(StatusEffectType type) + { + if (type != StatusEffectType.Fire) return; + + _shouldDealDamage = false; + _data = null; + FireFX?.SetEmitting(false); + } +} \ No newline at end of file diff --git a/scripts/components/FlipComponent.cs b/scripts/components/FlipComponent.cs new file mode 100644 index 0000000..62e263d --- /dev/null +++ b/scripts/components/FlipComponent.cs @@ -0,0 +1,36 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +public partial class FlipComponent : Node2D +{ + [Export] public Sprite2D LeftEye { get; set; } + [Export] public Sprite2D RightEye { get; set; } + [Export] public PlatformMovement PlatformMovement { get; set; } + + public override void _Process(double delta) + { + if (PlatformMovement == null) return; + + var velocity = PlatformMovement.LastDirection; + switch (velocity.X) + { + case < 0f: + LeftEye.Frame = 1; + RightEye.Frame = 1; + LeftEye.FlipH = true; + RightEye.FlipH = true; + break; + case > 0f: + LeftEye.Frame = 1; + RightEye.Frame = 1; + LeftEye.FlipH = false; + RightEye.FlipH = false; + break; + default: + LeftEye.Frame = 0; + RightEye.Frame = 0; + break; + } + } +} \ No newline at end of file diff --git a/scripts/components/GravityMotionComponent.cs b/scripts/components/GravityMotionComponent.cs new file mode 100644 index 0000000..17066e6 --- /dev/null +++ b/scripts/components/GravityMotionComponent.cs @@ -0,0 +1,37 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +public partial class GravityMotionComponent : Node2D +{ + [Export] public CharacterBody2D Body { get; set; } + [Export] public LaunchComponent LaunchComponent { get; set; } + [Export] public Vector2 Gravity { get; set; } = new Vector2(0, 1000f); + [Export] public Vector2 TargetDirection { get; set; } = Vector2.Up; + + private Vector2 _velocity = Vector2.Zero; + + public override void _Ready() + { + if (LaunchComponent == null) return; + + var direction = LaunchComponent.InitialDirection.X > 0f ? TargetDirection : new Vector2(-TargetDirection.X, TargetDirection.Y); + direction = direction.Normalized(); + _velocity = direction * LaunchComponent.Speed; + } + + public override void _PhysicsProcess(double delta) + { + if (Body == null) return; + + _velocity += Gravity * (float)delta; + Body.Velocity = _velocity; + + Body.MoveAndSlide(); + + if (_velocity.LengthSquared() > 0.01f) + { + Body.Rotation = _velocity.Angle(); + } + } +} \ No newline at end of file diff --git a/scripts/components/LaunchComponent.cs b/scripts/components/LaunchComponent.cs new file mode 100644 index 0000000..af9fae4 --- /dev/null +++ b/scripts/components/LaunchComponent.cs @@ -0,0 +1,24 @@ +using Godot; + +namespace Mr.BrickAdventures.scripts.components; + +public partial class LaunchComponent : Node2D +{ + [Export] public Vector2 InitialDirection { get; set; } = Vector2.Right; + [Export] public float Speed { get; set; } = 16f; + [Export] public Vector2 SpawnPosition { get; set; } = Vector2.Zero; + [Export] public float SpawnRotation { get; set; } = 0f; + + public override void _Ready() + { + if (Owner is not Node2D root) return; + + root.GlobalPosition = SpawnPosition; + root.GlobalRotation = SpawnRotation; + } + + public Vector2 GetInitialVelocity() + { + return InitialDirection.Normalized() * Speed; + } +} \ No newline at end of file diff --git a/scripts/components/PlatformMovement.cs b/scripts/components/PlatformMovement.cs index 6775850..6cdd526 100644 --- a/scripts/components/PlatformMovement.cs +++ b/scripts/components/PlatformMovement.cs @@ -39,6 +39,8 @@ public partial class PlatformMovement : Node2D, IMovement private float _jumpGravity; private float _fallGravity; + public Vector2 LastDirection => _lastDirection; + public override void _Ready() { base._Ready();