using Godot; using System; using System.Diagnostics; using Cirno.Scripts; public partial class PlayerMovement : CharacterBody2D, IDestructible { [Export] public int Speed { get; set; } = 400; [Export] public float CrosshairDistance { get; set; } = 10f; [Export] public PackedScene BulletScene { get; set; } [Export] public PackedScene SelectorScene { get; set; } [Export] public string GameOverScene { get; set; } private Node2D _selector; private Interactable _lastInteractable; [Export] public Marker2D Muzzle { get; set; } private AnimatedSprite2D _animatedSprite; private Vector2 _movementDirection { get; set; } private Vector2 _facingDirection { get; set; } private Sprite2D _crosshair; private Timer _cooldownTimer; [Export] public float Health = 4f; [DebugGUIPrint] private float _currentHealth = 0f; [Export] public double RateOfFire = 0.4f; [Export] public float BulletSpeed = 300f; private bool _isDestroyed = false; public override void _Ready() { _currentHealth = Health; _animatedSprite = GetNode("./Smoothing2D/AnimatedSprite2D"); _crosshair = GetNode("./Smoothing2D/Crosshair"); _cooldownTimer = GetNode("./ShootTimer"); _movementDirection = Vector2.Zero; _facingDirection = Vector2.Zero; if (SelectorScene != null) { _selector = this.CreateChild(SelectorScene); _selector.Visible = false; } } /*public override _Process(float _delta) { if (Input.IsActionPressed("ui_right")) { _animatedSprite.Play("run"); } else { _animatedSprite.Stop(); } }*/ public override void _Process(double delta) { HandleShoot(); SetAnimation(); FindInteractable(); } private void FindInteractable() { if (Input.IsActionJustPressed("Use") && _lastInteractable != null) { _lastInteractable.Activate(); } //var spaceState = GetWorld2D().DirectSpaceState; //var query = PhysicsRayQueryParameters2D.Create(Vector2.Zero, ) } private void HandleShoot() { if (!Input.IsActionJustPressed("shoot")) return; //Debug.WriteLine("Shoot"); var bullet = BulletScene.Instantiate(); Owner.AddChild(bullet); bullet.Transform = Muzzle.GlobalTransform; bullet.Position = this.Position; bullet.SetDirection(this._facingDirection); } private void SetAnimation() { if (Velocity.X == 0 && Velocity.Y == 0) { _animatedSprite.SpeedScale = 0; } else { _animatedSprite.SpeedScale = 1; } if (Velocity.X > 0) { _animatedSprite.Play("walk_right"); } else if (Velocity.X < 0) { _animatedSprite.Play("walk_left"); } else if (Velocity.Y > 0) { _animatedSprite.Play("walk_down"); } else if (Velocity.Y < 0) { _animatedSprite.Play("walk_up"); } } public Vector2 GetInput() { return Input.GetVector("left", "right", "up", "down"); } private Vector2 CalculateCrosshairPosition() { return _facingDirection * CrosshairDistance;// + this.Position; //var angle = Mathf.Atan2(this.Position.X, this.Position.Y); //var cPos = new Vector2(this.Position.X + CrosshairDistance * Godot.Mathf.Cos(angle), this.Position.Y + CrosshairDistance * Godot.Mathf.Sin(angle)); } public override void _PhysicsProcess(double delta) { _movementDirection = GetInput(); if (_movementDirection != Vector2.Zero) { _facingDirection = _movementDirection; } Velocity = _movementDirection * (float)(Speed * delta); MoveAndSlide(); _crosshair.Position = CalculateCrosshairPosition(); //FindInteractable(); } private void _on_interaction_controller_area_entered(Area2D area) { // Replace with function body. if (area.IsInGroup("Interactable") && area is Interactable interactable) { Debug.WriteLine("Interactable Entered"); if (_selector != null) { _selector.Position = interactable.Position; _selector.Visible = true; _lastInteractable = interactable; } } } private void Explode() { Debug.WriteLine("Ded"); //CreateParticles(); //CreateDebris(); if (GameOverScene != null) { GetTree().ChangeSceneToFile(GameOverScene); } else { QueueFree(); } } public void Hit(float damage) { GD.Print($"Player damaged for {damage}"); if (_isDestroyed) return; _currentHealth -= damage; if (!(_currentHealth <= 0)) return; _isDestroyed = true; Explode(); } public bool IsDestroyed() { return _isDestroyed; } private void _on_damage_hit_box_area_entered(Area2D area) { if (area is Bullet bullet) { GD.Print("Received damage manually"); this.Hit(bullet.Damage); bullet.QueueFree(); } } }