Big refactor in place: Organize nodes in line with dependency injection expectations, use state machine flow more

This commit is contained in:
2024-09-11 15:33:36 -07:00
parent 6a4eb81529
commit 4d47a7586e
63 changed files with 1123 additions and 469 deletions

View File

@@ -7,7 +7,7 @@ using Godot;
namespace GameJamDungeon
{
public interface IPlayer : ICharacterBody3D
public interface IPlayer : ICharacterBody3D, IKillable
{
PlayerStatInfo PlayerStatInfo { get; }
@@ -84,7 +84,7 @@ namespace GameJamDungeon
public void Setup()
{
Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed };
Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration };
PlayerLogic = new PlayerLogic();
PlayerLogic.Set(this as IPlayer);
@@ -92,14 +92,6 @@ namespace GameJamDungeon
PlayerLogic.Set(AppRepo);
PlayerLogic.Set(GameRepo);
PlayerLogic.Set(PlayerData);
GameRepo.SetPlayerGlobalPosition(GlobalPosition);
GameRepo.PlayerGlobalPosition.Sync += OnPlayerPositionUpdated;
GameRepo.SetPlayerStatInfo(PlayerStatInfo);
HealthTimer.Timeout += OnHealthTimerTimeout;
CollisionDetector.AreaEntered += OnEnemyHitBoxEntered;
}
public void OnResolved()
@@ -127,6 +119,11 @@ namespace GameJamDungeon
PlayerLogic.Start();
SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2;
GlobalPosition = GameRepo.PlayerGlobalPosition.Value;
GameRepo.SetPlayerStatInfo(PlayerStatInfo);
HealthTimer.Timeout += OnHealthTimerTimeout;
CollisionDetector.AreaEntered += OnEnemyHitBoxEntered;
}
public void OnReady()
@@ -227,6 +224,8 @@ namespace GameJamDungeon
AnimationPlayer.AnimationFinished -= OnAnimationFinished;
}
public void Kill() => PlayerLogic.Input(new PlayerLogic.Input.Killed());
private void OnHPChanged(double newHP)
{
HPNumber.Text = $"{Mathf.RoundToInt(newHP)}/{PlayerStatInfo.MaximumHP}";

View File

@@ -98,8 +98,8 @@ tracks/1/keys = {
[sub_resource type="AnimationLibrary" id="AnimationLibrary_w8l8m"]
_data = {
"RESET": SubResource("Animation_hcjph"),
"attack": SubResource("Animation_0jjwv")
&"attack": SubResource("Animation_0jjwv"),
&"RESET": SubResource("Animation_hcjph")
}
[sub_resource type="SpriteFrames" id="SpriteFrames_ywvvo"]
@@ -139,8 +139,9 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.381018, 0)
collision_layer = 38
collision_mask = 7
script = ExtResource("1_xcol5")
RotationSpeed = 0.025
MoveSpeed = 2.0
RotationSpeed = 3.0
MoveSpeed = 4.0
Acceleration = 1.0
PlayerStatInfo = SubResource("Resource_up0v1")
[node name="Hitbox" type="Area3D" parent="."]
@@ -182,7 +183,7 @@ omni_range = 83.659
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
libraries = {
"": SubResource("AnimationLibrary_w8l8m")
&"": SubResource("AnimationLibrary_w8l8m")
}
[node name="SwordSlashAnimation" type="AnimatedSprite2D" parent="."]

View File

@@ -1,7 +1,16 @@
namespace GameJamDungeon
using Chickensoft.Serialization;
using Godot;
namespace GameJamDungeon
{
public partial record PlayerData
{
// TODO: Implement save system
[Save("global_transform")]
public required Transform3D GlobalTransform { get; init; }
[Save("state_machine")]
public required PlayerLogic StateMachine { get; init; }
[Save("velocity")]
public required Vector3 Velocity { get; init; }
}
}

View File

@@ -7,6 +7,8 @@
public float MoveSpeed { get; set; }
public float RotationSpeed { get; set; }
public float Acceleration { get; set; }
}
}
}

View File

@@ -1,20 +1,22 @@
@startuml PlayerLogic
state "PlayerLogic State" as GameJam2024Practice_PlayerLogic_State {
state "Alive" as GameJam2024Practice_PlayerLogic_State_Alive {
state "Idle" as GameJam2024Practice_PlayerLogic_State_Idle
state "Attacking" as GameJam2024Practice_PlayerLogic_State_Attacking
state "PlayerLogic State" as GameJamDungeon_PlayerLogic_State {
state "Alive" as GameJamDungeon_PlayerLogic_State_Alive {
state "Attacking" as GameJamDungeon_PlayerLogic_State_Attacking
state "Idle" as GameJamDungeon_PlayerLogic_State_Idle
}
state "Disabled" as GameJam2024Practice_PlayerLogic_State_Disabled
state "Dead" as GameJamDungeon_PlayerLogic_State_Dead
state "Disabled" as GameJamDungeon_PlayerLogic_State_Disabled
}
GameJam2024Practice_PlayerLogic_State_Alive --> GameJam2024Practice_PlayerLogic_State_Alive : Moved
GameJam2024Practice_PlayerLogic_State_Alive --> GameJam2024Practice_PlayerLogic_State_Alive : PhysicsTick
GameJam2024Practice_PlayerLogic_State_Attacking --> GameJam2024Practice_PlayerLogic_State_Idle : AttackAnimationFinished
GameJam2024Practice_PlayerLogic_State_Disabled --> GameJam2024Practice_PlayerLogic_State_Idle : Enable
GameJam2024Practice_PlayerLogic_State_Idle --> GameJam2024Practice_PlayerLogic_State_Attacking : Attack
GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Alive : Moved
GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Alive : PhysicsTick
GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Dead : Killed
GameJamDungeon_PlayerLogic_State_Attacking --> GameJamDungeon_PlayerLogic_State_Idle : AttackAnimationFinished
GameJamDungeon_PlayerLogic_State_Disabled --> GameJamDungeon_PlayerLogic_State_Idle : Enable
GameJamDungeon_PlayerLogic_State_Idle --> GameJamDungeon_PlayerLogic_State_Attacking : Attack
GameJam2024Practice_PlayerLogic_State_Alive : OnPhysicsTick → MovementComputed
GameJam2024Practice_PlayerLogic_State_Idle : OnAttack → Attack
GameJamDungeon_PlayerLogic_State_Alive : OnPhysicsTick → MovementComputed
GameJamDungeon_PlayerLogic_State_Idle : OnAttack → Attack
[*] --> GameJam2024Practice_PlayerLogic_State_Disabled
[*] --> GameJamDungeon_PlayerLogic_State_Idle
@enduml

View File

@@ -12,6 +12,7 @@ namespace GameJamDungeon
{
public virtual Transition On(in Input.PhysicsTick input)
{
var delta = input.Delta;
var player = Get<IPlayer>();
var settings = Get<Settings>();
@@ -20,8 +21,9 @@ namespace GameJamDungeon
var strafeRightInput = player.GetRightStrafeInputVector();
var transform = player.Transform;
transform.Basis = new Basis(Vector3.Up, settings.RotationSpeed * -rawInput.X) * transform.Basis;
var velocity = player.Basis * new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z) * settings.MoveSpeed;
transform.Basis = new Basis(Vector3.Up, settings.RotationSpeed * -rawInput.X * (float)delta) * transform.Basis;
var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z);
var velocity = player.Basis * moveDirection * settings.MoveSpeed * settings.Acceleration;
Output(new Output.MovementComputed(transform.Basis, velocity));
@@ -38,7 +40,7 @@ namespace GameJamDungeon
public Transition On(in Input.Killed input)
{
GD.Print("Player died");
return To<Disabled>();
return To<Dead>();
}
}
}

View File

@@ -0,0 +1,12 @@
using Chickensoft.Introspection;
namespace GameJamDungeon;
public partial class PlayerLogic
{
public abstract partial record State
{
[Meta, Id("player_logic_state_dead")]
public partial record Dead : State;
}
}