130 lines
3.9 KiB
C#
130 lines
3.9 KiB
C#
using AceFieldNewHorizon.Scripts.Entities;
|
|
using Godot;
|
|
|
|
namespace AceFieldNewHorizon.Scripts.Tiles;
|
|
|
|
public partial class EnemyPortalTile : BaseTile
|
|
{
|
|
[Export] public PackedScene EnemyScene;
|
|
[Export] public int MaxEnemies = 5;
|
|
[Export] public float SpawnDelay = 5.0f; // Time between spawn attempts
|
|
[Export] public float SpawnRadius = 50.0f; // Radius around the nest where enemies can spawn
|
|
[Export] public bool Active = true;
|
|
|
|
private Timer _spawnTimer;
|
|
private int _currentEnemyCount = 0;
|
|
|
|
public override void _Ready()
|
|
{
|
|
base._Ready();
|
|
|
|
// Add to Hostile group to prevent enemies from attacking their own nest
|
|
AddToGroup("Hostile");
|
|
|
|
// Create and configure the timer
|
|
_spawnTimer = new Timer
|
|
{
|
|
Autostart = true,
|
|
WaitTime = SpawnDelay
|
|
};
|
|
AddChild(_spawnTimer);
|
|
_spawnTimer.Timeout += OnSpawnTimerTimeout;
|
|
|
|
var sprite = GetNode<Sprite2D>("Sprite2D");
|
|
|
|
// Create and configure the shadow sprite
|
|
var shadow = new Sprite2D
|
|
{
|
|
Texture = sprite.Texture,
|
|
Scale = sprite.Scale * 1.05f, // Slightly larger than the original
|
|
Modulate = new Color(0, 0, 0, 0.5f), // Slightly more transparent
|
|
Position = new Vector2(0, 12), // Closer to the sprite (reduced from 30)
|
|
ZIndex = -1
|
|
};
|
|
AddChild(shadow);
|
|
|
|
// Create floating animation
|
|
const float floatOffset = 5.0f;
|
|
const float floatDuration = 2.0f;
|
|
|
|
var tween = CreateTween().SetLoops();
|
|
tween.TweenProperty(sprite, "position:y", -floatOffset, floatDuration)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine);
|
|
tween.TweenProperty(sprite, "position:y", floatOffset, floatDuration * 2)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine);
|
|
tween.TweenProperty(sprite, "position:y", 0, floatDuration)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine);
|
|
|
|
// Animate shadow
|
|
tween.Parallel().TweenProperty(shadow, "position:y", 12 - (floatOffset * 0.3f), floatDuration)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine);
|
|
tween.Parallel().TweenProperty(shadow, "scale", sprite.Scale * 1.02f, floatDuration)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine);
|
|
tween.Parallel().TweenProperty(shadow, "modulate:a", 0.6f, floatDuration)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine);
|
|
|
|
tween.Parallel().TweenProperty(shadow, "position:y", 12 + (floatOffset * 0.4f), floatDuration * 2)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine)
|
|
.SetDelay(floatDuration);
|
|
tween.Parallel().TweenProperty(shadow, "scale", sprite.Scale * 1.08f, floatDuration * 2)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine)
|
|
.SetDelay(floatDuration);
|
|
tween.Parallel().TweenProperty(shadow, "modulate:a", 0.4f, floatDuration * 2)
|
|
.SetEase(Tween.EaseType.InOut)
|
|
.SetTrans(Tween.TransitionType.Sine)
|
|
.SetDelay(floatDuration);
|
|
}
|
|
|
|
private void OnSpawnTimerTimeout()
|
|
{
|
|
if (!Active || EnemyScene == null || _currentEnemyCount >= MaxEnemies)
|
|
return;
|
|
|
|
// Check if we can spawn more enemies
|
|
var enemies = GetTree().GetNodesInGroup("Enemy");
|
|
_currentEnemyCount = enemies.Count;
|
|
|
|
if (_currentEnemyCount >= MaxEnemies)
|
|
return;
|
|
|
|
// Spawn a new enemy
|
|
var enemy = EnemyScene.Instantiate<Enemy>();
|
|
if (enemy != null)
|
|
{
|
|
GetParent().AddChild(enemy);
|
|
|
|
// Calculate a random position within the spawn radius
|
|
var randomAngle = GD.Randf() * Mathf.Pi * 2;
|
|
var randomOffset = new Vector2(
|
|
Mathf.Cos(randomAngle) * SpawnRadius,
|
|
Mathf.Sin(randomAngle) * SpawnRadius
|
|
);
|
|
|
|
enemy.GlobalPosition = GlobalPosition + randomOffset;
|
|
_currentEnemyCount++;
|
|
|
|
// Connect to the enemy's death signal if available
|
|
enemy.TreeExiting += () => OnEnemyDied();
|
|
}
|
|
}
|
|
|
|
private void OnEnemyDied()
|
|
{
|
|
_currentEnemyCount = Mathf.Max(0, _currentEnemyCount - 1);
|
|
}
|
|
|
|
public void SetActive(bool active)
|
|
{
|
|
Active = active;
|
|
_spawnTimer.Paused = !active;
|
|
}
|
|
}
|