using Godot; using System; using System.Diagnostics; using Cirno.Scripts.Components; using Cirno.Scripts.Resources; public partial class Bullet : Area2D { [Export] public float Speed = 1900f; [Export] public float Damage = 1f; [Export] public BulletOwner Owner = BulletOwner.None; private Vector2 _direction = Vector2.Right; private double _elapsedTime = 0f; private BulletInfo _bulletInfo; public void Initialize(BulletInfo bulletInfo) { _bulletInfo = bulletInfo; Position = bulletInfo.Position; Owner = bulletInfo.Owner; } private void ApplyTimeModifiers() { foreach (var modifier in _bulletInfo.TimeModifiers) { if (modifier.Applied) { continue; } if (_elapsedTime >= modifier.TimeInSeconds) { switch (modifier.ModifierType) { case TimeModifierType.SpeedChange: //_bulletInfo.Speed += modifier.Value; Speed = modifier.Value; break; case TimeModifierType.RotationChange: RotateBullet(modifier.Value); //Rotation += Mathf.DegToRad(modifier.Value); break; case TimeModifierType.FacePlayer: FacePlayer(); break; } modifier.Applied = true; } } } private void RotateBullet(float degrees) { float radians = Mathf.DegToRad(degrees); _direction = _direction.Rotated(radians).Normalized(); // Rotate direction } private void FacePlayer() { // TODO: cache player var player = GetTree().GetFirstNodeInGroup("Player") as Node2D; if (player != null) { _direction = (player.GlobalPosition - this.GlobalPosition).Normalized(); //LookAt(player.GlobalPosition); } } //private void OnBodyEntered(Node body) //{ // When a body is entered, invoke the event and pass the collided body // BulletHit?.Invoke(body); // Then remove the bullet // QueueFree(); //} public void SetDirection(Vector2 direction) { var normalized = direction.Normalized(); _direction = normalized; //Debug.WriteLine($"Bullet Shot at direction {direction.X} {direction.Y}"); } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { _elapsedTime += delta; if (_bulletInfo != null) { ApplyTimeModifiers(); } this.Position += ((float)(Speed * delta) * _direction); } private void _on_visible_on_screen_notifier_2d_screen_exited() { //Debug.WriteLine("Destroy bullet out of screen"); QueueFree(); } private void _on_body_entered(Node2D body) { if (body.IsInGroup("Solid")) { //Debug.WriteLine("Collision"); QueueFree(); } //// Do not Collide with body for purpose of destroying bullets // else if (body.IsInGroup("Destroyable")) // { // Debug.WriteLine("Collision with destroyable object body"); // QueueFree(); // } } private void _on_area_entered(Area2D area) { if (area.IsInGroup("Solid")) { QueueFree(); return; } if (area.IsInGroup("Destroyable") && area is IDestructible destructible) { //Debug.WriteLine("Collision with destroyable object area"); destructible.Hit(Damage); QueueFree(); } } } public enum BulletOwner { None, Player, Enemy }