NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Map/MapPathfind.cs

1446 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Generic;
using System.IO;
using TGS;
using Unity.Mathematics;
using UnityEngine;
using NLDPB;
using System.Diagnostics;
using Gameplay;
public class MapHex
{
public const float Length = 1.73205f;
public const float Radius = 1.5f;
public int index;
public int Nx;
public int Nz;
public int Ax;
public int Ay;
public int Az;
public float Wx;
public float Wz;
public int CityID;
public int StaticCamp;
public int Camp;
public bool isChecked;
public void SetData( int nWidth, int nHeight, int nIndex )
{
//index = Nz * nWidth + Nx
index = nIndex;
Nz = nIndex/nWidth;
Nx = nIndex - Nz *nWidth;
Az = Nz;
Ax = Nx-Nz/2;
Ay = -Ax-Az;
Wx = (Nx + Nz * 0.5f - Nz / 2 ) * (Radius*2.0f);
Wz = Nz * (Length*1.5f);
}
public override string ToString() {
return $"index={index}, NC=({Nx}, {Nz}), AC=({Ax}, {Ay}, {Az}), WC=({Wx}, 0, {Wz}), City ID={CityID}";
}
public bool IsMyNext(MapHex hex)
{
int xOffset = math.abs(hex.Ax- Ax);
int zOffset = math.abs(hex.Az-Az);
int yOffset = math.abs(hex.Ay-Ay);
return xOffset <= 1 && zOffset <= 1 && yOffset <= 1;
}
public bool IsMe(MapHex hex)
{
return hex.Nx == Nx && hex.Nz == Nz;
}
public int Distance(MapHex hex)
{
int xOffset = math.abs(hex.Ax- Ax);
int zOffset = math.abs(hex.Az-Az);
int yOffset = math.abs(hex.Ay-Ay);
return math.max(yOffset, math.max(xOffset, zOffset));
}
public bool CanPass(int startCityID, int endCityID)
{
if(CityID > 0) {
return CityID == startCityID || CityID == endCityID;
} else {
return true;
}
}
public bool IsCampSource() {
return Camp == (int)BattlefieldActorCamp.CampAsource || Camp == (int)BattlefieldActorCamp.CampBsource;
}
public int GetRealCamp() {
switch (Camp) {
case (int)BattlefieldActorCamp.CampAsource:
return (int)BattlefieldActorCamp.CampA;
case (int)BattlefieldActorCamp.CampBsource:
return (int)BattlefieldActorCamp.CampB;
default:
return Camp;
}
}
public bool IsRealCamp() {
switch(Camp) {
case (int)BattlefieldActorCamp.CampAsource:
case (int)BattlefieldActorCamp.CampBsource:
case (int)BattlefieldActorCamp.CampA:
case (int)BattlefieldActorCamp.CampB:
return true;
}
return false;
}
}
public class PathNode
{
public MapHex hex;
public HexDir dir;
//public List<PathNode> childs;
public PathNode parent;
public CityRoad cr;
public int crIndex;
public bool goRight;
public PathNode()
{
//childs = new List<PathNode>();
}
}
public class CityRoad
{
public MapHex center;
public MapHex [] road;
public int Cover;
public void GetNextHex(MapHex hex, out MapHex left, out int leftIndex, out MapHex right, out int rightIndex)
{
int index = -1;
for(int i = 0; i < road.Length; i ++)
{
if(road[i].IsMe(hex))
{
index = i;
break;
}
}
if(index == -1)
{
UnityEngine.Debug.LogError($"CityRoad GetNextHex not found index, hex={hex}");
left = null;
right = null;
leftIndex = 0;
rightIndex = 0;
return;
}
leftIndex = index -1;
if(leftIndex < 0)
leftIndex = road.Length - 1;
rightIndex = index +1;
if(rightIndex >= road.Length)
rightIndex = 0;
left = road[leftIndex];
right = road[rightIndex];
//UnityEngine.Debug.Log($"GetNextHex 1 rsult, index={index}, leftIndex={leftIndex}, rightIndex={rightIndex}");
//UnityEngine.Debug.Log($"hex={hex}");
//UnityEngine.Debug.Log($"left={left}");
//UnityEngine.Debug.Log($"right={right}");
}
public void GetNextHex(int index, bool goRight, out MapHex next, out int nextIndex)
{
if(goRight)
{
index ++;
if(index >= road.Length)
index = 0;
}
else
{
index --;
if(index < 0)
index = road.Length - 1;
}
nextIndex = index;
next = road[index];
//UnityEngine.Debug.Log($"GetNextHex 2 index={index}, goRight={goRight}, nextIndex={nextIndex}");
//UnityEngine.Debug.Log($"next={next}");
}
}
public enum HexDir
{
None = 0,
RightUp,
RightDown,
LeftUp,
LeftDown,
Right,
Left,
UpRL,
DownRL,
}
public class MapArea {
public bool hasSource;
public List<MapHex> hexes;
public MapArea()
{
hexes = new List<MapHex>();
}
public void Reverse() {
for (int i = 0; i < hexes.Count; i ++) {
var h = hexes[i];
if (h.Camp == (int)BattlefieldActorCamp.CampA) {
h.Camp = (int)BattlefieldActorCamp.CampB;
} else if (h.Camp == (int)BattlefieldActorCamp.CampB) {
h.Camp = (int)BattlefieldActorCamp.CampA;
}
}
}
}
public class MapGo {
public int Camp;
public GameObject go;
}
public class MapActor {
public MapPathfind m_mp;
public MapHex m_Current;
public int m_Camp;
public float m_Speed;
bool IsMoving;
GameObject go;
List<MapHex> m_path;
int pathIndex;
public void Init(MapPathfind m, MapHex hex, int camp, float speed) {
m_mp = m;
m_Current = hex;
m_Camp = camp;
m_Speed = speed;
go = GameObject.CreatePrimitive(PrimitiveType.Capsule);
go.transform.position = new Vector3(m_Current.Wx, 0, m_Current.Wz);
go.transform.localScale = new Vector3(2, 1, 2);
m_mp.SetRoundCamp(false, hex, m_Camp, 3);
}
public void SetMove() {
m_path = m_mp.DoFind2(this);
if(m_path != null) {
pathIndex = m_path.Count-1;
IsMoving = true;
}
}
public void Update() {
if(IsMoving) {
var curPos = go.transform.position;
var target = new Vector3(m_path[pathIndex].Wx, 0, m_path[pathIndex].Wz);
var moveDis = m_Speed * Time.deltaTime;
var disCheck = Vector3.Distance(curPos, target);
if(moveDis > disCheck) {
var nextHex = m_path[pathIndex];
UnityEngine.Debug.Log($"m_Current.CityID={m_Current.CityID}, next City id={nextHex.CityID}");
if(m_Current.CityID > 0 && nextHex.CityID <= 0) { // 离开城了
UnityEngine.Debug.Log("离开城了m_Current.CityID=" +m_Current.CityID);
var cr = m_mp.GetCityRoad(m_Current.CityID);
m_mp.SetRoundCamp(true, cr.center, (int)BattlefieldActorCamp.BacNone, cr.Cover);
} else if (m_Current.CityID <= 0 && nextHex.CityID > 0) {
UnityEngine.Debug.Log("进入城了m_Current.CityID=" +m_Current.CityID);
var cr = m_mp.GetCityRoad(nextHex.CityID);
m_mp.SetRoundCamp(true, cr.center, m_Camp, cr.Cover);
}
m_Current = nextHex;
m_mp.SetRoundCamp(false, m_Current, m_Camp, 3);
go.transform.position = target;
pathIndex --;
if(pathIndex < 0) {
IsMoving = false;
}
} else {
var dir = target - curPos;
dir.Normalize();
go.transform.position = curPos + dir * moveDis;
}
}
}
}
public class MapPathfind : MonoBehaviour
{
public TerrainGridSystem TGS;
MapData m_mapData;
public bool Reload;
public MapHex [] m_hexes;
public MapGo [] m_hexCamps;
// width x轴
// height z轴
public int ANx;
public int ANz;
public bool AMove;
public int BNx;
public int BNz;
public bool BMove;
public bool FindPath;
MapHex m_Start;
MapHex m_End;
Dictionary<int, CityRoad> m_Roads;
public GameObject PathGo;
public GameObject RoundGo;
public GameObject CityGo;
public GameObject StartGo;
public GameObject EndGo;
PathNode m_EndNode;
public HashSet<int> m_CloseList;
public bool DestroyPath;
List<MapHex> BornPosA;
List<MapHex> BornPosB;
public GameObject Blue;
public GameObject BlueSource;
public GameObject BlueBuilding;
public GameObject Red;
public GameObject RedSource;
public GameObject RedBuilding;
public Transform CampRoot;
MapActor A;
MapActor B;
void Start()
{
Reload = true;
// 19,3 0,15
}
void CreateMap()
{
m_Roads = new Dictionary<int, CityRoad>();
string jsonPath = Application.dataPath + "/Editor/MapPath/MapData_MapsTest.json";
string txt = File.ReadAllText(jsonPath);
m_mapData = JsonUtility.FromJson<MapData>(txt);
UnityEngine.Debug.Log($"width={m_mapData.Width}, height={m_mapData.Height}, data length={m_mapData.BlocksData.Count}");
m_hexes = new MapHex[m_mapData.BlocksData.Count];
for(int i = 0; i < m_mapData.BlocksData.Count; i ++)
{
MapHex hex = new MapHex();
hex.SetData(m_mapData.Width, m_mapData.Height, i);
m_hexes[i] = hex;
//UnityEngine.Debug.Log(hex.ToString());
}
AddCity(1, 5, 4, 1, 3 );
//AddCity(2, 12, 21, 1 );
//AddCity(3, 4, 19, 1 );
//AddCity(4, 16, 19, 1 );
//AddCity(5, 14, 18, 1 );
//AddCity(6, 12, 17, 1 );
//AddCity(7, 4, 16, 1 );
//AddCity(8, 2, 15, 1 );
//AddCity(9, 14, 13, 1, 3 );
//AddCity(10, 6, 12, 1 );
//AddCity(11, 15, 11, 1 );
//AddCity(12, 9, 10, 1 );
//AddCity(13, 9, 6, 1, 2 );
AddCity(14, 15, 6, 2, 4 );
//AddCity(15, 16, 16, 2 );
//AddCity(16, 3, 11, 2 );
AddCity(17, 14, 24, 2, 4 );
AddCity(18, 9, 15, 3, 5 );
m_hexCamps = new MapGo[m_hexes.Length];
for(int i = 0; i < m_hexes.Length; i ++) {
m_hexCamps[i] = new MapGo();
}
BornPosA = new List<MapHex>
{
m_hexes[GetIndex(0, 0)],
m_hexes[GetIndex(1, 0)],
m_hexes[GetIndex(0, 1)]
};
BornPosB = new List<MapHex>
{
m_hexes[GetIndex(19, 29)],
m_hexes[GetIndex(18, 29)],
m_hexes[GetIndex(19, 28)]
};
}
public void AddCity(int nCityID, int Nx, int Nz, int range, int cover )
{
MapHex center = m_hexes[GetIndex(Nx, Nz)];
// 找最外一圈路径
List<MapHex> RoundRoad = new List<MapHex>();
// 获取建筑所在的格子
int MaxX = center.Ax + range;
int MinX = center.Ax - range;
int MaxY = center.Ay + range;
int MinY = center.Ay - range;
int MaxZ = center.Az + range;
int MinZ = center.Az - range;
for(int x = MinX; x <= MaxX; x ++)
{
for(int y = MinY; y <= MaxY; y ++)
{
int z = -x-y;
if(z >= MinZ && z <= MaxZ)
{
MapHex hex = GetMapHex(x, y, z);
if(x == MinX || x == MaxX
|| y == MinY || y == MaxY
|| z == MinZ || z == MaxZ)
{
RoundRoad.Add(hex);
}
else
{
hex.CityID = nCityID;
//UnityEngine.Debug.Log(hex.ToString());
var go = Instantiate(CityGo);
go.transform.SetParent(transform);
go.transform.position = new Vector3(hex.Wx, 0, hex.Wz);
}
}
}
}
int RoadNodeCount = RoundRoad.Count;
List<MapHex> rounds = new List<MapHex>();
MapHex next = RoundRoad[0];
rounds.Add(next);
RoundRoad.RemoveAt(0);
while(RoundRoad.Count > 0)
{
MapHex nextHex = null;
for(int i = 0; i < RoundRoad.Count; i ++)
{
if(next.IsMyNext(RoundRoad[i]))
{
next = RoundRoad[i];
RoundRoad.RemoveAt(i);
rounds.Add(next);
nextHex = next;
break;
}
}
if(nextHex == null)
{
UnityEngine.Debug.LogError("nextHex not found ...");
break;
}
}
for(int i = 0; i < rounds.Count; i ++)
{
UnityEngine.Debug.Log($"find next, city={nCityID}, count={rounds.Count}, current={rounds[i]}");
}
if(rounds.Count == RoadNodeCount)
{
CityRoad cr = new CityRoad();
cr.center = center;
cr.road = rounds.ToArray();
cr.Cover = cover;
m_Roads.Add(nCityID, cr);
/*
for(int i = 0; i < cr.road.Length; i ++)
{
var go = Instantiate(RoundGo);
go.transform.SetParent(transform);
go.transform.position = new Vector3(cr.road[i].Wx, 0, cr.road[i].Wz);
}
//*/
}
else
{
UnityEngine.Debug.LogError($"Road create error, city={nCityID}, rounds.Count:{rounds.Count} != RoadNodeCount:{RoadNodeCount}");
}
/*
UnityEngine.Debug.Log("Road Start ========================= count=" +rounds.Count);
for(int i = 0; i < rounds.Count; i ++)
{
UnityEngine.Debug.Log(rounds[i]);
}
UnityEngine.Debug.Log("Road End =========================");
*/
}
int GetIndex(int Nx, int Nz)
{
return Nz*m_mapData.Width+Nx;
}
void clearChecked() {
for(int i = 0; i < m_hexes.Length; i ++) {
m_hexes[i].isChecked = false;
}
}
void Update()
{
if(Reload)
{
Reload = false;
CreateMap();
InitRange(BornPosA, BornPosB);
A = new MapActor();
A.Init(this, BornPosA[0], (int)BattlefieldActorCamp.CampA, 3.0f);
B = new MapActor();
B.Init(this, BornPosB[0], (int)BattlefieldActorCamp.CampB, 3.0f);
}
// if(FindPath)
// {
// Stopwatch stopwatch = new Stopwatch();
// stopwatch.Start();
// DoFind2();
// stopwatch.Stop();
// FindPath = false;
// UnityEngine.Debug.Log($"DoFind2 执行时间: {stopwatch.ElapsedMilliseconds} 毫秒");
// }
if(DestroyPath)
{
DestroyPath = false;
//删除本节点下所有的GameObect
while (transform.childCount > 0)
{
DestroyImmediate(transform.GetChild(0).gameObject);
}
}
if(A != null) {
if(AMove) {
AMove = false;
A.SetMove();
}
A.Update();
}
if(B != null) {
if(BMove) {
BMove = false;
B.SetMove();
}
B.Update();
}
CheckRange(BornPosA[0]);
for(int i = 0; i < m_hexes.Length; i ++) {
if(m_hexCamps[i].Camp != m_hexes[i].Camp) {
if(m_hexCamps[i].go != null) {
GameObject.Destroy(m_hexCamps[i].go);
m_hexCamps[i].go = null;
}
m_hexCamps[i].Camp = m_hexes[i].Camp;
switch(m_hexCamps[i].Camp)
{
case (int)BattlefieldActorCamp.CampA:
{
m_hexCamps[i].go = GameObject.Instantiate(Blue);
}
break;
case (int)BattlefieldActorCamp.CampAsource:
{
m_hexCamps[i].go = GameObject.Instantiate(BlueSource);
}
break;
case (int)BattlefieldActorCamp.CampAbuilding:
{
m_hexCamps[i].go = GameObject.Instantiate(BlueBuilding);
}
break;
case (int)BattlefieldActorCamp.CampB:
{
m_hexCamps[i].go = GameObject.Instantiate(Red);
}
break;
case (int)BattlefieldActorCamp.CampBsource:
{
m_hexCamps[i].go = GameObject.Instantiate(RedSource);
}
break;
case (int)BattlefieldActorCamp.CampBbuilding:
{
m_hexCamps[i].go = GameObject.Instantiate(RedBuilding);
}
break;
}
if(m_hexCamps[i].go != null) {
m_hexCamps[i].go.transform.SetParent(CampRoot);
m_hexCamps[i].go.transform.position = new Vector3(m_hexes[i].Wx, 0, m_hexes[i].Wz);
}
}
}
}
HexDir GetTargetPositionDir(MapHex start, MapHex end)
{
var dir = GetLineDir(start, end);
if(dir != HexDir.None)
return dir;
if(end.Az > start.Az)
{
if(end.Ax < start.Ax && end.Ay < start.Ay)
{
return HexDir.UpRL;
}
else if(end.Ay > start.Ay)
{
return HexDir.LeftUp;
}
else
{
return HexDir.RightUp;
}
}
else
{
if(end.Ax > start.Ax && end.Ay > start.Ay)
{
return HexDir.DownRL;
}
else if(end.Ax < start.Ax)
{
return HexDir.LeftDown;
}
else
{
return HexDir.RightDown;
}
}
}
HexDir GetLineDir(MapHex start, MapHex end)
{
if(start.Ax == end.Ax)
{
if(end.Az > start.Az)
{
return HexDir.RightUp;
}
else
{
return HexDir.LeftDown;
}
}
else if( start.Az == end.Az)
{
if(end.Ax > start.Ax)
{
return HexDir.Right;
}
else
{
return HexDir.Left;
}
}
else if( start.Ay == end.Ay)
{
if(end.Az > start.Az)
{
return HexDir.LeftUp;
}
else
{
return HexDir.RightDown;
}
}
return HexDir.None;
}
void AddPathNode(PathNode node, PathNode parent)
{
node.parent = parent;
}
bool GetNextNode(PathNode currentNode, List<PathNode> openList, int startCityID, int endCityID)
{
var dir = currentNode.dir;
var nextHex = GetNextHex(currentNode.hex, dir);
if(nextHex != null)
{
// 下一格是建筑,那当前这一格,肯定就在路点上
if(!nextHex.CanPass(startCityID, endCityID))
{
// 如果当前格没有路点信息,则找左右两个路点作为下一格
if(currentNode.cr == null)
{
m_Roads.TryGetValue(nextHex.CityID, out CityRoad cr);
if(cr == null)
{
UnityEngine.Debug.LogError("City road not found, city id=" + nextHex.CityID);
return false;
}
cr.GetNextHex(currentNode.hex, out MapHex left, out int leftIndex, out MapHex right, out int rightIndex);
if(!m_CloseList.TryGetValue(left.index, out int hexIndex))
{
PathNode nodeLeft = new PathNode();
nodeLeft.hex = left;
nodeLeft.dir = GetTargetPositionDir(left, m_End);
nodeLeft.cr = cr;
nodeLeft.crIndex = leftIndex;
nodeLeft.goRight = false;
//nodeLeft.parent = currentNode;
AddPathNode(nodeLeft, currentNode);
if(m_End.IsMe(left))
{
m_EndNode = nodeLeft;
return true;
}
openList.Add(nodeLeft);
}
if(!m_CloseList.TryGetValue(right.index, out int hexIndex2))
{
PathNode nodeRight = new PathNode();
nodeRight.hex = right;
nodeRight.dir = GetTargetPositionDir(right, m_End);
nodeRight.cr = cr;
nodeRight.crIndex = rightIndex;
nodeRight.goRight = true;
//nodeRight.parent = currentNode;
AddPathNode(nodeRight, currentNode);
if(m_End.IsMe(right))
{
m_EndNode = nodeRight;
return true;
}
openList.Add(nodeRight);
}
}
else // 当前格本身就在路点上,则找下一格路点
{
currentNode.cr.GetNextHex(currentNode.crIndex, currentNode.goRight, out MapHex next, out int nextIndex);
if(!m_CloseList.TryGetValue(next.index, out int hexIndex2))
{
PathNode nodeNext = new PathNode();
nodeNext.hex = next;
nodeNext.cr = currentNode.cr;
nodeNext.dir = GetTargetPositionDir(next, m_End);
nodeNext.goRight = currentNode.goRight;
nodeNext.crIndex = nextIndex;
//nodeNext.parent = currentNode;
AddPathNode(nodeNext, currentNode);
if(m_End.IsMe(next))
{
m_EndNode = nodeNext;
return true;
}
openList.Add(nodeNext);
}
}
}
else
{
PathNode nextNode = new PathNode();
nextNode.hex = nextHex;
nextNode.dir = dir;
var dirNext = GetLineDir(nextHex, m_End);
if(dirNext != HexDir.None)
{
nextNode.dir = dirNext;
}
nextNode.parent = currentNode;
AddPathNode(nextNode, currentNode);
if(m_End.IsMe(nextHex))
{
m_EndNode = nextNode;
return true;
}
openList.Add(nextNode);
}
}
return false;
}
public List<MapHex> DoFind2(MapActor actor)
{
m_EndNode = null;
m_CloseList = new HashSet<int>();
m_Start = actor.m_Current;
var StartCityID = m_Start.CityID;
if(actor.m_Camp == (int)BattlefieldActorCamp.CampA) {
if(m_Start.Nx == ANx && m_Start.Nz == ANz) {
return null;
}
m_End = m_hexes[GetIndex(ANx, ANz)];
} else {
if(m_Start.Nx == BNx && m_Start.Nz == BNz) {
return null;
}
m_End = m_hexes[GetIndex(BNx, BNz)];
}
//
var EndCityID = m_End.CityID;
StartGo.transform.position = new Vector3(m_Start.Wx, 0, m_Start.Wz);
EndGo.transform.position = new Vector3(m_End.Wx, 0, m_End.Wz);
List<PathNode> openList = new List<PathNode>();
PathNode path = new PathNode();
path.hex = m_Start;
path.dir = GetTargetPositionDir(m_Start, m_End);
openList.Add(path);
List<MapHex> hexList = new List<MapHex>();
while(openList.Count > 0)
{
//UnityEngine.Debug.Log("START ============================================== openList.Count=" + openList.Count);
List<PathNode> newOpenList = new List<PathNode>();
for(int i = 0; i < openList.Count; i ++)
{
hexList.Clear();
var node = openList[i];
m_CloseList.Add(node.hex.index);
//UnityEngine.Debug.Log($"node.dir={node.dir}, node={node.hex}");
switch(node.dir)
{
case HexDir.DownRL:
{
node.dir = HexDir.LeftDown;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("LeftDown go end");
goto End;
}
node.dir = HexDir.RightDown;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("RightDown go end");
goto End;
}
}
break;
case HexDir.UpRL:
{
node.dir = HexDir.LeftUp;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("LeftUp go end");
goto End;
}
node.dir = HexDir.RightUp;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("RightUp go end");
goto End;
}
}
break;
//*
case HexDir.LeftUp:
{
node.dir = HexDir.Left;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("LeftUp HexDir.Left go end");
goto End;
}
node.dir = HexDir.LeftUp;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("HexDir.LeftUp go end");
goto End;
}
}
break;
case HexDir.LeftDown:
{
node.dir = HexDir.Left;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("LeftDown HexDir.Left go end");
goto End;
}
node.dir = HexDir.LeftDown;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("HexDir.LeftDown go end");
goto End;
}
}
break;
case HexDir.RightUp:
{
node.dir = HexDir.Right;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("RightUp HexDir.Right go end");
goto End;
}
node.dir = HexDir.RightUp;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("HexDir.RightUp go end");
goto End;
}
}
break;
case HexDir.RightDown:
{
node.dir = HexDir.Right;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("RightDown HexDir.Right go end");
goto End;
}
node.dir = HexDir.RightDown;
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("HexDir.RightDown go end");
goto End;
}
}
break;
//*/
default:
{
if(GetNextNode(node, newOpenList, StartCityID, EndCityID))
{
UnityEngine.Debug.Log("default go end");
goto End;
}
}
break;
}
}
openList.Clear();
openList.AddRange(newOpenList);
//UnityEngine.Debug.Log("NEXT ============================================== openList.Count=" + openList.Count);
}
End:
/*
PathNode pathNode2 = m_EndNode;
while(pathNode2.parent != null)
{
PathNode check = pathNode2.parent;
while(check.parent != null)
{
var dir = GetLineDir(pathNode2.hex, check.hex);
if(dir != HexDir.None)
{
List<MapHex> list = new List<MapHex>();
MapHex hex = pathNode2.hex;
while(true)
{
MapHex nextHex = GetNextHex(hex, dir);
if(nextHex.CityID <= 0)
{
if(nextHex.IsMe(check.hex))
{
break;
}
list.Add(nextHex);
hex = nextHex;
}
else
{
list.Clear();
break;
}
}
if(list.Count > 0)
{
PathNode newAdd = pathNode2;
while(list.Count > 0)
{
PathNode newNext = new PathNode();
newNext.hex = list[0];
newAdd.parent = newNext;
newAdd = newNext;
list.RemoveAt(0);
}
newAdd.parent = check;
}
}
check = check.parent;
}
pathNode2 = pathNode2.parent;
}
//*/
List<MapHex> result = new List<MapHex>();
int nCount = 0;
PathNode pathNode = m_EndNode;
while(pathNode.parent != null)
{
UnityEngine.Debug.Log(pathNode.hex);
result.Add(pathNode.hex);
//var go = Instantiate(PathGo);
//go.transform.SetParent(transform);
//go.transform.position = new Vector3(pathNode.hex.Wx, 0, pathNode.hex.Wz);
nCount ++;
pathNode = pathNode.parent;
}
UnityEngine.Debug.Log("all path node count="+ nCount);
return result;
}
MapHex GetMapHex(int Ax, int Ay, int Az)
{
int Nz = Az;
int Nx = Ax+Az/2;
//UnityEngine.Debug.Log($"GetMapHex Ax={Ax}, Ay={Ay}, Az={Az}, Nx={Nx}, Nz={Nz}");
if(Nx < 0 || Nx > m_mapData.Width-1)
{
//UnityEngine.Debug.LogError($"GetMapHex 1 not found Nx={Nx}, Nz={Nz}");
return null;
}
if(Nz < 0 || Nz > m_mapData.Height-1)
{
//UnityEngine.Debug.LogError($"GetMapHex 2 not found Nx={Nx}, Nz={Nz}");
return null;
}
int index = GetIndex(Nx, Nz);
return m_hexes[index];
}
public CityRoad GetCityRoad(int cityID) {
if(m_Roads.TryGetValue(cityID, out CityRoad v)) {
return v;
}
return null;
}
/*
*/
MapHex GetNextHex(MapHex hex, HexDir dir)
{
switch(dir)
{
case HexDir.RightUp:
{
//往右上走Ax不变Az+1
int NextAx = hex.Ax;
int NextAz = hex.Az+1;
int NextAy = -NextAx-NextAz;
return GetMapHex(NextAx, NextAy, NextAz);
}
case HexDir.RightDown:
{
// 往右下走Ay不变Az-1
int NextAz = hex.Az-1;
int NextAy = hex.Ay;
int NextAx = -NextAz-NextAy;
return GetMapHex(NextAx, NextAy, NextAz);
}
case HexDir.LeftUp:
{
//往左上走Ay不变Az+1
int NextAy = hex.Ay;
int NextAz = hex.Az+1;
int NextAx = -NextAz-NextAy;
return GetMapHex(NextAx, NextAy, NextAz);
}
case HexDir.LeftDown:
{
//往左下走Ax不变Az-1
int NextAx = hex.Ax;
int NextAz = hex.Az-1;
int NextAy = -NextAx-NextAz;
return GetMapHex(NextAx, NextAy, NextAz);
}
case HexDir.Right:
{
//往右走Az不变Ay-1
int NextAz = hex.Az;
int NextAy = hex.Ay-1;
int NextAx = -NextAz-NextAy;
return GetMapHex(NextAx, NextAy, NextAz);
}
case HexDir.Left:
{
//往左走Az不变Ay+1
int NextAz = hex.Az;
int NextAy = hex.Ay+1;
int NextAx = -NextAz-NextAy;
return GetMapHex(NextAx, NextAy, NextAz);
}
default:
UnityEngine.Debug.LogError("GetNextHex invalid dir, dir=" + dir);
return null;
}
}
// 获取指定阵营的空格子
List<MapHex> GetRoundEmptyHex(MapHex center) {
List<MapHex> result = new List<MapHex>();
int MaxX = center.Ax + 1;
int MinX = center.Ax - 1;
int MaxY = center.Ay + 1;
int MinY = center.Ay - 1;
int MaxZ = center.Az + 1;
int MinZ = center.Az - 1;
;
for (int x = MinX; x <= MaxX; x++) {
for (int y = MinY; y <= MaxY; y++) {
int z = -x - y;
if (z >= MinZ && z <= MaxZ) {
var hex = GetMapHex(x, y, z);
if (hex != null && hex != center && hex.CityID == 0 && !hex.isChecked) {
hex.isChecked = true;
result.Add(hex);
}
}
}
}
return result;
}
public void SetRoundCamp(bool isBuilding, MapHex center, int camp , int length ) {
length--;
int MaxX = center.Ax + length;
int MinX = center.Ax - length;
int MaxY = center.Ay + length;
int MinY = center.Ay - length;
int MaxZ = center.Az + length;
int MinZ = center.Az - length;
for (int x = MinX; x <= MaxX; x++ ) {
for (int y = MinY; y <= MaxY; y++) {
int z = -x - y;
if (z >= MinZ && z <= MaxZ) {
var hex = GetMapHex(x, y, z);
if (hex != null) {
if (isBuilding) {
if(camp == (int)BattlefieldActorCamp.CampA) {
hex.Camp = (int)BattlefieldActorCamp.CampAbuilding;
} else if(camp == (int)BattlefieldActorCamp.CampB) {
hex.Camp = (int)BattlefieldActorCamp.CampBbuilding;
} else if (camp == (int)BattlefieldActorCamp.BacNone) {
if(hex.CityID <= 0) {
hex.Camp = hex.StaticCamp;
} else {
hex.Camp = camp;
}
} else {
hex.Camp = camp;
}
} else {
if (hex.CityID == 0 && hex.Camp < (int)BattlefieldActorCamp.CampMax) { // 如果不是设置建筑范围,则周围有建筑范围,不能更新
hex.Camp = camp;
}
}
}
}
}
}
}
// 获取周围相同阵营,并且没有检查过的格子
List<MapHex> GetRoundUnchecked(MapHex center) {
List<MapHex> result = new List<MapHex>();
int MaxX = center.Ax + 1;
int MinX = center.Ax - 1;
int MaxY = center.Ay + 1;
int MinY = center.Ay - 1;
int MaxZ = center.Az + 1;
int MinZ = center.Az - 1;
for (int x = MinX; x <= MaxX; x++) {
for (int y = MinY; y <= MaxY; y++) {
int z = -x - y;
if (z >= MinZ && z <= MaxZ) {
var hex = GetMapHex(x, y, z);
if( hex != null && !hex.isChecked && hex.CityID == 0 && hex.GetRealCamp() == center.GetRealCamp() ){
hex.isChecked = true;
result.Add(hex);
}
}
}
}
return result;
}
// 获取任意一个未检查过的格子
MapHex GetNextUnchecked() {
for(int i = 0; i < m_hexes.Length; i ++) {
var h = m_hexes[i];
if (!h.isChecked && h.CityID == 0 && h.IsRealCamp() ) {
h.isChecked = true;
return h;
}
}
return null;
}
void CheckRange(MapHex start) {
clearChecked();
List<MapArea> areas = new List<MapArea>();
var nextHex = start;
while(nextHex != null) {
var area = new MapArea();
areas.Add(area);
int checkIndex = 0;
List<MapHex> checkList = new List<MapHex>();
checkList.Add(nextHex);
while(checkIndex < checkList.Count) {
var current = checkList[checkIndex];
current.isChecked = true;
checkIndex++;
area.hexes.Add(current);
if (current.IsCampSource()) {
area.hasSource = true;
}
var result = GetRoundUnchecked(current);
if (result.Count > 0 ){
checkList.AddRange(result);
}
}
nextHex = GetNextUnchecked();
}
for (int i = 0; i < areas.Count; i ++) {
if (!areas[i].hasSource ){
areas[i].Reverse();
}
}
}
// 采用膨胀算法初始化势力范围
void InitRange( List<MapHex> BornPosA, List<MapHex> BornPosB) {
clearChecked();
int checkIndexA = 0;
List<MapHex> checkListA = new List<MapHex>();
checkListA.AddRange(BornPosA);
for (int i = 0; i < checkListA.Count; i ++) {
checkListA[i].isChecked = true;
checkListA[i].Camp = (int)BattlefieldActorCamp.CampAsource;
}
int checkIndexB = 0;
List<MapHex> checkListB = new List<MapHex>();
checkListB.AddRange(BornPosB);
for (int i = 0; i < checkListB.Count; i ++) {
checkListB[i].isChecked = true;
checkListB[i].Camp = (int)BattlefieldActorCamp.CampBsource;
}
bool working = true;
while(working) {
working = false;
if (checkIndexA < checkListA.Count) {
var current = checkListA[checkIndexA];
current.isChecked = true;
if (current.Camp == (int)BattlefieldActorCamp.BacNone) {
current.Camp = (int)BattlefieldActorCamp.CampA; // 设置格子所属势力
current.StaticCamp = (int)BattlefieldActorCamp.CampA;
}
var result = GetRoundEmptyHex(current); // 只获取周围没有阵营的空格子
if (result.Count > 0) {
checkListA.AddRange(result);
}
checkIndexA++;
if (checkIndexA < checkListA.Count) {
working = true;
}
}
if (checkIndexB < checkListB.Count) {
var current = checkListB[checkIndexB];
current.isChecked = true;
if (current.Camp == (int)BattlefieldActorCamp.BacNone) {
current.Camp = (int)BattlefieldActorCamp.CampB; // 设置格子所属势力
current.StaticCamp = (int)BattlefieldActorCamp.CampB;
}
var result = GetRoundEmptyHex(current); // 只获取周围没有阵营的空格子
if (result.Count > 0) {
checkListB.AddRange(result);
}
checkIndexB++;
if (checkIndexB < checkListB.Count) {
working = true;
}
}
}
}
}