288 lines
8.6 KiB
C#
288 lines
8.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Gameplay.Area;
|
|
using Gameplay.Character;
|
|
using Gameplay.Level;
|
|
using Gameplay.Vehicle.Impl;
|
|
using LTGame;
|
|
using UnityEngine;
|
|
namespace Gameplay.Vehicle.State
|
|
{
|
|
public class VehicleStateMove : BaseVehicleState
|
|
{
|
|
|
|
private List<int> _tgsPath;
|
|
private int _currentPathIndex;
|
|
private Map _map;
|
|
private Vector3 _targetPosition;
|
|
private int _lastTargetCellIndex;
|
|
private readonly List<Vector3> _roadPointList;
|
|
|
|
private float _lastMoveSpeed;
|
|
|
|
private int _loopAudioId;
|
|
|
|
private bool _isNoMove;
|
|
|
|
public VehicleStateMove(NormalVehicle owner) : base(owner, EVehicleState.Move)
|
|
{
|
|
_tgsPath = new List<int>();
|
|
_roadPointList = new List<Vector3>();
|
|
}
|
|
|
|
protected override void _OnEnter(NBaseState exitState,
|
|
object param)
|
|
{
|
|
base._OnEnter(exitState, param);
|
|
|
|
_lastTargetCellIndex = owner.controlData.targetCellIndex;
|
|
|
|
_map = LevelManager.Instance.CurrentLevel.Map;
|
|
_isNoMove = true;
|
|
// 初始化路径
|
|
_FindPath();
|
|
|
|
if (isFinished) return;
|
|
|
|
_isNoMove = false;
|
|
owner.statusData.isMoveing = true;
|
|
|
|
owner.vAnim.targetAnim = "move";
|
|
|
|
_PlayLoopAudio();
|
|
}
|
|
|
|
private void _PlayLoopAudio()
|
|
{
|
|
_loopAudioId = -1;
|
|
if (string.IsNullOrEmpty(owner.configData.audioData.walkLoopAudioId))
|
|
{
|
|
return;
|
|
}
|
|
_loopAudioId = AudioManager.Instance.PlayAudio(owner.configData.audioData.walkLoopAudioId, AudioCriManager.EPlayType.Sound, owner.Node.GameObject, true);
|
|
}
|
|
|
|
protected override void _OnRunning()
|
|
{
|
|
base._OnRunning();
|
|
|
|
owner.fightData.lastMoveTime = LevelManager.Instance.CurrentLevel.LevelTime;
|
|
|
|
if (owner.aliveData.currentHp <= 0)
|
|
{
|
|
isFinished = true;
|
|
nextState = EVehicleState.Destroy;
|
|
return;
|
|
}
|
|
|
|
// 如果目标改变,则重新寻路
|
|
if (_lastTargetCellIndex != owner.controlData.targetCellIndex)
|
|
{
|
|
isFinished = true;
|
|
nextState = EVehicleState.Move;
|
|
return;
|
|
}
|
|
|
|
// 持续判断当前索引格子是否可移动
|
|
var currentMoveCellIndex = _tgsPath[_currentPathIndex];
|
|
var isLocalMove = currentMoveCellIndex == owner.transData.cellIndex;
|
|
if (!isLocalMove)
|
|
{
|
|
// 同方格移动,不处理
|
|
var canMove = PathFinder.CanPass(currentMoveCellIndex, owner);
|
|
if (!canMove)
|
|
{
|
|
isFinished = true;
|
|
nextState = EVehicleState.Move;
|
|
return;
|
|
}
|
|
}
|
|
|
|
_DoMove();
|
|
}
|
|
|
|
protected override void _OnExit(NBaseState exitState,
|
|
object param)
|
|
{
|
|
base._OnExit(exitState, param);
|
|
|
|
owner.statusData.isMoveing = false;
|
|
|
|
if (_loopAudioId != 0)
|
|
{
|
|
AudioManager.Instance.StopSoundById(_loopAudioId);
|
|
}
|
|
|
|
_PlayStopAudio();
|
|
}
|
|
|
|
private void _PlayStopAudio()
|
|
{
|
|
if (string.IsNullOrEmpty(owner.configData.audioData.walkStopAudioId))
|
|
{
|
|
return;
|
|
}
|
|
AudioManager.Instance.PlayAudio(owner.configData.audioData.walkStopAudioId, AudioCriManager.EPlayType.Sound, owner.Node.GameObject);
|
|
DebugUtil.LogG("播放停止音效:" + owner.configData.audioData.walkStopAudioId);
|
|
}
|
|
|
|
private void _DoMove()
|
|
{
|
|
|
|
if (!_DirectMoveTo(_targetPosition, deltaTime))
|
|
{
|
|
// 还在走,就继续走
|
|
return;
|
|
}
|
|
|
|
|
|
// 到达转折点
|
|
_currentPathIndex++;
|
|
if (_currentPathIndex >= _tgsPath.Count)
|
|
{
|
|
if (owner.controlData.targetCellIndex != owner.transData.cellIndex)
|
|
{
|
|
// 重新寻路
|
|
isFinished = true;
|
|
nextState = EDownState.Move;
|
|
return;
|
|
}
|
|
// 到达终点
|
|
_ArriveBlock();
|
|
}
|
|
else
|
|
{
|
|
var newCellIndex = _tgsPath[_currentPathIndex];
|
|
// 更新目标点
|
|
_targetPosition = _map.TGSCellIndex2WorldPosition(newCellIndex);
|
|
}
|
|
}
|
|
|
|
private void _ArriveBlock()
|
|
{
|
|
isFinished = true;
|
|
nextState = _isNoMove ? EVehicleState.Idle : EVehicleState.Stop;
|
|
owner.controlData.targetCellIndex = -1;
|
|
owner.controlData.markEnemy = null;
|
|
Framework.EventManager.Instance.Send(Framework.EventManager.EventName.LevelCharacterArriveBlock, owner);
|
|
|
|
// 判断当前位置是否重叠
|
|
PathFinder.AvoidRepeat(owner);
|
|
}
|
|
|
|
private bool _DirectMoveTo(Vector3 pos,
|
|
float dt)
|
|
{
|
|
var currentPos = owner.transData.pos;
|
|
var toTarget = pos - currentPos;
|
|
toTarget.y = 0;
|
|
|
|
_RotateToBlock(toTarget, dt);
|
|
|
|
var requireDistance = toTarget.magnitude;
|
|
|
|
var moveSpeed = owner.fightData.GetMoveSpeed();
|
|
var moveDt = dt * moveSpeed;
|
|
|
|
if (moveDt < requireDistance)
|
|
{
|
|
var moveDir = toTarget.normalized;
|
|
var moveDistance = moveDt * moveDir;
|
|
var newPos = currentPos + moveDistance;
|
|
owner.transData.pos = newPos;
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// 直接到达目标点
|
|
owner.transData.pos = pos;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private void _RotateToBlock(Vector3 toTarget,
|
|
float dt)
|
|
{
|
|
var toAngle = Vector3.SignedAngle(Vector3.forward, toTarget, Vector3.up);
|
|
var currentAngle = owner.transData.yaw;
|
|
if (Math.Abs(toAngle - currentAngle) > 0.1f)
|
|
{
|
|
var turnSpeed = owner.fightData.turnSpeed;
|
|
var turnDt = dt * turnSpeed;
|
|
var newAngle = Mathf.MoveTowardsAngle(currentAngle, toAngle, turnDt);
|
|
owner.transData.yaw = newAngle;
|
|
}
|
|
|
|
}
|
|
|
|
private bool _IsFathExist()
|
|
{
|
|
return !(_tgsPath == null || _tgsPath.Count <= 0);
|
|
}
|
|
|
|
private void _FindPath()
|
|
{
|
|
if (_map == null) return;
|
|
|
|
_roadPointList.Clear();
|
|
_currentPathIndex = 0;
|
|
var to = owner.controlData.targetCellIndex;
|
|
var from = owner.transData.cellIndex;
|
|
|
|
if (to == from)
|
|
{
|
|
// 进行一次check
|
|
var nowPos = owner.transData.pos;
|
|
var targetPos = _map.TGSCellIndex2WorldPosition(to);
|
|
var distance = Vector3.Distance(nowPos, targetPos);
|
|
if (distance < 0.1f)
|
|
{
|
|
// 到达目标点
|
|
_ArriveBlock();
|
|
return;
|
|
}
|
|
}
|
|
|
|
owner.pathData.GetPath(_tgsPath, to);
|
|
|
|
// 再次判定是否可以直接走通
|
|
if (_IsFathExist())
|
|
{
|
|
_targetPosition = _map.TGSCellIndex2WorldPosition(_tgsPath[_currentPathIndex]);
|
|
}
|
|
else
|
|
{
|
|
owner.Log($"无有效路径: from:{from} to:{to}");
|
|
isFinished = true;
|
|
nextState = EDownState.Idle;
|
|
|
|
// 停止到当前节点
|
|
owner.StopToCurrentCell();
|
|
}
|
|
|
|
for (var i = _tgsPath.Count - 1; i >= 0; --i)
|
|
{
|
|
var tgsIndex = _tgsPath[i];
|
|
var worldPos = _map.TGSCellIndex2WorldPosition(tgsIndex);
|
|
_roadPointList.Add(worldPos);
|
|
}
|
|
if (!_tgsPath.Contains(owner.controlData.targetCellIndex))
|
|
{
|
|
var targetPos = _map.TGSCellIndex2WorldPosition(owner.controlData.targetCellIndex);
|
|
_roadPointList.Insert(0, targetPos);
|
|
}
|
|
}
|
|
|
|
public List<Vector3> CalcRoadLine()
|
|
{
|
|
return _roadPointList;
|
|
}
|
|
|
|
public int GetCurrentIndex()
|
|
{
|
|
return _currentPathIndex;
|
|
}
|
|
|
|
}
|
|
}
|