Refactor enemy view model for data viewer project
This commit is contained in:
108
src/enemy/EnemyModelView.cs
Normal file
108
src/enemy/EnemyModelView.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.GodotNodeInterfaces;
|
||||
using Chickensoft.Introspection;
|
||||
using GameJamDungeon;
|
||||
using Godot;
|
||||
|
||||
public interface IEnemyModelView : INode3D
|
||||
{
|
||||
public void PlayAttackAnimation();
|
||||
|
||||
public void PlayHitAnimation();
|
||||
public void PlayDeathAnimation();
|
||||
|
||||
public void RotateModel(Basis enemyBasis, Vector3 cameraDirection);
|
||||
}
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class EnemyModelView : Node3D, IEnemyModelView
|
||||
{
|
||||
private const string ATTACK = "attack";
|
||||
private const string IDLE_FORWARD = "idle_front_walk";
|
||||
private const string IDLE_LEFT = "idle_left_walk";
|
||||
private const string IDLE_BACK = "idle_back_walk";
|
||||
private const string PARAMETERS_PLAYBACK = "parameters/playback";
|
||||
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Node] public AnimatedSprite2D AnimatedSprite { get; set; } = default!;
|
||||
|
||||
[Node] public IHitbox Hitbox { get; set; } = default!;
|
||||
|
||||
[Node] public AnimationPlayer AnimationPlayer { get; set; } = default!;
|
||||
|
||||
[Node] public AnimationTree AnimationTree { get; set; } = default!;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
AnimationTree.AnimationFinished += AnimationTree_AnimationFinished;
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Start(IDLE_FORWARD);
|
||||
}
|
||||
|
||||
public void PlayAttackAnimation()
|
||||
{
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(ATTACK);
|
||||
}
|
||||
|
||||
public void PlayHitAnimation()
|
||||
{
|
||||
LoadShader("res://src/vfx/shaders/DamageHit.gdshader");
|
||||
var tweener = GetTree().CreateTween();
|
||||
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
public void PlayDeathAnimation()
|
||||
{
|
||||
LoadShader("res://src/vfx/shaders/PixelMelt.gdshader");
|
||||
var tweener = GetTree().CreateTween();
|
||||
tweener.TweenMethod(Callable.From((float x) => SetShaderValue(x)), 0.0f, 1.0f, 0.8f);
|
||||
tweener.TweenCallback(Callable.From(QueueFree));
|
||||
}
|
||||
|
||||
public void RotateModel(Basis enemyBasis, Vector3 cameraDirection)
|
||||
{
|
||||
var rotateUpperThreshold = 0.85f;
|
||||
var rotateLowerThreshold = 0.3f;
|
||||
|
||||
var enemyForwardDirection = enemyBasis.Z;
|
||||
var enemyLeftDirection = enemyBasis.X;
|
||||
|
||||
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)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_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)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_BACK);
|
||||
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).
|
||||
AnimatedSprite.FlipH = leftDotProduct > 0;
|
||||
// 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)
|
||||
AnimationTree.Get(PARAMETERS_PLAYBACK).As<AnimationNodeStateMachinePlayback>().Travel(IDLE_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadShader(string shaderPath)
|
||||
{
|
||||
var shader = GD.Load<Shader>(shaderPath);
|
||||
AnimatedSprite.Material = new ShaderMaterial();
|
||||
var shaderMaterial = (ShaderMaterial)AnimatedSprite.Material;
|
||||
shaderMaterial.Shader = shader;
|
||||
}
|
||||
|
||||
private void AnimationTree_AnimationFinished(StringName animName)
|
||||
{
|
||||
if (animName == "attack")
|
||||
AnimationTree.Get("parameters/playback").As<AnimationNodeStateMachinePlayback>().Travel(IDLE_FORWARD);
|
||||
}
|
||||
|
||||
private void SetShaderValue(float shaderValue)
|
||||
{
|
||||
var shaderMaterial = (ShaderMaterial)AnimatedSprite.Material;
|
||||
shaderMaterial.SetShaderParameter("progress", shaderValue);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user