2024-02-26 08:33:37 +01:00
|
|
|
using Godot;
|
|
|
|
|
using System;
|
2024-02-27 17:16:55 +01:00
|
|
|
using System.Diagnostics;
|
2024-06-09 18:19:57 +02:00
|
|
|
using Cirno.Scripts;
|
2024-02-26 08:33:37 +01:00
|
|
|
|
2024-08-18 17:38:32 +02:00
|
|
|
public partial class PlayerMovement : CharacterBody2D, IDestructible
|
2024-02-26 08:33:37 +01:00
|
|
|
{
|
|
|
|
|
[Export]
|
|
|
|
|
public int Speed { get; set; } = 400;
|
2025-01-28 14:05:38 +01:00
|
|
|
|
|
|
|
|
[Export]
|
|
|
|
|
public int StrafeSpeed { get; set; } = 200;
|
|
|
|
|
|
|
|
|
|
public int MovementSpeed => _isStrafing ? StrafeSpeed : Speed;
|
2024-02-26 23:45:20 +01:00
|
|
|
|
2024-05-01 16:39:14 +02:00
|
|
|
[Export]
|
|
|
|
|
public float CrosshairDistance { get; set; } = 10f;
|
|
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
[Export]
|
|
|
|
|
public PackedScene SelectorScene { get; set; }
|
|
|
|
|
|
2024-08-24 15:25:30 +02:00
|
|
|
[Export]
|
2024-08-25 17:06:59 +02:00
|
|
|
public string GameOverScene { get; set; }
|
2024-08-24 15:25:30 +02:00
|
|
|
|
2025-01-30 15:45:29 +01:00
|
|
|
private Selector _selector;
|
2024-06-09 18:19:57 +02:00
|
|
|
|
2025-01-30 15:45:29 +01:00
|
|
|
//private Interactable _lastInteractable;
|
2024-02-27 17:16:55 +01:00
|
|
|
|
|
|
|
|
[Export]
|
2024-05-01 11:48:04 +02:00
|
|
|
public Marker2D Muzzle { get; set; }
|
2024-02-27 17:16:55 +01:00
|
|
|
|
2024-02-26 08:33:37 +01:00
|
|
|
private AnimatedSprite2D _animatedSprite;
|
2024-02-26 23:45:20 +01:00
|
|
|
|
2024-05-01 11:48:04 +02:00
|
|
|
private Vector2 _movementDirection { get; set; }
|
2024-08-24 15:25:30 +02:00
|
|
|
|
2024-05-01 11:48:04 +02:00
|
|
|
private Vector2 _facingDirection { get; set; }
|
2025-01-27 17:30:45 +01:00
|
|
|
|
|
|
|
|
private Vector2 _rightStickInput { get; set; }
|
2024-05-01 11:48:04 +02:00
|
|
|
|
2024-05-01 16:39:14 +02:00
|
|
|
private Sprite2D _crosshair;
|
|
|
|
|
|
2025-01-28 09:17:35 +01:00
|
|
|
[Export] public float MaxHealth = 32f;
|
2024-11-15 16:32:26 +01:00
|
|
|
|
|
|
|
|
[Export] public Weapon EquippedWeapon;
|
2025-01-21 15:17:26 +01:00
|
|
|
|
2024-08-18 17:38:32 +02:00
|
|
|
private float _currentHealth = 0f;
|
2025-01-22 11:35:37 +01:00
|
|
|
|
2024-08-18 17:38:32 +02:00
|
|
|
private bool _isDestroyed = false;
|
|
|
|
|
|
2025-01-24 15:24:37 +01:00
|
|
|
private GameManager _gameManager;
|
|
|
|
|
|
2025-01-28 10:43:35 +01:00
|
|
|
[Export] public Sprite2D HitboxSprite { get; set; }
|
|
|
|
|
|
2025-01-27 17:30:45 +01:00
|
|
|
private bool _isStrafing { get; set; }
|
|
|
|
|
|
2025-02-06 15:57:03 +01:00
|
|
|
private bool _canMove = true;
|
|
|
|
|
|
2025-01-28 09:17:35 +01:00
|
|
|
[Signal]
|
|
|
|
|
public delegate void HealthChangedEventHandler(float newHealth, float MaxHealth);
|
|
|
|
|
|
2025-01-30 08:34:09 +01:00
|
|
|
[Signal]
|
|
|
|
|
public delegate void InteractableAreaEnteredEventHandler(Interactable interactable);
|
|
|
|
|
|
|
|
|
|
[Signal]
|
|
|
|
|
public delegate void InteractableAreaExitedEventHandler(Interactable interactable);
|
|
|
|
|
|
2025-01-28 09:17:35 +01:00
|
|
|
public float CurrentHealth
|
|
|
|
|
{
|
|
|
|
|
get => _currentHealth;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (_currentHealth != value)
|
|
|
|
|
{
|
|
|
|
|
_currentHealth = value;
|
|
|
|
|
EmitSignal(nameof(HealthChanged), _currentHealth, MaxHealth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-20 21:58:59 +01:00
|
|
|
//private InventoryManager _inventoryManager;
|
|
|
|
|
|
2024-02-26 08:33:37 +01:00
|
|
|
public override void _Ready()
|
|
|
|
|
{
|
2025-01-28 09:17:35 +01:00
|
|
|
CurrentHealth = MaxHealth;
|
2024-08-18 17:38:32 +02:00
|
|
|
|
2024-05-01 12:49:46 +02:00
|
|
|
_animatedSprite = GetNode<AnimatedSprite2D>("./Smoothing2D/AnimatedSprite2D");
|
2024-05-02 12:50:08 +02:00
|
|
|
_crosshair = GetNode<Sprite2D>("./Smoothing2D/Crosshair");
|
2025-01-20 21:58:59 +01:00
|
|
|
//_inventoryManager = GetNode<InventoryManager>("/root/GameScene/InventoryManager");
|
2024-05-01 16:39:14 +02:00
|
|
|
|
2024-05-01 11:48:04 +02:00
|
|
|
_movementDirection = Vector2.Zero;
|
|
|
|
|
_facingDirection = Vector2.Zero;
|
2025-01-27 17:30:45 +01:00
|
|
|
_rightStickInput = Vector2.Zero;
|
|
|
|
|
_isStrafing = false;
|
2024-06-09 18:19:57 +02:00
|
|
|
|
2025-02-06 15:57:03 +01:00
|
|
|
_gameManager = this.GetGameManager(); //GetNode<GameManager>("/root/GameScene");
|
|
|
|
|
|
|
|
|
|
_gameManager.GameStateChange += GameManagerOnGameStateChange;
|
|
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
if (SelectorScene != null)
|
|
|
|
|
{
|
2025-01-30 15:45:29 +01:00
|
|
|
_selector = this.CreateSibling<Selector>(SelectorScene, this.GlobalPosition);
|
2025-01-29 14:54:01 +01:00
|
|
|
_selector.Visible = true;
|
2024-06-09 18:19:57 +02:00
|
|
|
}
|
2024-02-26 08:33:37 +01:00
|
|
|
}
|
|
|
|
|
|
2025-02-06 15:57:03 +01:00
|
|
|
private void GameManagerOnGameStateChange(GameState state)
|
|
|
|
|
{
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case GameState.Menu:
|
|
|
|
|
break;
|
|
|
|
|
case GameState.Paused:
|
|
|
|
|
_canMove = false;
|
|
|
|
|
break;
|
|
|
|
|
case GameState.Playing:
|
|
|
|
|
_canMove = true;
|
|
|
|
|
break;
|
|
|
|
|
case GameState.Dialogue:
|
|
|
|
|
_canMove = false;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-26 08:33:37 +01:00
|
|
|
/*public override _Process(float _delta)
|
|
|
|
|
{
|
|
|
|
|
if (Input.IsActionPressed("ui_right"))
|
|
|
|
|
{
|
|
|
|
|
_animatedSprite.Play("run");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_animatedSprite.Stop();
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
2024-02-26 23:45:20 +01:00
|
|
|
public override void _Process(double delta)
|
|
|
|
|
{
|
|
|
|
|
SetAnimation();
|
2025-02-06 15:57:03 +01:00
|
|
|
if (!_canMove) return;
|
|
|
|
|
HandleShoot();
|
2024-06-09 18:19:57 +02:00
|
|
|
FindInteractable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FindInteractable()
|
|
|
|
|
{
|
2025-01-30 17:43:39 +01:00
|
|
|
if (!Input.IsActionJustPressed("Use") || _selector.SelectedInteractable == null) return;
|
|
|
|
|
if (!_selector.SelectedInteractable.CanActivate()) return;
|
|
|
|
|
bool success = _selector.SelectedInteractable.Activate();
|
|
|
|
|
|
|
|
|
|
if (success)
|
2024-06-09 18:19:57 +02:00
|
|
|
{
|
2025-01-30 17:43:39 +01:00
|
|
|
// Deselect and scan for next
|
|
|
|
|
_selector.SelectedInteractable = null;
|
|
|
|
|
_selector.SelectNext();
|
2024-06-09 18:19:57 +02:00
|
|
|
}
|
2024-08-24 15:25:30 +02:00
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
//var spaceState = GetWorld2D().DirectSpaceState;
|
2024-08-24 15:25:30 +02:00
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
//var query = PhysicsRayQueryParameters2D.Create(Vector2.Zero, )
|
2024-02-26 23:45:20 +01:00
|
|
|
}
|
|
|
|
|
|
2024-02-27 17:16:55 +01:00
|
|
|
private void HandleShoot()
|
|
|
|
|
{
|
2024-11-15 16:32:26 +01:00
|
|
|
if (EquippedWeapon == null) return;
|
|
|
|
|
if (!Input.IsActionPressed("shoot")) return;
|
|
|
|
|
|
|
|
|
|
EquippedWeapon.ShootDirection = this._facingDirection;
|
|
|
|
|
EquippedWeapon.Shoot();
|
|
|
|
|
|
|
|
|
|
// //Debug.WriteLine("Shoot");
|
|
|
|
|
// var bullet = BulletScene.Instantiate<Bullet>();
|
|
|
|
|
// Owner.AddChild(bullet);
|
|
|
|
|
// bullet.Transform = Muzzle.GlobalTransform;
|
|
|
|
|
// bullet.Position = this.Position;
|
|
|
|
|
// bullet.SetDirection(this._facingDirection);
|
2024-02-27 17:16:55 +01:00
|
|
|
}
|
|
|
|
|
|
2024-02-26 23:45:20 +01:00
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-26 17:35:40 +01:00
|
|
|
public Vector2 GetInput()
|
2024-02-26 08:33:37 +01:00
|
|
|
{
|
2024-02-26 17:35:40 +01:00
|
|
|
return Input.GetVector("left", "right", "up", "down");
|
2024-02-26 08:33:37 +01:00
|
|
|
}
|
2025-01-27 17:30:45 +01:00
|
|
|
|
|
|
|
|
private Vector2 GetRightStickInput()
|
|
|
|
|
{
|
|
|
|
|
return new Vector2(
|
|
|
|
|
Input.GetAxis("aim_left","aim_right"),
|
|
|
|
|
Input.GetAxis("aim_up", "aim_down")
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-02-26 08:33:37 +01:00
|
|
|
|
2024-05-01 16:39:14 +02:00
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 10:43:35 +01:00
|
|
|
// public override void _Draw()
|
|
|
|
|
// {
|
|
|
|
|
// if (_isStrafing)
|
|
|
|
|
// {
|
|
|
|
|
// HitboxSprite.Visible = true;
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// HitboxSprite.Visible = false;
|
|
|
|
|
// }
|
|
|
|
|
// base._Draw();
|
|
|
|
|
// }
|
|
|
|
|
|
2024-02-26 08:33:37 +01:00
|
|
|
public override void _PhysicsProcess(double delta)
|
2024-08-24 15:25:30 +02:00
|
|
|
{
|
2025-02-06 15:57:03 +01:00
|
|
|
if (!_canMove) return;
|
|
|
|
|
|
2024-05-01 11:48:04 +02:00
|
|
|
_movementDirection = GetInput();
|
2025-01-28 10:43:35 +01:00
|
|
|
|
2025-01-27 17:30:45 +01:00
|
|
|
_isStrafing = Input.IsActionPressed("strafe");
|
2025-01-28 10:43:35 +01:00
|
|
|
// Toggle visibility of the hitbox sprite based on strafing
|
|
|
|
|
if (HitboxSprite != null)
|
|
|
|
|
{
|
|
|
|
|
HitboxSprite.Visible = _isStrafing;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-27 17:30:45 +01:00
|
|
|
_rightStickInput = GetRightStickInput();
|
|
|
|
|
|
|
|
|
|
// Update Facing Direction
|
|
|
|
|
if (!_isStrafing)
|
2024-08-24 15:25:30 +02:00
|
|
|
{
|
2025-01-27 17:30:45 +01:00
|
|
|
if (_rightStickInput.Length() > 0.1f) // If the right stick is moved
|
|
|
|
|
{
|
|
|
|
|
_facingDirection = _rightStickInput.Normalized();
|
|
|
|
|
}
|
|
|
|
|
else if (_movementDirection != Vector2.Zero) // Fall back to movement direction
|
|
|
|
|
{
|
|
|
|
|
_facingDirection = _movementDirection;
|
|
|
|
|
}
|
2024-05-01 11:48:04 +02:00
|
|
|
}
|
2025-01-27 17:30:45 +01:00
|
|
|
|
|
|
|
|
// if (_movementDirection != Vector2.Zero)
|
|
|
|
|
// {
|
|
|
|
|
// _facingDirection = _movementDirection;
|
|
|
|
|
// }
|
2025-01-28 14:05:38 +01:00
|
|
|
Velocity = _movementDirection * (float)( MovementSpeed * delta);
|
2024-02-26 17:35:40 +01:00
|
|
|
|
2024-02-26 08:33:37 +01:00
|
|
|
MoveAndSlide();
|
2024-05-01 16:39:14 +02:00
|
|
|
|
|
|
|
|
_crosshair.Position = CalculateCrosshairPosition();
|
|
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
//FindInteractable();
|
2024-08-24 15:25:30 +02:00
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
}
|
2025-02-06 15:57:03 +01:00
|
|
|
|
2024-06-09 18:19:57 +02:00
|
|
|
private void _on_interaction_controller_area_entered(Area2D area)
|
|
|
|
|
{
|
2025-02-06 15:57:03 +01:00
|
|
|
if (!_canMove) return;
|
2024-06-09 18:19:57 +02:00
|
|
|
// Replace with function body.
|
2025-01-30 17:43:39 +01:00
|
|
|
if (area.IsInGroup("Interactable") && area is Interactable interactable && interactable.CanActivate())
|
2024-06-09 18:19:57 +02:00
|
|
|
{
|
2025-01-29 14:54:01 +01:00
|
|
|
Debug.WriteLine($"Interactable {area.Name} Entered");
|
2024-06-09 18:19:57 +02:00
|
|
|
|
2025-01-30 08:34:09 +01:00
|
|
|
EmitSignal(nameof(InteractableAreaEntered), interactable);
|
|
|
|
|
|
2025-01-30 15:45:29 +01:00
|
|
|
if (_selector == null) return;
|
2025-01-30 15:58:55 +01:00
|
|
|
//_selector.Position = interactable.Position;
|
|
|
|
|
_selector.SelectedInteractable = interactable;
|
|
|
|
|
//_selector.AddInteractable(interactable);
|
2025-01-30 15:45:29 +01:00
|
|
|
//_selector.Visible = true;
|
|
|
|
|
//_lastInteractable = interactable;
|
2024-06-09 18:19:57 +02:00
|
|
|
}
|
2024-02-26 08:33:37 +01:00
|
|
|
}
|
2024-08-18 17:38:32 +02:00
|
|
|
|
2025-01-29 14:54:01 +01:00
|
|
|
private void _on_interaction_controller_area_exited(Area2D area)
|
|
|
|
|
{
|
2025-02-06 15:57:03 +01:00
|
|
|
if (!_canMove) return;
|
2025-01-30 08:34:09 +01:00
|
|
|
if (area.IsInGroup("Interactable") && area is Interactable interactable)
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine($"Interactable {area.Name} Exited");
|
|
|
|
|
|
|
|
|
|
EmitSignal(nameof(InteractableAreaExited), interactable);
|
2025-01-30 15:45:29 +01:00
|
|
|
|
|
|
|
|
if (_selector == null) return;
|
|
|
|
|
_selector.RemoveInteractable(interactable);
|
2025-01-30 08:34:09 +01:00
|
|
|
}
|
2025-01-29 14:54:01 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-18 17:38:32 +02:00
|
|
|
private void Explode()
|
|
|
|
|
{
|
|
|
|
|
Debug.WriteLine("Ded");
|
|
|
|
|
//CreateParticles();
|
|
|
|
|
//CreateDebris();
|
2024-08-24 15:25:30 +02:00
|
|
|
if (GameOverScene != null)
|
|
|
|
|
{
|
2024-08-25 17:06:59 +02:00
|
|
|
GetTree().ChangeSceneToFile(GameOverScene);
|
2024-08-24 15:25:30 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
QueueFree();
|
|
|
|
|
}
|
2024-08-18 17:38:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Hit(float damage)
|
|
|
|
|
{
|
2025-02-06 15:57:03 +01:00
|
|
|
if (!_canMove) return;
|
2024-08-18 17:38:32 +02:00
|
|
|
GD.Print($"Player damaged for {damage}");
|
|
|
|
|
if (_isDestroyed) return;
|
2024-08-24 15:25:30 +02:00
|
|
|
|
2025-01-28 09:17:35 +01:00
|
|
|
CurrentHealth -= damage;
|
|
|
|
|
if (!(CurrentHealth <= 0)) return;
|
2024-08-18 17:38:32 +02:00
|
|
|
_isDestroyed = true;
|
|
|
|
|
Explode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsDestroyed()
|
|
|
|
|
{
|
|
|
|
|
return _isDestroyed;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-24 15:25:30 +02:00
|
|
|
private void _on_damage_hit_box_area_entered(Area2D area)
|
|
|
|
|
{
|
2025-02-06 15:57:03 +01:00
|
|
|
if (!_canMove) return;
|
2024-08-24 15:25:30 +02:00
|
|
|
if (area is Bullet bullet)
|
|
|
|
|
{
|
2024-08-18 17:38:32 +02:00
|
|
|
GD.Print("Received damage manually");
|
|
|
|
|
this.Hit(bullet.Damage);
|
|
|
|
|
bullet.QueueFree();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-26 08:33:37 +01:00
|
|
|
}
|