第十一章 地图动作与地图事件(Map Action and Map Event)
我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制。
我们这一章来完成地图上的操作,地图的操作将全部由MapAction
控制。
文章目录
五 移动、攻击与待机(Move, Attack and Holding)
我们在之前把这个方法MoveMapClass
和AttackMapClass
留空了。
这一节,我们来填充方法,并增加一个待机HoldingMapClass
。
1 移动(Move)
我们在移动之前需要:
-
隐藏移动范围光标;
-
隐藏鼠标光标;
而在移动的方法,在之前寻路的测试环节已经写过了,所以这里不再过多叙述。
填充方法:
/// <summary>
/// 移动
/// </summary>
/// <param name="mapClass"></param>
/// <param name="moveTo"></param>
protected void MoveMapClass(MapClass mapClass, CellData moveTo)
{
// 隐藏光标
map.HideRangeCursors();
DisplayMouseCursor(false);
// 开始移动动画
Stack<CellData> path = map.searchPath.BuildPath(moveTo);
mapClass.onMovingEnd += MapClass_OnMovingEnd;
mapStatus = MapStatus.Animation;
mapClass.animatorController.PlayMove();
mapClass.StartMove(path);
}
/// <summary>
/// 移动结束回调
/// </summary>
/// <param name="mapClass"></param>
/// <param name="endCell"></param>
private void MapClass_OnMovingEnd(CellData endCell)
{
mapClass.onMovingEnd -= MapClass_OnMovingEnd;
// TODO
}
2 移动结束(On Moving End)
在移动结束时,我们需要:
-
设置开始格子的地图对象;
-
设置结束格子的地图对象;
-
角色消耗移动力;
-
打开子菜单(移动后菜单)。
填充MapClass_OnMovingEnd
方法:
/// <summary>
/// 移动结束回调
/// </summary>
/// <param name="endCell"></param>
private void MapClass_OnMovingEnd(CellData endCell)
{
selectedUnit.onMovingEnd -= MapClass_OnMovingEnd;
// 设置坐标
selectedCell.mapObject = null;
movingEndCell = endCell;
movingEndCell.mapObject = selectedUnit;
selectedUnit.UpdatePosition(movingEndCell.position);
map.mouseCursor.UpdatePosition(movingEndCell.position);
mapClass.role.OnMoveEnd(endCell.g); // 减去移动消耗
ShowMapMenu(true);
}
其中还需要在Role
中添加移动消耗方法:
public void OnMoveEnd(float consume)
{
self.movePoint -= consume;
}
减去移动消耗时会有错误。这是由于,我们在寻找移动范围与攻击范围时同时对g
进行了操作,破坏了数值,这只需要在搜寻攻击范围时使用h
,而不是使用g
就可以解决。只有移动范围使用g
。
// 以下在 PathFinding 中的SearchAttackRange,将 g 改成 h
if (useEndCell)
{
m_EndCell = start;
m_EndCell.h = 0f;
m_Reachable.Add(m_EndCell);
}
else
{
m_StartCell = start;
m_StartCell.h = 0f;
m_Reachable.Add(m_StartCell);
}
// 以下在 FindRange 中,将 g 改成 h
public virtual bool CanAddAdjacentToReachable(PathFinding search, CellData adjacent)
{
// 如果已经在关闭集
if (search.IsCellInExpored(adjacent))
{
return false;
}
// 已经加入过开放集
if (search.IsCellInReachable(adjacent))
{
return false;
}
// 计算消耗 = 当前cell的消耗 + 邻居cell的消耗
float h = search.currentCell.h + CalcGPerCell(search, adjacent);
// 不在范围内
if (h < 0f || h > search.range.y)
{
return false;
}
adjacent.h = h;
return true;
}
public virtual void BuildResult(PathFinding search)
{
for (int i = 0; i < search.explored.Count; i++)
{
CellData cell = search.explored[i];
if (cell.h >= search.range.x && cell.h <= search.range.y)
{
search.result.Add(cell);
}
}
}
// 以下在 FindMoveRange 中,增加 override 方法
public