-
- using System.Collections.Generic;
- using System.Linq;
- using Godot;
-
- /// <summary>
- /// 地牢地砖管理类, 提供一些操作 TileMap 和计算导航的接口
- /// </summary>
- public class DungeonTileMap
- {
- //--------------------- 导航 -------------------------
-
- //已经标记过的点
- private readonly HashSet<Vector2I> _usePoints = new HashSet<Vector2I>();
-
- //导航区域数据
- private readonly List<NavigationPolygonData> _polygonDataList = new List<NavigationPolygonData>();
-
- //连接门的导航区域
- private readonly List<DoorNavigationInfo> _connectNavigationItemList = new List<DoorNavigationInfo>();
-
- //----------------------------------------------------
-
- private TileMap _tileRoot;
- //地面地砖在 Atlas 的位置
- private List<Vector2I> _floorAtlasCoords;
- //生成导航的结果
- private GenerateNavigationResult _generateNavigationResult;
-
- public DungeonTileMap(TileMap tileRoot)
- {
- _tileRoot = tileRoot;
- }
-
- /// <summary>
- /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的地图数据
- /// </summary>
- public void AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, SeedRandom random)
- {
- _connectNavigationItemList.Clear();
- _AutoFillRoomTile(config, startRoomInfo, random);
- }
-
- private void _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, SeedRandom random)
- {
- foreach (var info in roomInfo.Next)
- {
- _AutoFillRoomTile(config, info, random);
- }
-
- //铺房间
- if (roomInfo.RoomSplit == null)
- {
- FillRect(GameConfig.FloorMapLayer, config.Floor, roomInfo.Position + Vector2.One,
- roomInfo.Size - new Vector2(2, 2));
-
- FillRect(GameConfig.TopMapLayer, config.IN_LT, roomInfo.Position, Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.L, roomInfo.Position + new Vector2(0, 1),
- new Vector2(1, roomInfo.Size.Y - 2));
- FillRect(GameConfig.TopMapLayer, config.IN_LB, roomInfo.Position + new Vector2(0, roomInfo.Size.Y - 1),
- new Vector2(1, 1));
- FillRect(GameConfig.TopMapLayer, config.B, roomInfo.Position + new Vector2(1, roomInfo.Size.Y - 1),
- new Vector2(roomInfo.Size.X - 2, 1));
- FillRect(GameConfig.TopMapLayer, config.IN_RB,
- roomInfo.Position + new Vector2(roomInfo.Size.X - 1, roomInfo.Size.Y - 1),
- Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.R, roomInfo.Position + new Vector2(roomInfo.Size.X - 1, 1),
- new Vector2(1, roomInfo.Size.Y - 2));
- FillRect(GameConfig.TopMapLayer, config.IN_RT, roomInfo.Position + new Vector2(roomInfo.Size.X - 1, 0),
- Vector2.One);
- FillRect(GameConfig.MiddleMapLayer, config.T, roomInfo.Position + Vector2.Right,
- new Vector2(roomInfo.Size.X - 2, 1));
- }
- else
- {
- //var rectSize = roomInfo.RoomSplit.RoomInfo.Size;
- var rectPos = roomInfo.RoomSplit.RoomInfo.Position.AsVector2I();
- //var offset = roomInfo.GetOffsetPosition() / GameConfig.TileCellSizeVector2I;
-
- //填充tile操作
- var tileInfo = roomInfo.RoomSplit.TileInfo;
- for (var i = 0; i < tileInfo.Floor.Count; i += 5)
- {
- var posX = tileInfo.Floor[i];
- var posY = tileInfo.Floor[i + 1];
- var sourceId = tileInfo.Floor[i + 2];
- var atlasCoordsX = tileInfo.Floor[i + 3];
- var atlasCoordsY = tileInfo.Floor[i + 4];
- var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
- _tileRoot.SetCell(GameConfig.FloorMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY));
- }
- for (var i = 0; i < tileInfo.Middle.Count; i += 5)
- {
- var posX = tileInfo.Middle[i];
- var posY = tileInfo.Middle[i + 1];
- var sourceId = tileInfo.Middle[i + 2];
- var atlasCoordsX = tileInfo.Middle[i + 3];
- var atlasCoordsY = tileInfo.Middle[i + 4];
- var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
- _tileRoot.SetCell(GameConfig.MiddleMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY));
- }
- for (var i = 0; i < tileInfo.Top.Count; i += 5)
- {
- var posX = tileInfo.Top[i];
- var posY = tileInfo.Top[i + 1];
- var sourceId = tileInfo.Top[i + 2];
- var atlasCoordsX = tileInfo.Top[i + 3];
- var atlasCoordsY = tileInfo.Top[i + 4];
- var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
- _tileRoot.SetCell(GameConfig.TopMapLayer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY));
- }
- //随机选择预设
- RoomPreinstallInfo preinstallInfo;
- if (EditorPlayManager.IsPlay && roomInfo.RoomType == GameApplication.Instance.DungeonManager.CurrConfig.DesignatedType) //编辑器模式, 指定预设
- {
- preinstallInfo = EditorManager.SelectPreinstall;
- }
- else //普通模式
- {
- if (roomInfo.RoomSplit.Preinstall.Count == 1)
- {
- preinstallInfo = roomInfo.RoomSplit.Preinstall[0];
- }
- else
- {
- var weights = roomInfo.RoomSplit.Preinstall.Select(info => info.Weight).ToArray();
- var index = random.RandomWeight(weights);
- preinstallInfo = roomInfo.RoomSplit.Preinstall[index];
- }
- }
-
-
- var roomPreinstall = new RoomPreinstall(roomInfo, preinstallInfo);
- roomInfo.RoomPreinstall = roomPreinstall;
- //执行预处理操作
- roomPreinstall.Pretreatment(random);
-
- //初始化标记
- //roomInfo.RoomSplit.Preinstall.
-
- //roomInfo.RoomSplit.TileInfo.
- // var template = ResourceManager.Load<PackedScene>(roomInfo.RoomSplit.ScenePath);
- // var tileInstance = template.Instantiate<DungeonRoomTemplate>();
- //
- // //其它物体
- // var childCount = tileInstance.GetChildCount();
- // for (var i = 0; i < childCount; i++)
- // {
- // var item = tileInstance.GetChild(i);
- // if (!(item is ActivityMark))
- // {
- // item.GetParent().RemoveChild(item);
- // item.Owner = null;
- // _tileRoot.AddChild(item);
- // if (item is Node2D node)
- // {
- // node.Position = roomInfo.GetWorldPosition() + (node.GlobalPosition - offset);
- // }
- //
- // i--;
- // childCount--;
- // }
- // }
- //
- // //物体标记
- // var activityMarks = tileInstance.GetMarks();
- // foreach (var activityMark in activityMarks)
- // {
- // var pos = activityMark.Position;
- // activityMark.GetParent().RemoveChild(activityMark);
- // activityMark.Owner = null;
- // //_tileRoot.AddChild(activityMark);
- // activityMark.Position = roomInfo.GetWorldPosition() + (pos - offset);
- // activityMark.TileRoot = _tileRoot;
- // //执行预处理操作
- // activityMark.Pretreatment(random);
- // }
- // roomInfo.ActivityMarks.AddRange(activityMarks);
- //
- // //填充tile操作
- // for (int i = 0; i < rectSize.X; i++)
- // {
- // for (int j = 0; j < rectSize.Y; j++)
- // {
- // var coords = new Vector2I((int)(rectPos.X + i), (int)(rectPos.Y + j));
- // var atlasCoords = tileInstance.GetCellAtlasCoords(0, coords);
- // if (atlasCoords.X != -1 && atlasCoords.Y != -1)
- // {
- // // 在 Godot 4.0 中使用以下这段代码区分层级, 会导致游戏关闭时有概率报错卡死, 目前尚不清楚原因
- // //获取自定义层级
- // // var customData = tileInstance.GetCellTileData(0, coords).GetCustomData(CustomTileLayerName);
- // // var layer = customData.AsInt32();
- // // layer = Mathf.Clamp(layer, GameConfig.FloorMapLayer, GameConfig.TopMapLayer);
- //
- // var layer = config.GetLayer(atlasCoords);
- // _tileRoot.SetCell(layer, new Vector2I(roomInfo.Position.X + i, roomInfo.Position.Y + j),
- // 0, atlasCoords);
- // }
- // }
- // }
- //
- // tileInstance.CallDeferred(Node.MethodName.QueueFree);
- }
-
- //铺过道
- foreach (var doorInfo in roomInfo.Doors)
- {
- if (doorInfo.ConnectRoom.Id > roomInfo.Id)
- {
- //普通的直线连接
- var doorDir1 = doorInfo.Direction;
- var doorDir2 = doorInfo.ConnectDoor.Direction;
- if (!doorInfo.HasCross)
- {
- var rect = Utils.CalcRect(
- doorInfo.OriginPosition.X,
- doorInfo.OriginPosition.Y,
- doorInfo.ConnectDoor.OriginPosition.X,
- doorInfo.ConnectDoor.OriginPosition.Y
- );
-
- switch (doorDir1)
- {
- case DoorDirection.E:
- rect.Size = new Vector2(rect.Size.X, GameConfig.CorridorWidth);
- FullHorizontalAisle(config, rect);
- FullHorizontalAisleLeft(config, rect, doorInfo);
- FullHorizontalAisleRight(config, rect, doorInfo.ConnectDoor);
- break;
- case DoorDirection.W:
- rect.Size = new Vector2(rect.Size.X, GameConfig.CorridorWidth);
- FullHorizontalAisle(config, rect);
- FullHorizontalAisleLeft(config, rect, doorInfo.ConnectDoor);
- FullHorizontalAisleRight(config, rect, doorInfo);
- break;
-
- case DoorDirection.S:
- rect.Size = new Vector2(GameConfig.CorridorWidth, rect.Size.Y);
- FullVerticalAisle(config, rect);
- FullVerticalAisleUp(config, rect, doorInfo);
- FullVerticalAisleDown(config, rect, doorInfo.ConnectDoor);
- break;
- case DoorDirection.N:
- rect.Size = new Vector2(GameConfig.CorridorWidth, rect.Size.Y);
- FullVerticalAisle(config, rect);
- FullVerticalAisleUp(config, rect, doorInfo.ConnectDoor);
- FullVerticalAisleDown(config, rect, doorInfo);
- break;
- }
- }
- else //带交叉点
- {
- //方向, 0横向, 1纵向
- var dir1 = 0;
- var dir2 = 0;
-
- Rect2 rect;
- Rect2 rect2;
-
- //计算范围
- switch (doorDir1)
- {
- case DoorDirection.E: //→
- rect = new Rect2(
- doorInfo.OriginPosition.X,
- doorInfo.OriginPosition.Y,
- doorInfo.Cross.X - doorInfo.OriginPosition.X,
- GameConfig.CorridorWidth
- );
- break;
- case DoorDirection.W: //←
- rect = new Rect2(
- doorInfo.Cross.X + GameConfig.CorridorWidth,
- doorInfo.Cross.Y,
- doorInfo.OriginPosition.X - (doorInfo.Cross.X + GameConfig.CorridorWidth),
- GameConfig.CorridorWidth
- );
- break;
- case DoorDirection.S: //↓
- dir1 = 1;
- rect = new Rect2(
- doorInfo.OriginPosition.X,
- doorInfo.OriginPosition.Y,
- GameConfig.CorridorWidth,
- doorInfo.Cross.Y - doorInfo.OriginPosition.Y
- );
- break;
- case DoorDirection.N: //↑
- dir1 = 1;
- rect = new Rect2(
- doorInfo.Cross.X,
- doorInfo.Cross.Y + GameConfig.CorridorWidth,
- GameConfig.CorridorWidth,
- doorInfo.OriginPosition.Y - (doorInfo.Cross.Y + GameConfig.CorridorWidth)
- );
- break;
- default:
- rect = new Rect2();
- break;
- }
-
- switch (doorDir2)
- {
- case DoorDirection.E: //→
- rect2 = new Rect2(
- doorInfo.ConnectDoor.OriginPosition.X,
- doorInfo.ConnectDoor.OriginPosition.Y,
- doorInfo.Cross.X - doorInfo.ConnectDoor.OriginPosition.X,
- GameConfig.CorridorWidth
- );
- break;
- case DoorDirection.W: //←
- rect2 = new Rect2(
- doorInfo.Cross.X + GameConfig.CorridorWidth,
- doorInfo.Cross.Y,
- doorInfo.ConnectDoor.OriginPosition.X -
- (doorInfo.Cross.X + GameConfig.CorridorWidth),
- GameConfig.CorridorWidth
- );
- break;
- case DoorDirection.S: //↓
- dir2 = 1;
- rect2 = new Rect2(
- doorInfo.ConnectDoor.OriginPosition.X,
- doorInfo.ConnectDoor.OriginPosition.Y,
- GameConfig.CorridorWidth,
- doorInfo.Cross.Y - doorInfo.ConnectDoor.OriginPosition.Y
- );
- break;
- case DoorDirection.N: //↑
- dir2 = 1;
- rect2 = new Rect2(
- doorInfo.Cross.X,
- doorInfo.Cross.Y + GameConfig.CorridorWidth,
- GameConfig.CorridorWidth,
- doorInfo.ConnectDoor.OriginPosition.Y -
- (doorInfo.Cross.Y + GameConfig.CorridorWidth)
- );
- break;
- default:
- rect2 = new Rect2();
- break;
- }
-
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, doorInfo.Cross + Vector2.One,
- new Vector2(GameConfig.CorridorWidth - 2, GameConfig.CorridorWidth - 2));
-
- //墙壁, 0横向, 1纵向
- if (dir1 == 0)
- {
- FullHorizontalAisle(config, rect);
- FullHorizontalAisleLeft(config, rect, doorDir1 == DoorDirection.E ? doorInfo : null);
- FullHorizontalAisleRight(config, rect, doorDir1 == DoorDirection.W ? doorInfo : null);
- }
- else
- {
- FullVerticalAisle(config, rect);
- FullVerticalAisleUp(config, rect, doorDir1 == DoorDirection.S ? doorInfo : null);
- FullVerticalAisleDown(config, rect, doorDir1 == DoorDirection.N ? doorInfo : null);
- }
-
- if (dir2 == 0)
- {
- FullHorizontalAisle(config, rect2);
- FullHorizontalAisleLeft(config, rect2, doorDir2 == DoorDirection.E ? doorInfo.ConnectDoor : null);
- FullHorizontalAisleRight(config, rect2, doorDir2 == DoorDirection.W ? doorInfo.ConnectDoor : null);
- }
- else
- {
- FullVerticalAisle(config, rect2);
- FullVerticalAisleUp(config, rect2, doorDir2 == DoorDirection.S ? doorInfo.ConnectDoor : null);
- FullVerticalAisleDown(config, rect2, doorDir2 == DoorDirection.N ? doorInfo.ConnectDoor : null);
- }
-
- if ((doorDir1 == DoorDirection.N && doorDir2 == DoorDirection.E) || //↑→
- (doorDir2 == DoorDirection.N && doorDir1 == DoorDirection.E))
- {
- FillRect(GameConfig.TopMapLayer, config.OUT_RT,
- doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1),
- Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.IN_RT, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0),
- Vector2.One);
- FillRect(GameConfig.MiddleMapLayer, config.T, doorInfo.Cross, new Vector2(GameConfig.CorridorWidth - 1, 1));
- FillRect(GameConfig.TopMapLayer, config.R, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 1),
- new Vector2(1, GameConfig.CorridorWidth - 1));
- }
- else if ((doorDir1 == DoorDirection.E && doorDir2 == DoorDirection.S) || //→↓
- (doorDir2 == DoorDirection.E && doorDir1 == DoorDirection.S))
- {
- FillRect(GameConfig.MiddleMapLayer, config.OUT_RB, doorInfo.Cross, Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.IN_RB,
- doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1,
- GameConfig.CorridorWidth - 1),
- Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.R, doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0),
- new Vector2(1, GameConfig.CorridorWidth - 1));
- FillRect(GameConfig.TopMapLayer, config.B, doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1),
- new Vector2(GameConfig.CorridorWidth - 1, 1));
- }
- else if ((doorDir1 == DoorDirection.S && doorDir2 == DoorDirection.W) || //↓←
- (doorDir2 == DoorDirection.S && doorDir1 == DoorDirection.W))
- {
- FillRect(GameConfig.MiddleMapLayer, config.OUT_LB,
- doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1, 0), Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.IN_LB, doorInfo.Cross + new Vector2(0, GameConfig.CorridorWidth - 1),
- Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.L, doorInfo.Cross, new Vector2(1, GameConfig.CorridorWidth - 1));
- FillRect(GameConfig.TopMapLayer, config.B, doorInfo.Cross + new Vector2(1, GameConfig.CorridorWidth - 1),
- new Vector2(GameConfig.CorridorWidth - 1, 1));
- }
- else if ((doorDir1 == DoorDirection.W && doorDir2 == DoorDirection.N) || //←↑
- (doorDir2 == DoorDirection.W && doorDir1 == DoorDirection.N))
- {
- FillRect(GameConfig.TopMapLayer, config.OUT_LT,
- doorInfo.Cross + new Vector2(GameConfig.CorridorWidth - 1,
- GameConfig.CorridorWidth - 1),
- Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.IN_LT, doorInfo.Cross, Vector2.One);
- FillRect(GameConfig.MiddleMapLayer, config.T, doorInfo.Cross + new Vector2(1, 0),
- new Vector2(GameConfig.CorridorWidth - 1, 1));
- FillRect(GameConfig.TopMapLayer, config.L, doorInfo.Cross + new Vector2(0, 1),
- new Vector2(1, GameConfig.CorridorWidth - 1));
- }
-
- //在房间墙上开洞
- switch (doorDir1)
- {
- case DoorDirection.E: //→
- ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(-1, 1),
- new Vector2(1, rect.Size.Y - 2));
- break;
- case DoorDirection.W: //←
- ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(0, 1),
- new Vector2(1, rect.Size.Y - 2));
- break;
- case DoorDirection.S: //↓
- ClearRect(GameConfig.TopMapLayer, doorInfo.OriginPosition + new Vector2(1, -1),
- new Vector2(rect.Size.X - 2, 1));
- break;
- case DoorDirection.N: //↑
- ClearRect(GameConfig.MiddleMapLayer, doorInfo.OriginPosition + new Vector2(1, 2),
- new Vector2(rect.Size.X - 2, 1));
- break;
- }
-
- switch (doorDir2)
- {
- case DoorDirection.E: //→
- ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(-1, 1),
- new Vector2(1, rect2.Size.Y - 2));
- break;
- case DoorDirection.W: //←
- ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(0, 1),
- new Vector2(1, rect2.Size.Y - 2));
- break;
- case DoorDirection.S: //↓
- ClearRect(GameConfig.TopMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, -1),
- new Vector2(rect2.Size.X - 2, 1));
- break;
- case DoorDirection.N: //↑
- ClearRect(GameConfig.MiddleMapLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, 0),
- new Vector2(rect2.Size.X - 2, 1));
- break;
- }
- }
- }
- }
- }
-
- //填充tile区域
- private void FillRect(int layer, TileCellInfo info, Vector2 pos, Vector2 size)
- {
- for (int i = 0; i < size.X; i++)
- {
- for (int j = 0; j < size.Y; j++)
- {
- _tileRoot.SetCell(layer, new Vector2I((int)pos.X + i, (int)pos.Y + j), 0, info.AutoTileCoord);
- }
- }
- }
-
- //清除tile区域
- private void ClearRect(int layer, Vector2 pos, Vector2 size)
- {
- for (int i = 0; i < size.X; i++)
- {
- for (int j = 0; j < size.Y; j++)
- {
- _tileRoot.SetCell(layer, new Vector2I((int)pos.X + i, (int)pos.Y + j), 0);
- }
- }
- }
-
- //横向过道
- private void FullHorizontalAisle(AutoTileConfig config, Rect2 rect)
- {
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, rect.Position + new Vector2(0, 1), rect.Size - new Vector2(0, 2));
- FillRect(GameConfig.MiddleMapLayer, config.T, rect.Position, new Vector2(rect.Size.X, 1));
- FillRect(GameConfig.TopMapLayer, config.B, rect.Position + new Vector2(0, rect.Size.Y - 1), new Vector2(rect.Size.X, 1));
- }
-
- //纵向过道
- private void FullVerticalAisle(AutoTileConfig config, Rect2 rect)
- {
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, rect.Position + new Vector2(1, 0), rect.Size - new Vector2(2, 0));
- FillRect(GameConfig.TopMapLayer, config.L, rect.Position, new Vector2(1, rect.Size.Y));
- FillRect(GameConfig.TopMapLayer, config.R, rect.Position + new Vector2(rect.Size.X - 1, 0), new Vector2(1, rect.Size.Y));
- }
-
- //横向过道, 门朝右, 连接方向向左
- private void FullHorizontalAisleLeft(AutoTileConfig config, Rect2 rect, RoomDoorInfo doorInfo = null)
- {
- //左
- ClearRect(GameConfig.TopMapLayer, rect.Position + new Vector2(-1, 1), new Vector2(1, rect.Size.Y - 2));
- if (doorInfo == null)
- {
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, rect.Position + new Vector2(-1, 1),
- new Vector2(1, rect.Size.Y - 2));
- }
- else
- {
- ClearRect(GameConfig.TopMapLayer, rect.Position + new Vector2(-1, 0), Vector2.One);
- FillRect(GameConfig.MiddleMapLayer, config.OUT_LB, rect.Position + new Vector2(-1, 0), Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.OUT_LT, rect.Position + new Vector2(-1, 3), Vector2.One);
-
- FillRect(GameConfig.FloorMapLayer, config.Floor, rect.Position + new Vector2(-1, 1), new Vector2(1, rect.Size.Y - 2));
- //生成门的导航区域
- var x = rect.Position.X * GameConfig.TileCellSize;
- var y = rect.Position.Y * GameConfig.TileCellSize;
-
- var op1 = new Vector2(x - GameConfig.TileCellSize * 1.5f, y + GameConfig.TileCellSize * 1.5f);
- var op2 = new Vector2(x + GameConfig.TileCellSize * 0.5f, y + GameConfig.TileCellSize * 1.5f);
- var op3 = new Vector2(x + GameConfig.TileCellSize * 0.5f, y + GameConfig.TileCellSize * 3f);
- var op4 = new Vector2(x - GameConfig.TileCellSize * 1.5f, y + GameConfig.TileCellSize * 3f);
- AddDoorNavigation(
- doorInfo, op1, op2, op3, op4,
- op1,
- new Vector2(op1.X + GameConfig.TileCellSize, op2.Y),
- new Vector2(op1.X + GameConfig.TileCellSize, op3.Y),
- op4
- );
- }
- }
-
- //横向过道, 门朝左, 连接方向向右
- private void FullHorizontalAisleRight(AutoTileConfig config, Rect2 rect, RoomDoorInfo doorInfo = null)
- {
- //右
- ClearRect(GameConfig.TopMapLayer, rect.Position + new Vector2(rect.Size.X, 1), new Vector2(1, rect.Size.Y - 2));
- if (doorInfo == null)
- {
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, rect.Position + new Vector2(rect.Size.X, 1), new Vector2(1, rect.Size.Y - 2));
- }
- else
- {
- ClearRect(GameConfig.TopMapLayer, rect.Position + new Vector2(rect.Size.X, 0), Vector2.One);
- FillRect(GameConfig.MiddleMapLayer, config.OUT_RB, rect.Position + new Vector2(rect.Size.X, 0), Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.OUT_RT, rect.Position + new Vector2(rect.Size.X, 3), Vector2.One);
-
- FillRect(GameConfig.FloorMapLayer, config.Floor, rect.Position + new Vector2(rect.Size.X, 1), new Vector2(1, rect.Size.Y - 2));
- //生成门的导航区域
- var x = rect.Position.X * GameConfig.TileCellSize;
- var y = rect.Position.Y * GameConfig.TileCellSize;
-
- var op1 = new Vector2(x - GameConfig.TileCellSize * 1.5f + (rect.Size.X + 1) * GameConfig.TileCellSize, y + GameConfig.TileCellSize * 1.5f);
- var op2 = new Vector2(x + GameConfig.TileCellSize * 0.5f + (rect.Size.X + 1) * GameConfig.TileCellSize, y + GameConfig.TileCellSize * 1.5f);
- var op3 = new Vector2(x + GameConfig.TileCellSize * 0.5f + (rect.Size.X + 1) * GameConfig.TileCellSize, y + GameConfig.TileCellSize * 3f);
- var op4 = new Vector2(x - GameConfig.TileCellSize * 1.5f + (rect.Size.X + 1) * GameConfig.TileCellSize, y + GameConfig.TileCellSize * 3f);
- AddDoorNavigation(
- doorInfo, op1, op2, op3, op4,
- new Vector2(op2.X - GameConfig.TileCellSize, op1.Y),
- op2,
- op3,
- new Vector2(op2.X - GameConfig.TileCellSize, op4.Y)
- );
- }
- }
-
- //纵向过道, 门朝下, 连接方向向上
- private void FullVerticalAisleUp(AutoTileConfig config, Rect2 rect, RoomDoorInfo doorInfo = null)
- {
- //上
- ClearRect(GameConfig.TopMapLayer, rect.Position + new Vector2(1, -1), new Vector2(rect.Size.X - 2, 1));
- if (doorInfo == null)
- {
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, rect.Position + new Vector2(1, -1),
- new Vector2(rect.Size.X - 2, 1));
- }
- else
- {
- FillRect(GameConfig.TopMapLayer, config.OUT_RT, rect.Position + new Vector2(0, -1), Vector2.One);
- FillRect(GameConfig.TopMapLayer, config.OUT_LT, rect.Position + new Vector2(3, -1), Vector2.One);
-
- FillRect(GameConfig.FloorMapLayer, config.Floor, rect.Position + new Vector2(1, -1), new Vector2(rect.Size.X - 2, 1));
- //生成门的导航区域
- var x = rect.Position.X * GameConfig.TileCellSize;
- var y = rect.Position.Y * GameConfig.TileCellSize;
-
- var op1 = new Vector2(x + GameConfig.TileCellSize * 1.5f, y - GameConfig.TileCellSize * 1f);
- var op2 = new Vector2(x + GameConfig.TileCellSize * 2.5f, y - GameConfig.TileCellSize * 1f);
- var op3 = new Vector2(x + GameConfig.TileCellSize * 2.5f, y + GameConfig.TileCellSize * 0.5f);
- var op4 = new Vector2(x + GameConfig.TileCellSize * 1.5f, y + GameConfig.TileCellSize * 0.5f);
- AddDoorNavigation(
- doorInfo, op1, op2, op3, op4,
- op1,
- op2,
- new Vector2(op3.X, op1.Y + GameConfig.TileCellSize),
- new Vector2(op4.X, op1.Y + GameConfig.TileCellSize)
- );
- }
- }
-
- //纵向过道, 门朝上, 连接方向向下
- private void FullVerticalAisleDown(AutoTileConfig config, Rect2 rect, RoomDoorInfo doorInfo = null)
- {
- //下
- ClearRect(GameConfig.MiddleMapLayer, rect.Position + new Vector2(1, rect.Size.Y), new Vector2(rect.Size.X - 2, 1));
- if (doorInfo == null)
- {
- FillRect(GameConfig.AisleFloorMapLayer, config.Floor, rect.Position + new Vector2(1, rect.Size.Y), new Vector2(rect.Size.X - 2, 1));
- }
- else
- {
- FillRect(GameConfig.MiddleMapLayer, config.OUT_RB, rect.Position + new Vector2(0, rect.Size.Y), Vector2.One);
- FillRect(GameConfig.MiddleMapLayer, config.OUT_LB, rect.Position + new Vector2(3, rect.Size.Y), Vector2.One);
-
- FillRect(GameConfig.FloorMapLayer, config.Floor, rect.Position + new Vector2(1, rect.Size.Y), new Vector2(rect.Size.X - 2, 1));
- //生成门的导航区域
- var x = rect.Position.X * GameConfig.TileCellSize;
- var y = rect.Position.Y * GameConfig.TileCellSize;
-
- var op1 = new Vector2(x + GameConfig.TileCellSize * 1.5f, y - GameConfig.TileCellSize * 1f + (rect.Size.Y + 1) * GameConfig.TileCellSize);
- var op2 = new Vector2(x + GameConfig.TileCellSize * 2.5f, y - GameConfig.TileCellSize * 1f + (rect.Size.Y + 1) * GameConfig.TileCellSize);
- var op3 = new Vector2(x + GameConfig.TileCellSize * 2.5f, y + GameConfig.TileCellSize * 0.5f + (rect.Size.Y + 1) * GameConfig.TileCellSize);
- var op4 = new Vector2(x + GameConfig.TileCellSize * 1.5f, y + GameConfig.TileCellSize * 0.5f + (rect.Size.Y + 1) * GameConfig.TileCellSize);
- AddDoorNavigation(
- doorInfo, op1, op2, op3, op4,
- new Vector2(op1.X, op3.Y - GameConfig.TileCellSize),
- new Vector2(op2.X, op3.Y - GameConfig.TileCellSize),
- op3,
- op4
- );
- }
- }
-
- /// <summary>
- /// 添加房间
- /// </summary>
- private void AddDoorNavigation(RoomDoorInfo doorInfo,
- Vector2 op1, Vector2 op2, Vector2 op3, Vector2 op4,
- Vector2 cp1, Vector2 cp2, Vector2 cp3, Vector2 cp4)
- {
- var openPolygonData = new NavigationPolygonData();
- openPolygonData.Type = NavigationPolygonType.Out;
- openPolygonData.SetPoints(new []{ op1, op2, op3, op4 });
-
- var closePolygonData = new NavigationPolygonData();
- closePolygonData.Type = NavigationPolygonType.Out;
- closePolygonData.SetPoints(new []{ cp1, cp2, cp3, cp4 });
-
- _connectNavigationItemList.Add(new DoorNavigationInfo(doorInfo, openPolygonData, closePolygonData));
- }
-
- /// <summary>
- /// 计算并动生成导航区域, layer 为需要计算的层级,如果没有设置 floorAtlasCoords,则该 layer 下不为空的地砖都将视为可行走区域
- /// </summary>
- public void GenerateNavigationPolygon(int layer)
- {
- _usePoints.Clear();
- _polygonDataList.Clear();
-
- try
- {
- var size = new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize);
-
- var rect = _tileRoot.GetUsedRect();
-
- var x = rect.Position.X;
- var y = rect.Position.Y;
- var w = rect.Size.X;
- var h = rect.Size.Y;
-
- for (int j = y; j < h; j++)
- {
- for (int i = x; i < w; i++)
- {
- if (IsWayTile(layer, i, j))
- {
- if (!_usePoints.Contains(new Vector2I(i, j)))
- {
- NavigationPolygonData polygonData = null;
-
- if (!IsWayTile(layer, i, j - 1))
- {
- polygonData = CalcOutline(layer, i, j, size);
- }
- else if (!IsWayTile(layer, i, j + 1))
- {
- polygonData = CalcInline(layer, i, j, size);
- }
-
- if (polygonData != null)
- {
- _polygonDataList.Add(polygonData);
- }
- }
- }
- }
- }
-
- _generateNavigationResult = new GenerateNavigationResult(true);
- }
- catch (NavigationPointException e)
- {
- _usePoints.Clear();
- _polygonDataList.Clear();
- GD.Print(e.Message);
- _generateNavigationResult = new GenerateNavigationResult(false, e);
- }
- }
-
- /// <summary>
- /// 获取生成导航区域操作的结果, 如果没有调用过 GenerateNavigationPolygon() 函数, 则返回 null
- /// </summary>
- /// <returns></returns>
- public GenerateNavigationResult GetGenerateNavigationResult()
- {
- return _generateNavigationResult;
- }
-
- /// <summary>
- /// 将导航区域挂载到 navigationRoot 上
- /// </summary>
- public void MountNavigationPolygon(Node2D navigationRoot)
- {
- //TestData();
- // 在 Godot4.0_rc6 中 如果将所有点都放在 NavigationPolygon 里面, 即使点是对的, 但调用 MakePolygonsFromOutlines 还是可能会报错, 这应该是个bug
-
- //通过 GenerateNavigationPolygon() 计算出来的导航区域
- for (var i = 0; i < _polygonDataList.Count; i++)
- {
- var polygonData = _polygonDataList[i];
- CreateNavigationRegion(navigationRoot, polygonData);
- }
-
- //门占用区域的导航区域
- for (var i = 0; i < _connectNavigationItemList.Count; i++)
- {
- var item = _connectNavigationItemList[i];
- item.CloseNavigationNode = CreateNavigationRegion(navigationRoot, item.CloseNavigationData);
- item.OpenNavigationNode = CreateNavigationRegion(navigationRoot, item.OpenNavigationData);
- item.CloseNavigationNode.Enabled = false;
- item.OpenNavigationNode.Enabled = false;
- item.DoorInfo.Navigation = item;
- }
- }
-
- //创建导航区域
- private NavigationRegion2D CreateNavigationRegion(Node2D navigationRoot, NavigationPolygonData polygonData)
- {
- var polygon = new NavigationPolygon();
- polygon.AddOutline(polygonData.GetPoints());
- polygon.MakePolygonsFromOutlines();
- var navigationPolygon = new NavigationRegion2D();
- navigationPolygon.Name = "NavigationRegion" + (navigationRoot.GetChildCount() + 1);
- navigationPolygon.NavigationPolygon = polygon;
- navigationRoot.AddChild(navigationPolygon);
- return navigationPolygon;
- }
-
- /// <summary>
- /// 获取房间内的导航点数据
- /// </summary>
- public NavigationPolygonData[] GetPolygonData()
- {
- return _polygonDataList.ToArray();
- }
-
- /// <summary>
- /// 设置导航网格数据
- /// </summary>
- /// <param name="list"></param>
- public void SetPolygonData(List<NavigationPolygonData> list)
- {
- _polygonDataList.Clear();
- _polygonDataList.AddRange(list);
- _generateNavigationResult = new GenerateNavigationResult(true);
- }
-
- /// <summary>
- /// 清除生成的导航数据
- /// </summary>
- public void ClearPolygonData()
- {
- _polygonDataList.Clear();
- _generateNavigationResult = null;
- }
-
- /// <summary>
- /// 获取连接门导航数据, 必须要调用 AutoFillRoomTile() 函数才有数据
- /// </summary>
- public NavigationPolygonData[] GetConnectDoorPolygonData()
- {
- var array = new NavigationPolygonData[_connectNavigationItemList.Count];
- for (var i = 0; i < _connectNavigationItemList.Count; i++)
- {
- array[i] = _connectNavigationItemList[i].OpenNavigationData;
- }
- return array;
- }
-
- /// <summary>
- /// 设置地面的地砖,将影响导航网格计算
- /// </summary>
- public void SetFloorAtlasCoords(List<Vector2I> floorAtlasCoords)
- {
- _floorAtlasCoords = floorAtlasCoords;
- }
-
- /// <summary>
- /// 返回指定位置的Tile是否为可以行走
- /// </summary>
- private bool IsWayTile(int layer, int x, int y)
- {
- if (_floorAtlasCoords == null || _floorAtlasCoords.Count == 0)
- {
- return _tileRoot.GetCellTileData(layer, new Vector2I(x, y)) != null;
- }
-
- var result = _tileRoot.GetCellAtlasCoords(layer, new Vector2I(x, y));
- return _floorAtlasCoords.Contains(result);
- }
-
- //计算导航网格外轮廓
- private NavigationPolygonData CalcOutline(int layer, int i, int j, Vector2 size)
- {
- var polygonData = new NavigationPolygonData();
- polygonData.Type = NavigationPolygonType.Out;
- var points = new List<Vector2>();
- // 0:右, 1:下, 2:左, 3:上
- var dir = 0;
- var offset = new Vector2(size.X * 0.5f, size.Y * 0.5f);
- //找到路, 向右开始找边界
- var startPos = new Vector2I(i, j);
-
- var tempI = i;
- var tempJ = j;
-
- while (true)
- {
- switch (dir)
- {
- case 0: //右
- {
- if (IsWayTile(layer, tempI, tempJ - 1)) //先向上找
- {
- dir = 3;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempJ--;
- break;
- }
- else if (IsWayTile(layer, tempI + 1, tempJ)) //再向右找
- {
- if (points.Count == 0)
- {
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempI++;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ + 1)) //向下找
- {
- dir = 1;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempJ++;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- case 1: //下
- {
- if (IsWayTile(layer, tempI + 1, tempJ)) //先向右找
- {
- dir = 0;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempI++;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ + 1)) //再向下找
- {
- if (points.Count == 0)
- {
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempJ++;
- break;
- }
- else if (IsWayTile(layer, tempI - 1, tempJ)) //向左找
- {
- dir = 2;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempI--;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- case 2: //左
- {
- if (IsWayTile(layer, tempI, tempJ + 1)) //先向下找
- {
- dir = 1;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempJ++;
- break;
- }
- else if (IsWayTile(layer, tempI - 1, tempJ)) //再向左找
- {
- if (points.Count == 0)
- {
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempI--;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ - 1)) //向上找
- {
- dir = 3;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempJ--;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- case 3: //上
- {
- if (IsWayTile(layer, tempI - 1, tempJ)) //先向左找
- {
- dir = 2;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempI--;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ - 1)) //再向上找
- {
- if (points.Count == 0)
- {
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempJ--;
- break;
- }
- else if (IsWayTile(layer, tempI + 1, tempJ)) //向右找
- {
- dir = 0;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempI++;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- }
- }
- }
-
- //计算导航网格内轮廓
- private NavigationPolygonData CalcInline(int layer, int i, int j, Vector2 size)
- {
- var polygonData = new NavigationPolygonData();
- polygonData.Type = NavigationPolygonType.In;
- var points = new List<Vector2>();
- // 0:右, 1:下, 2:左, 3:上
- var dir = 0;
- var offset = new Vector2(size.X * 0.5f, size.Y * 0.5f);
- //找到路, 向右开始找边界
- var startPos = new Vector2I(i - 1, j);
- PutUsePoint(startPos);
-
- var tempI = i;
- var tempJ = j;
-
- while (true)
- {
- switch (dir)
- {
- case 0: //右
- {
- if (IsWayTile(layer, tempI, tempJ + 1)) //向下找
- {
- dir = 1;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempJ++;
- break;
- }
- else if (IsWayTile(layer, tempI + 1, tempJ)) //再向右找
- {
- if (points.Count == 0)
- {
- //points.Add(new Vector2((tempI - 1) * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2((tempI - 1) * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempI++;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ - 1)) //先向上找
- {
- dir = 3;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempJ--;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- case 1: //下
- {
- if (IsWayTile(layer, tempI - 1, tempJ)) //向左找
- {
- dir = 2;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempI--;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ + 1)) //再向下找
- {
- if (points.Count == 0)
- {
- points.Add(new Vector2((tempI - 1) * size.X + offset.X, tempJ * size.Y + offset.Y));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempJ++;
- break;
- }
- else if (IsWayTile(layer, tempI + 1, tempJ)) //先向右找
- {
- dir = 0;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempI++;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- case 2: //左
- {
- if (IsWayTile(layer, tempI, tempJ - 1)) //向上找
- {
- dir = 3;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempJ--;
- break;
- }
- else if (IsWayTile(layer, tempI - 1, tempJ)) //再向左找
- {
- if (points.Count == 0)
- {
- points.Add(new Vector2((tempI - 1) * size.X + offset.X, tempJ * size.Y + offset.Y));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempI--;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ + 1)) //先向下找
- {
- dir = 1;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempJ++;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- case 3: //上
- {
- if (IsWayTile(layer, tempI + 1, tempJ)) //向右找
- {
- dir = 0;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- //points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y * 2));
- PutUsePoint(pos);
-
- tempI++;
- break;
- }
- else if (IsWayTile(layer, tempI, tempJ - 1)) //再向上找
- {
- if (points.Count == 0)
- {
- points.Add(new Vector2((tempI - 1) * size.X + offset.X, tempJ * size.Y + offset.Y));
- }
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- PutUsePoint(new Vector2I(tempI, tempJ));
- tempJ--;
- break;
- }
- else if (IsWayTile(layer, tempI - 1, tempJ)) //先向左找
- {
- dir = 2;
-
- var pos = new Vector2I(tempI, tempJ);
- if (points.Count > 1 && pos == startPos)
- {
- polygonData.SetPoints(points.ToArray());
- return polygonData;
- }
-
- points.Add(new Vector2(tempI * size.X + offset.X, tempJ * size.Y + offset.Y));
- PutUsePoint(pos);
-
- tempI--;
- break;
- }
-
- throw new NavigationPointException(new Vector2I(tempI, tempJ), "生成导航多边形发生错误! 点: " + new Vector2I(tempI, tempJ) + "发生交错!");
- }
- }
- }
- }
-
- //记录导航网格中已经使用过的坐标
- private void PutUsePoint(Vector2I pos)
- {
- if (_usePoints.Contains(pos))
- {
- throw new NavigationPointException(pos, "生成导航多边形发生错误! 点: " + pos + "发生交错!");
- }
-
- _usePoints.Add(pos);
- }
- }