Death and Rebirth

This commit is contained in:
Marco 2025-02-20 16:12:53 +01:00
commit be52d0e081
11 changed files with 309 additions and 83 deletions

View file

@ -7,9 +7,20 @@ public partial class AutodeleteParticle : GpuParticles2D
[Export]
public double LifeTime { get; private set; }
[Export]
public bool AutoStart { get; private set; }
private double _timer = 0;
public override void _Ready()
{
if (AutoStart)
{
Init();
}
}
public void Init()
{
this.Emitting = true;

View file

@ -106,6 +106,12 @@ public partial class GameManager : Node2D
_player.ShieldChanged += (newShield, maxShield) => _hud.UpdateShield(newShield, maxShield);
_player.InteractableAreaEntered += (interactable) => _hud.UpdateInteractable(interactable);
_player.Death += () =>
{
// Show Game Over
_hud.ShowGameOver();
};
}
else
{

View file

@ -28,6 +28,8 @@ public partial class Hud : CanvasLayer
[Export] private Container _itemsContainer;
[Export] private LabelSettings _labelSettings;
[Export] private Container _gameOverPanel;
[ExportGroup("Pause Menu")] [Export]
public Control PauseMenuContainer;
@ -45,11 +47,14 @@ public partial class Hud : CanvasLayer
private Dictionary<string, HudItem> _items = new();
private PauseMenu _pauseMenu;
private bool _playerDead = false;
public override void _Ready()
{
// Assuming the HUD has a Label node named "HealthLabel"
//_healthLabel = GetNode<Label>("HealthLabel");
_gameOverPanel.Hide();
}
public void ShowMessage(string text)
@ -61,23 +66,33 @@ public partial class Hud : CanvasLayer
GetNode<Timer>("MessageTimer").Start();
}
async public void ShowGameOver()
public void ShowGameOver()
{
ShowMessage("Game Over");
var messageTimer = GetNode<Timer>("MessageTimer");
await ToSignal(messageTimer, Timer.SignalName.Timeout);
var message = GetNode<Label>("Message");
message.Text = "Dodge the Creeps!";
message.Show();
await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
GetNode<Button>("StartButton").Show();
_gameOverPanel.Show();
_playerDead = true;
// ShowMessage("Game Over");
//
// var messageTimer = GetNode<Timer>("MessageTimer");
// await ToSignal(messageTimer, Timer.SignalName.Timeout);
//
// var message = GetNode<Label>("Message");
// message.Text = "Dodge the Creeps!";
// message.Show();
//
// await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
// GetNode<Button>("StartButton").Show();
}
public void UpdateHealth(float newHealth, float maxHealth)
{
// Hide game over if player is no longer dead
if (_playerDead && newHealth > 0)
{
_playerDead = false;
_gameOverPanel.Hide();
}
_healthLabel.Text = $"{newHealth}/{maxHealth}";
if (_healthBar != null)
{

View file

@ -3,6 +3,8 @@ using System;
using System.Diagnostics;
using System.Linq;
using Cirno.Scripts;
using Cirno.Scripts.Components;
using Cirno.Scripts.Components.Actors;
using Cirno.Scripts.Resources;
using Godot.Collections;
@ -46,6 +48,17 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
[Export] public float MaxHealth = 32f;
[Export] public float MaxShield = 32f;
[ExportGroup("Action Names")]
[Export] private string _shootActionName = "shoot";
[ExportGroup("Action Names")]
[Export] private string _useActionName = "Use";
[ExportGroup("Action Names")]
[Export] private string _strafeActionName = "strafe";
[ExportGroup("Action Names")]
[Export] private string _nextWeaponActionName = "next_weapon";
[ExportGroup("Action Names")]
[Export] private string _previousWeaponActionName = "previous_weapon";
public Weapon EquippedWeapon { get; set; }
@ -53,17 +66,22 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
public int CurrentWeaponIndex { get; set; } = 0;
private float _currentHealth = 0f;
private float _currentShield = 0f;
//private float _currentHealth = 0f;
//private float _currentShield = 0f;
private bool _isDestroyed = false;
private GameManager _gameManager;
private InventoryManager _inventoryManager;
private ActorResourceProvider _healthProvider;
private ActorResourceProvider _shieldProvider;
[Export] public Sprite2D HitboxSprite { get; set; }
[Export] public BulletOwner BulletGroup { get; set; } = BulletOwner.Player;
[Export] private PackedScene _deathParticles;
private bool _isStrafing { get; set; }
private bool _canMove = true;
@ -79,53 +97,71 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
[Signal]
public delegate void InteractableAreaExitedEventHandler(Interactable interactable);
[Signal]
public delegate void DeathEventHandler();
// public float CurrentHealth
// {
// get => _currentHealth;
// set
// {
// if (_currentHealth != value)
// {
// _currentHealth = value;
//
// if (_currentHealth > MaxHealth) {
// _currentHealth = MaxHealth;
// }
//
// EmitSignal(nameof(HealthChanged), _currentHealth, MaxHealth);
// }
// }
// }
public float CurrentHealth
{
get => _currentHealth;
set
{
if (_currentHealth != value)
{
_currentHealth = value;
if (_currentHealth > MaxHealth) {
_currentHealth = MaxHealth;
}
EmitSignal(nameof(HealthChanged), _currentHealth, MaxHealth);
}
}
get => _healthProvider.CurrentResource;
set => _healthProvider.CurrentResource = value;
}
public float CurrentShield
{
get => _currentShield;
set
{
if (_currentShield != value)
{
_currentShield = value;
if (_currentShield > MaxShield)
{
_currentShield = MaxShield;
}
EmitSignal(nameof(ShieldChanged), _currentShield, MaxShield);
}
}
get => _shieldProvider.CurrentResource;
set => _shieldProvider.CurrentResource = value;
}
//private InventoryManager _inventoryManager;
private Vector2 _lastCheckPointPosition;
public Vector2 LastCheckPointPosition
{
get => _lastCheckPointPosition;
set => _lastCheckPointPosition = value;
}
public override void _Ready()
{
CurrentHealth = MaxHealth;
CurrentShield = MaxShield;
// CurrentHealth = MaxHealth;
// CurrentShield = MaxShield;
_animatedSprite = GetNode<AnimatedSprite2D>("./Smoothing2D/AnimatedSprite2D");
_crosshair = GetNode<Sprite2D>("./Smoothing2D/Crosshair");
_healthProvider = GetNode<ActorResourceProvider>("HealthProvider");
_shieldProvider = GetNode<ActorResourceProvider>("ShieldProvider");
_healthProvider.MaxResource = MaxHealth;
_shieldProvider.MaxResource = MaxShield;
_healthProvider.ResourceChanged += (value, maxValue) =>
{
EmitSignal(nameof(HealthChanged), value, maxValue);
};
_shieldProvider.ResourceChanged += (value, maxValue) =>
{
EmitSignal(nameof(ShieldChanged), value, maxValue);
};
_healthProvider.FillResource();
_shieldProvider.FillResource();
_movementDirection = Vector2.Zero;
_facingDirection = Vector2.Zero;
@ -142,6 +178,8 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
_selector = this.CreateSibling<Selector>(SelectorScene, this.GlobalPosition);
_selector.Visible = false;
}
_lastCheckPointPosition = GlobalPosition;
}
private void GameManagerOnGameStateChange(GameState state)
@ -215,7 +253,7 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
private void FindInteractable()
{
var selected = _selector.SelectedInteractable;
if (!Input.IsActionJustPressed("Use") || selected == null) return;
if (!Input.IsActionJustPressed(_useActionName) || selected == null) return;
if (!selected.CanActivate()) return;
bool success = selected.Activate();
@ -235,7 +273,7 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
private void HandleShoot()
{
if (EquippedWeapon == null) return;
if (!Input.IsActionPressed("shoot")) return;
if (!Input.IsActionPressed(_shootActionName)) return;
EquippedWeapon.ShootDirection = this._facingDirection;
EquippedWeapon.Shoot();
@ -295,18 +333,23 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
//var cPos = new Vector2(this.Position.X + CrosshairDistance * Godot.Mathf.Cos(angle), this.Position.Y + CrosshairDistance * Godot.Mathf.Sin(angle));
}
public override void _Process(double delta)
{
if (_isDestroyed)
{
if (Input.IsActionJustPressed(_shootActionName))
Respawn();
return;
};
SetAnimation();
if (!_canMove) return;
_movementDirection = GetInput();
_isStrafing = Input.IsActionPressed("strafe");
_isStrafing = Input.IsActionPressed(_strafeActionName);
// Toggle visibility of the hitbox sprite based on strafing
if (HitboxSprite != null)
{
@ -331,12 +374,12 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
HandleShoot();
FindInteractable();
if (Input.IsActionJustPressed("next_weapon"))
if (Input.IsActionJustPressed(_nextWeaponActionName))
{
NextWeapon();
}
if (Input.IsActionJustPressed("previous_weapon"))
if (Input.IsActionJustPressed(_previousWeaponActionName))
{
PreviousWeapon();
}
@ -344,8 +387,18 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
_crosshair.Position = CalculateCrosshairPosition();
}
public void Respawn()
{
if (!_isDestroyed) return;
_isDestroyed = false;
this.GlobalPosition = LastCheckPointPosition;
_healthProvider.FillResource();
this.Visible = true;
}
public override void _PhysicsProcess(double delta)
{
if (_isDestroyed) return;
if (!_canMove) return;
Velocity = _movementDirection * MovementSpeed;
@ -391,14 +444,18 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
Debug.WriteLine("Ded");
//CreateParticles();
//CreateDebris();
if (GameOverScene != null)
{
GetTree().ChangeSceneToFile(GameOverScene);
}
else
{
QueueFree();
}
// if (GameOverScene != null)
// {
// GetTree().ChangeSceneToFile(GameOverScene);
// }
// else
// {
// QueueFree();
// }
var particles = this.CreateSibling<AutodeleteParticle>(_deathParticles, this.GlobalPosition);
//particles.Init();
this.Visible = false;
EmitSignal(SignalName.Death);
}
public void Hit(float damage, DamageType type = DamageType.Neutral)
@ -410,7 +467,7 @@ public partial class PlayerMovement : CharacterBody2D, IDestructible
if (CurrentShield > 0 && type is not DamageType.Explosive or DamageType.Acid) {
// Reduce shield
CurrentShield -= damage;
if (_currentHealth < 0 ) {
if (CurrentShield < 0 ) {
CurrentHealth -= Math.Abs(CurrentShield);
CurrentShield = 0;
}

View file

@ -0,0 +1,32 @@
using Godot;
namespace Cirno.Scripts.Resources.Events;
[GlobalClass]
public partial class UpdateCheckPointEvent : EventResource
{
private GameManager _gameManager;
[Export]
public NodePath Target { get; set; }
public override void Init(Node2D parent)
{
_gameManager = parent.GetGameManager();
}
public override void Start(Node2D parent)
{
_gameManager.Player.LastCheckPointPosition = parent.GetNode<Node2D>(Target).GlobalPosition;
}
public override void UpdateEvent(double delta)
{
}
public override bool IsComplete()
{
return true;
}
}