summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authoralex <[email protected]>2026-09-21 12:19:15 +0200
committeralex <[email protected]>2026-09-21 12:19:15 +0200
commitf0c870bb9dcffd79d0ad4e361d9f9f2a2ff807f8 (patch)
tree02a46e0ed70171a679dbd69f435a2a8e1a3a0959 /scripts
parent0c5df1e068ff8865545b7e1b3629377089c8b965 (diff)
downloadgodot-testing-f0c870bb9dcffd79d0ad4e361d9f9f2a2ff807f8.tar.xz
godot-testing-f0c870bb9dcffd79d0ad4e361d9f9f2a2ff807f8.zip
vela veciHEADmain
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Enemy.cs158
1 files changed, 151 insertions, 7 deletions
diff --git a/scripts/Enemy.cs b/scripts/Enemy.cs
index cdbcd38..d2f6477 100644
--- a/scripts/Enemy.cs
+++ b/scripts/Enemy.cs
@@ -5,27 +5,171 @@ public partial class Enemy : CharacterBody2D, IDamageable
{
[Export] public float MoveSpeed { get; set; } = 150.0f;
[Export] public float MaxHealth { get; set; } = 30.0f;
+ [Export] public float Damage { get; set; } = 50.0f;
+ [Export] public float AttackRange = 40.0f; // Distance to trigger swing
+ [Export] public float AttackCooldown = 1.2f;
+ [Export] public float SteeringAcceleration { get; set; } = 12.0f; // Higher = tighter turns, lower = smoother turns
+ [Export] public float SwingAngle = 150.0f; // The parent node holding the weapon
- private Node2D _player;
+ private NavigationAgent2D _nav;
+
+ [Export] public Node2D WeaponPivot; // The parent node holding the weapon
+ [Export] public Area2D WeaponHitbox;
+ private bool _isAttacking = false;
+ private bool _canAttack = true;
+ private Node2D _player;
+ private Vector2 _lastPlayerPos;
+
public override void _Ready()
{
- // Find the player automatically using the group we just set up
- _player = GetTree().GetFirstNodeInGroup("player") as Node2D;
+ _nav = GetNode<NavigationAgent2D>("NavigationAgent2D");
+ _player = GetTree().GetFirstNodeInGroup("player") as CharacterBody2D;
+ _lastPlayerPos = _player.GlobalPosition;
+ Callable.From(ActorSetup).CallDeferred();
+
+ _nav.AvoidanceEnabled = true;
+
+ // Connect the VelocityComputed signal to receive safe avoidance vectors
+ _nav.VelocityComputed += OnVelocityComputed;
+
+ if (WeaponHitbox != null)
+ {
+ // Keep hitbox turned off when not swinging
+ WeaponHitbox.Monitoring = false;
+ WeaponHitbox.BodyEntered += OnWeaponHitboxBodyEntered;
+ }
+
+ }
+
+ private async void ActorSetup()
+ {
+ await ToSignal(GetTree(), SceneTree.SignalName.PhysicsFrame);
+ SetMovementTarget(_player.Position);
+ }
+
+ public void SetMovementTarget(Vector2 movementTarget)
+ {
+ _nav.TargetPosition = movementTarget;
}
public override void _PhysicsProcess(double delta)
{
- if (_player == null) return;
+ if (!GodotObject.IsInstanceValid(_player) || _isAttacking) return;
// Calculate direction vector pointing from the enemy to the player
- Vector2 direction = GlobalPosition.DirectionTo(_player.GlobalPosition);
+ // if (GlobalPosition.DistanceSquaredTo(_lastPlayerPos) > 256.0f)
+ // {
+ // _lastPlayerPos = _player.GlobalPosition;
+ // _nav.TargetPosition = _lastPlayerPos;
+ // }
+ _nav.TargetPosition = _player.GlobalPosition;
+ float distanceToPlayer = GlobalPosition.DistanceTo(_player.GlobalPosition);
+ if (distanceToPlayer <= AttackRange)
+ {
+ if (_canAttack)
+ {
+ PerformSwingAttack();
+ return;
+ }
+ }
- // Move towards the player
- Velocity = direction * MoveSpeed;
+
+ if (_nav.IsNavigationFinished())
+ {
+ _nav.Velocity = Vector2.Zero;
+ Velocity = Velocity.MoveToward(Vector2.Zero, (float)delta * MoveSpeed * SteeringAcceleration);
+ MoveAndSlide();
+ return;
+ }
+
+ Vector2 nextPathPosition = _nav.GetNextPathPosition();
+ Vector2 desiredDirection = GlobalPosition.DirectionTo(nextPathPosition);
+ Vector2 targetVelocity = desiredDirection * MoveSpeed;
+
+ WeaponPivot.Rotation = desiredDirection.Angle();
+
+ // 5. Pass target velocity to the NavigationAgent for processing
+ if (_nav.AvoidanceEnabled)
+ {
+ // Triggers OnVelocityComputed signal on the next frame calculation
+ _nav.Velocity = targetVelocity;
+ }
+ else
+ {
+ // Fallback smooth steering without avoidance
+ ApplySmoothSteering(targetVelocity, (float)delta);
+ }
+ }
+ private async void PerformSwingAttack(){
+ _isAttacking = true;
+ _canAttack = false;
+ Velocity = Vector2.Zero; // Stop moving while swinging
+
+ // 1. Calculate the angle pointing toward the player
+ float aimAngle = (_player.GlobalPosition - GlobalPosition).Angle();
+
+ // Define swing arc (-60 degrees back to +60 degrees forward)
+ float startAngle = aimAngle - Mathf.DegToRad(SwingAngle/2);
+ float endAngle = aimAngle + Mathf.DegToRad(SwingAngle/2);
+
+ // 2. Set starting position for the swing
+
+
+ Tween prepTween = CreateTween();
+ // 3. Create a Tween to animate the rotation
+ prepTween.TweenProperty(WeaponPivot, "rotation", startAngle, 0.25f)
+ .SetTrans(Tween.TransitionType.Quad)
+ .SetEase(Tween.EaseType.Out);
+ await ToSignal(prepTween, Tween.SignalName.Finished);
+ WeaponPivot.Rotation = startAngle;
+ WeaponHitbox.Monitoring = true; // Turn on collision check
+
+ Tween swingTween = CreateTween();
+
+ // Rotate from startAngle to endAngle over 0.25 seconds with a smooth curve
+ swingTween.TweenProperty(WeaponPivot, "rotation", endAngle, 0.25f)
+ .SetTrans(Tween.TransitionType.Quad)
+ .SetEase(Tween.EaseType.Out);
+
+ // Wait for the swing movement to complete
+ await ToSignal(swingTween, Tween.SignalName.Finished);
+
+ // 4. Disable hitbox as soon as swing finishes
+ WeaponHitbox.Monitoring = false;
+
+ // 5. Retract weapon back to neutral position smoothly
+ Tween resetTween = CreateTween();
+ resetTween.TweenProperty(WeaponPivot, "rotation", aimAngle, 0.15f);
+ await ToSignal(resetTween, Tween.SignalName.Finished);
+
+ _isAttacking = false;
+
+ // Cooldown timer before the enemy can swing again
+ await ToSignal(GetTree().CreateTimer(AttackCooldown), SceneTreeTimer.SignalName.Timeout);
+ _canAttack = true;
+ }
+
+ private void OnWeaponHitboxBodyEntered(Node2D body)
+ {
+ // Deal damage when the weapon hits a damageable target
+ if (body is IDamageable target)
+ {
+ target.TakeDamage(Damage);
+ }
+ }
+ private void OnVelocityComputed(Vector2 safeVelocity)
+ {
+ Velocity = safeVelocity;
+ MoveAndSlide();
+ }
+ private void ApplySmoothSteering(Vector2 targetVelocity, float delta)
+ {
+ Velocity = Velocity.Lerp(targetVelocity, delta * SteeringAcceleration);
MoveAndSlide();
}
+
public void TakeDamage(float amount)
{
MaxHealth -= amount;