Вот мой сценарий сценария и переходы состояния: < /p>
using Godot;
using Godot.Collections;
using DialogueManagerRuntime;
using GodotUtilities;
[Scene]
public partial class Player : CharacterBody2D
{
[Export] private float walkingSpeed = 0.35f;
int tile_size = 16;
bool moving;
bool dialogueIsRunning;
Vector2 _inputDir = Vector2.Zero;
Vector2 last_dir = Vector2.Down;
Vector2 queuedDir;
AnimatedSprite2D charAnim;
Marker2D directionMarker;
Area2D actionableFinder;
private Tween tween;
private float bufferTime;
private bool enteredDoor;
private float originalSpeed;
[Node] private Sprite2D _playerSpr;
[Node] private AnimationPlayer _playerAnim;
[Node] private RayCast2D _rayCastUp;
[Node] private RayCast2D _rayCastDown;
[Node] private RayCast2D _rayCastLeft;
[Node] private RayCast2D _rayCastRight;
[Node] private StateMachine stateMachine;
public Vector2 GetInputDir()
{
return _inputDir;
}
public void SetInputDir(Vector2 dir)
{
_inputDir = dir;
}
public Vector2 GetLastDir(){ return last_dir; }
public void SetLastDir(Vector2 dir){ last_dir = dir; }
public override void _Ready()
{
WireNodes();
tween = CreateTween();
charAnim = GetNode("AnimatedSprite2D");
directionMarker = FindChild("Direction") as Marker2D;
actionableFinder = GetNode("Direction/Area2D");
if (actionableFinder == null)
{
GD.PrintErr("Something wrong");
}
else
{
GD.Print("Found: " + actionableFinder.Name);
}
DialogueManager.DialogueEnded += OnDialogueEnded;
enteredDoor = false;
originalSpeed = walkingSpeed;
GD.Print("Original Speed" + originalSpeed);
}
public float GetWalkingSpeed()
{
return walkingSpeed;
}
public void ModifySpeed(float modifier, bool original)
{
if (original)
{
walkingSpeed = originalSpeed;
}
else
{
walkingSpeed *= modifier;
}
walkingSpeed *= modifier;
}
public void SetEnteredDoor(bool isEnteredDoor)
{
enteredDoor = isEnteredDoor;
}
public override void _ExitTree()
{
DialogueManager.DialogueEnded -= OnDialogueEnded;
enteredDoor = false ;
}
private void OnDialogueEnded(Resource dialogue)
{
dialogueIsRunning = false;
}
public override void _UnhandledInput(InputEvent @event)
{
if (Input.IsActionJustPressed("ui_accept"))
{
Array actionables = actionableFinder.GetOverlappingAreas();
if (actionables.Count > 0)
{
(actionables[0] as Actionable).Action();
_inputDir = Vector2.Zero;
GD.Print("Hey Man!");
dialogueIsRunning = true;
}
}
}
public override void _Input(InputEvent @event)
{
Vector2 dir = Vector2.Zero;
if (Input.IsActionPressed("ui_left"))
{
dir = Vector2.Left;
}
else if (Input.IsActionPressed("ui_right"))
{
dir = Vector2.Right;
}
else if (Input.IsActionPressed("ui_down"))
{
dir = Vector2.Down;
}
else if (Input.IsActionPressed("ui_up"))
{
dir = Vector2.Up;
}
if (dir != Vector2.Zero && stateMachine.CurrentState.Name == "IdleState")
{
_inputDir = dir;
GD.Print("WalkingState: " + _inputDir);
EventManager.BroadcastStateChangedEvent(this, "WalkingState");
} else if (dir != Vector2.Zero)
{
_inputDir = dir;
}
}
protected internal void StopMovement()
{
_inputDir = Vector2.Zero;
EventManager.BroadcastStateChangedEvent(this, "IdleState");
}
}
< /code>
А вот логика для моего состояния ходьбы, которая обрабатывает фактическое движение < /p>
Код: Выделить всё
using Godot;
using System;
using System.Runtime.InteropServices.JavaScript;
public partial class WalkingState : State
{
[Export]private Player _player;
[Export] private int tile_size = 16;
[Export] private float walking_speed = 0.5f;
[Export] private RayCast2D _rayCastUp;
[Export] private RayCast2D _rayCastDown;
[Export] private RayCast2D _rayCastLeft;
[Export] private RayCast2D _rayCastRight;
[Export] private AnimationPlayer _playerAnimation;
private Vector2 _inputDir;
private Tween _walkingTween;
private bool isMoving = false;
private bool isQueued = false;
private Vector2 newDir;
public override void EnterState()
{
base.EnterState();
_player ??= parentStateMachine.Parent as Player;
if (_player != null)
{
_inputDir = _player.GetInputDir();
//SetRayCast(_inputDir);
Move(_inputDir);
PlayWalkingAnimation(_inputDir);
_player.SetLastDir(_inputDir);
}
else
{
GD.PrintErr("WalkingState: player is null");
}
}
public override void ExitState()
{
base.ExitState();
}
public override void ProcessState(double delta)
{
newDir = _player.GetInputDir();
if (newDir != _inputDir)
{
GD.Print("Assigning new direction");
_inputDir = newDir;
}
if (!IsKeyPressed() || _walkingTween.IsRunning() )
{
return;
}
_player.SetLastDir(_inputDir);
PlayWalkingAnimation(newDir);
Move(_inputDir);
}
public override void PhysicsProcessState(double delta)
{
//base.PhysicsProcessState(delta);
}
private void Move(Vector2 dir)
{
if (!CanMove())
{
GD.Print("Colliding");
_playerAnimation.Pause();
_player.StopMovement();
return;
}
if(isMoving) return;
isMoving = true;
if (_walkingTween != null)
{
_walkingTween.Kill();
}
_walkingTween = CreateTween();
Vector2 newPos = _player.Position + dir * tile_size;
_walkingTween.TweenProperty(_player, "position", newPos, walking_speed)
.SetEase(Tween.EaseType.InOut)
.SetTrans(Tween.TransitionType.Linear);
_walkingTween.Finished += () =>
{
GD.PrintRich("[color=green]Hello world![/color]");
isMoving = false;
if (!IsKeyPressed())
{
_playerAnimation.Pause();
_player.StopMovement();
GD.Print("Walking ended");
}
};
}
private void OnTweenFinished()
{
isMoving = false;
}
private bool CanMove()
{
if (_rayCastLeft.IsColliding() && _inputDir == Vector2.Left|| _rayCastRight.IsColliding() && _inputDir == Vector2.Right ||
_rayCastUp.IsColliding() && _inputDir == Vector2.Up || _rayCastDown.IsColliding() && _inputDir == Vector2.Down)
{
GD.Print("Colliding");
return false;
}
return true;
}
private void SetRayCast(Vector2 dir)
{
_rayCastUp.Enabled = false;
_rayCastDown.Enabled = false;
_rayCastLeft.Enabled = false;
_rayCastRight.Enabled = false;
if (_inputDir == Vector2.Right)
{
_rayCastRight.Enabled = true;
}
if (_inputDir == Vector2.Left)
{
_rayCastLeft.Enabled = true;
}
if (_inputDir == Vector2.Up)
{
_rayCastUp.Enabled = true;
}
if (_inputDir == Vector2.Down)
{
_rayCastDown.Enabled = true;
}
}
private bool IsKeyPressed()
{
return Input.IsActionPressed("ui_left") ||
Input.IsActionPressed("ui_right") ||
Input.IsActionPressed("ui_up") ||
Input.IsActionPressed("ui_down");
}
private void PlayWalkingAnimation(Vector2 dir)
{
if (!IsKeyPressed())
{
return;
}
String animationName = "";
GD.Print("Should play animation: " + CanMove());
if (dir == Vector2.Down)
{
_playerAnimation.Play("Down");
animationName = "Down";
}
if (dir == Vector2.Up)
{
_playerAnimation.Play("Up");
animationName = "Up";
}
if (dir == Vector2.Right)
{
_playerAnimation.Play("Right");
animationName = "Right";
}
if (dir == Vector2.Left)
{
_playerAnimation.Play("Left");
animationName = "Left";
}
if (_playerAnimation.CurrentAnimation != animationName)
{
_playerAnimation.Play(animationName);
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... ent-system
Мобильная версия