using DG.Tweening;
using FL.Battle.Actions;
using System;
using UnityEngine;
using XGame.Framework;
using XGame.Framework.Components;
using XGame.Framework.Map;
using XGame.Framework.Time;
namespace FL.Battle.Components
{
public interface IMoveContext
{
///
/// 所有者的根节点
///
Transform OwnerTr { get; }
}
public enum EMoveType
{
///
/// 直线运动
/// DoTween.DOMove
///
Line = 0,
///
/// 贝塞尔曲线轨迹
///
Bezier,
///
/// 抛物线
///
Parabola,
///
/// AnimationCurve曲线
///
Curve,
}
///
/// 移动参数
///
public struct MoveArgs
{
public Vector3 target;
public float speed;
///
/// 时间缩放值,默认需要传1
///
public float timeScale;
public EMoveType moveType;
public Ease ease;
///
/// 延迟,单位: 毫秒
///
public int delay;
//public Action onUpdate;
public Action onComplete;
///
/// 曲线
/// EMoveType.Curve时有效
///
public AnimationCurve curve;
///
/// 曲线的偏移量
/// EMoveType.Curve时有效
///
public Vector3 curveOffset;
}
///
/// DoTween.DOLocalMoveY
///
public class MoveComponent : Component, IParallelTarget, IPauseable, ITimeScalable
{
private IAction _action;
public Vector3 MoveDir { get; private set; }
public bool IsMoving => _action != null;
Vector3 IParallelTarget.Position => Context.OwnerTr.position;
public float TimeScale
{
get
{
if (_action is ITimeScalable scalable)
{
return scalable.TimeScale;
}
return 1;
}
set
{
if (_action is ITimeScalable scalable)
{
scalable.TimeScale = value;
}
}
}
public void MoveTo(MoveArgs args)
{
var position = Context.OwnerTr.position;
var duration = Mathf.RoundToInt(Vector3.Distance(args.target, position) * 1000 / args.speed);
MoveDir = Vector3.Normalize(args.target - position);
void OnCompleted()
{
ObjectPool.Recycle(_action);
_action = null;
MoveDir = Vector3.zero;
args.onComplete.SafeInvoke();
}
var actionArgs = new MoveActionArgs()
{
from = position,
to = args.target,
duration = duration,
delay = args.delay,
ease = args.ease,
//onUpdate = args.onUpdate,
onComplete = OnCompleted
};
if (args.moveType is EMoveType.Line)
{
var move = ObjectPool.Acquire();
_action = move;
move.args = actionArgs;
move.Start(Context.OwnerTr);
}
else if (args.moveType is EMoveType.Bezier)
{
var move = ObjectPool.Acquire();
_action = move;
move.args = actionArgs;
move.Start(Context.OwnerTr, false);
}
else if (args.moveType is EMoveType.Curve)
{
var move = ObjectPool.Acquire();
_action = move;
move.args = actionArgs;
move.curve = args.curve;
move.curveOffset = args.curveOffset;
move.Start(Context.OwnerTr);
}
else
{
var move = ObjectPool.Acquire();
_action = move;
move.args = actionArgs;
move.Start(Context.OwnerTr);
}
if (args.timeScale != 1)
{
TimeScale = args.timeScale;
}
}
public void Pause()
{
(_action as IPauseable)?.Pause();
}
public void Resume()
{
(_action as IPauseable)?.Resume();
}
public void StopMove()
{
if (_action != null)
{
ObjectPool.Recycle(_action);
_action = null;
MoveDir = Vector3.zero;
}
}
protected override void OnDispose()
{
StopMove();
}
}
}