Simplify enemy animation logic

This commit is contained in:
2025-10-06 02:13:05 -07:00
parent ad29e57fc9
commit ec0f9ebff7
56 changed files with 1584 additions and 5011 deletions

View File

@@ -7,24 +7,11 @@ namespace Zennysoft.Game.Ma;
[Meta(typeof(IAutoNode))]
public partial class EnemyModelView2D : Node3D, IEnemyModelView
{
protected const string PRIMARY_ATTACK = "primary_attack";
protected const string PRIMARY_ATTACK_LEFT = "primary_attack_left";
protected const string PRIMARY_ATTACK_RIGHT = "primary_attack_right";
protected const string PRIMARY_ATTACK_BACK = "primary_attack_back";
protected const string SECONDARY_ATTACK = "secondary_attack";
protected const string SECONDARY_ATTACK_LEFT = "secondary_attack_left";
protected const string SECONDARY_ATTACK_RIGHT = "secondary_attack_right";
protected const string SECONDARY_ATTACK_BACK = "secondary_attack_back";
protected const string PRIMARY_SKILL = "primary_skill";
protected const string IDLE_FORWARD = "idle_front";
protected const string IDLE_LEFT = "idle_left";
protected const string IDLE_RIGHT = "idle_right";
protected const string IDLE_BACK = "idle_back";
protected const string IDLE_FORWARD_WALK = "idle_front_walk";
protected const string IDLE_LEFT_WALK = "idle_left_walk";
protected const string IDLE_RIGHT_WALK = "idle_right_walk";
protected const string IDLE_BACK_WALK = "idle_back_walk";
protected const string PARAMETERS_PLAYBACK = "parameters/playback";
private readonly string _idleName = "Idle";
private readonly string _walkingName = "Walking";
private readonly string _primaryAttackName = "Primary Attack";
private readonly string _secondaryAttackName = "Secondary Attack";
private readonly string _activateName = "Activate";
public override void _Notification(int what) => this.Notify(what);
@@ -38,52 +25,30 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
[Node] public AnimationTree AnimationTree { get; set; } = default!;
protected DirectionType _currentDirection = DirectionType.FORWARD;
[ExportGroup("Animation Debug")]
[Export(PropertyHint.Enum)]
EnemyDirection _enemyDirection { get; set; } = EnemyDirection.Forward;
public void SetCurrentDirection(Basis enemyBasis, Vector3 cameraDirection) => _currentDirection = GetEnemyDirection(enemyBasis, cameraDirection, 0.55f, 0.45f);
private AnimationNodeStateMachinePlayback _stateMachine;
public void PlayPrimaryAttackAnimation()
public void OnReady()
{
switch (_currentDirection)
{
case DirectionType.FORWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK);
break;
case DirectionType.RIGHT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK_RIGHT);
break;
case DirectionType.LEFT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK_LEFT);
break;
case DirectionType.BACKWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_ATTACK_BACK);
break;
}
_stateMachine = (AnimationNodeStateMachinePlayback)AnimationTree.Get("parameters/playback");
}
public void PlaySecondaryAttackAnimation()
{
switch (_currentDirection)
{
case DirectionType.FORWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK);
break;
case DirectionType.RIGHT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK_RIGHT);
break;
case DirectionType.LEFT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK_LEFT);
break;
case DirectionType.BACKWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(SECONDARY_ATTACK_BACK);
break;
}
}
public void SetCurrentDirection(Basis enemyBasis, Vector3 cameraDirection) => _enemyDirection = GetEnemyDirection(enemyBasis, cameraDirection, 0.55f, 0.45f);
public void PlayPrimarySkillAnimation()
{
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(PRIMARY_SKILL);
}
public void PlayPrimaryAttackAnimation() => _stateMachine.Travel(_primaryAttackName);
public void PlaySecondaryAttackAnimation() => _stateMachine.Travel(_secondaryAttackName);
public void PlayPrimarySkillAnimation() => _stateMachine.Travel("Primary Skill");
public void PlayIdleAnimation() => _stateMachine.Travel(_idleName);
public void PlayWalkAnimation() => _stateMachine.Travel(_walkingName);
public void PlayActivateAnimation() => _stateMachine.Travel(_activateName);
public void PlayHitAnimation()
{
@@ -100,49 +65,11 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
tweener.TweenCallback(Callable.From(QueueFree));
}
public virtual void PlayIdleAnimation()
{
switch (_currentDirection)
{
case DirectionType.FORWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD);
break;
case DirectionType.RIGHT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_RIGHT);
break;
case DirectionType.LEFT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT);
break;
case DirectionType.BACKWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK);
break;
}
}
public virtual void PlayWalkAnimation()
{
switch (_currentDirection)
{
case DirectionType.FORWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD_WALK);
break;
case DirectionType.RIGHT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_RIGHT_WALK);
break;
case DirectionType.LEFT:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT_WALK);
break;
case DirectionType.BACKWARD:
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK_WALK);
break;
}
}
private DirectionType GetEnemyDirection(
Basis enemyBasis,
Vector3 cameraDirection,
float rotateUpperThreshold,
float rotateLowerThreshold)
private EnemyDirection GetEnemyDirection(
Basis enemyBasis,
Vector3 cameraDirection,
float rotateUpperThreshold,
float rotateLowerThreshold)
{
var enemyForwardDirection = enemyBasis.Z;
var enemyLeftDirection = enemyBasis.X;
@@ -150,25 +77,37 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
var leftDotProduct = enemyLeftDirection.Dot(cameraDirection);
var forwardDotProduct = enemyForwardDirection.Dot(cameraDirection);
// Check if forward facing. If the dot product is -1, the enemy is facing the camera.
if (forwardDotProduct < -rotateUpperThreshold)
return DirectionType.FORWARD;
// Check if forward facing. If the dot product is -1, the enemy is facing the camera.
if (forwardDotProduct < -rotateUpperThreshold)
{
SetForward();
return EnemyDirection.Forward;
}
// Check if backward facing. If the dot product is 1, the enemy is facing the same direction as the camera.
else if (forwardDotProduct > rotateUpperThreshold)
return DirectionType.BACKWARD;
else
{
// If the dot product of the perpendicular direction is positive (up to 1), the enemy is facing to the left (since it's mirrored).
if (leftDotProduct > 0)
return DirectionType.RIGHT;
// Check if backward facing. If the dot product is 1, the enemy is facing the same direction as the camera.
else if (forwardDotProduct > rotateUpperThreshold)
{
SetBack();
return EnemyDirection.Backward;
}
else
{
// If the dot product of the perpendicular direction is positive (up to 1), the enemy is facing to the left (since it's mirrored).
if (leftDotProduct > 0)
{
SetRight();
return EnemyDirection.Right;
}
// Check if side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning.
if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold)
return DirectionType.LEFT;
}
// Check if side facing. If the dot product is close to zero in the positive or negative direction, its close to the threshold for turning.
if (Mathf.Abs(forwardDotProduct) < rotateLowerThreshold)
{
SetLeft();
return EnemyDirection.Left;
}
}
return _currentDirection;
return _enemyDirection;
}
private void LoadShader(string shaderPath)
@@ -185,12 +124,39 @@ public partial class EnemyModelView2D : Node3D, IEnemyModelView
private void SetShaderValue(float shaderValue)
{
var sprites = FindChildren("*", "AnimatedSprite2D", true).Cast<AnimatedSprite2D>();
foreach (var sprite in sprites)
{
var shaderMaterial = (ShaderMaterial)sprite.Material;
shaderMaterial.SetShaderParameter("progress", shaderValue);
}
var sprites = FindChildren("*", "AnimatedSprite2D", true).Cast<AnimatedSprite2D>();
foreach (var sprite in sprites)
{
var shaderMaterial = (ShaderMaterial)sprite.Material;
shaderMaterial.SetShaderParameter("progress", shaderValue);
}
}
private void SetForward()
{
_enemyDirection = EnemyDirection.Forward;
}
private void SetLeft()
{
_enemyDirection = EnemyDirection.Left;
}
private void SetRight()
{
_enemyDirection = EnemyDirection.Right;
}
private void SetBack()
{
_enemyDirection = EnemyDirection.Backward;
}
private enum EnemyDirection
{
Left,
Right,
Forward,
Backward
}
}