-
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using Godot;
-
- /// <summary>
- /// 地牢地砖管理类, 提供一些操作 TileMap 和计算导航的接口
- /// </summary>
- public class DungeonTileMap
- {
-
- //----------------------------------------------------
-
- private TileMap _tileRoot;
-
- public DungeonTileMap(TileMap tileRoot)
- {
- _tileRoot = tileRoot;
- }
-
- /// <summary>
- /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的房间数据, 该函数为协程函数
- /// </summary>
- public IEnumerator AutoFillRoomTile(AutoTileConfig config, RoomInfo startRoomInfo, World world)
- {
- yield return _AutoFillRoomTile(config, startRoomInfo, world);
- }
-
- /// <summary>
- /// 根据 startRoom 和 config 数据自动填充 tileMap 参数中的过道数据, 该函数为协程函数
- /// </summary>
- public IEnumerator AutoFillAisleTile(AutoTileConfig config, RoomInfo roomInfo, World world)
- {
- yield return _AutoFillAisleTile(config, roomInfo, world);
- }
-
- private IEnumerator _AutoFillRoomTile(AutoTileConfig config, RoomInfo roomInfo, World world)
- {
- foreach (var info in roomInfo.Next)
- {
- yield return _AutoFillRoomTile(config, info, world);
- }
-
- //铺房间
- var rectPos = roomInfo.RoomSplit.RoomInfo.Position.AsVector2I();
- var tileInfo = roomInfo.RoomSplit.TileInfo;
-
- //---------------------- 生成房间小地图预览 ----------------------
- //先计算范围
- var x = int.MaxValue;
- var y = int.MaxValue;
- var x2 = int.MinValue;
- var y2 = int.MinValue;
- for (var i = 0; i < tileInfo.Floor.Count; i += 4)
- {
- var posX = tileInfo.Floor[i];
- var posY = tileInfo.Floor[i + 1];
- x = Mathf.Min(x, posX);
- x2 = Mathf.Max(x2, posX);
- y = Mathf.Min(y, posY);
- y2 = Mathf.Max(y2, posY);
- }
- //创建image, 这里留两个像素宽高用于描边
- var image = Image.Create(x2 - x + 3, y2 - y + 3, false, Image.Format.Rgba8);
- //image.Fill(Colors.Green);
- //填充像素点
- for (var i = 0; i < tileInfo.Floor.Count; i += 4)
- {
- var posX = tileInfo.Floor[i] - x + 1;
- var posY = tileInfo.Floor[i + 1] - y + 1;
- image.SetPixel(posX, posY, new Color(0, 0, 0, 0.5882353F));
- }
- //创建texture
- var imageTexture = ImageTexture.CreateFromImage(image);
- roomInfo.PreviewTexture = imageTexture;
-
- //---------------------- 填充tile操作 ----------------------
- var terrainInfo = config.TerrainInfo;
-
- SetAutoLayerDataFromList(MapLayer.AutoFloorLayer, config.SourceId, roomInfo, tileInfo.Floor, rectPos, terrainInfo);
- SetCustomLayerDataFromList(MapLayer.CustomFloorLayer1, roomInfo, tileInfo.CustomFloor1, rectPos);
- SetCustomLayerDataFromList(MapLayer.CustomFloorLayer2, roomInfo, tileInfo.CustomFloor2, rectPos);
- SetCustomLayerDataFromList(MapLayer.CustomFloorLayer3, roomInfo, tileInfo.CustomFloor3, rectPos);
- SetCustomLayerDataFromList(MapLayer.CustomMiddleLayer1, roomInfo, tileInfo.CustomMiddle1, rectPos);
- SetCustomLayerDataFromList(MapLayer.CustomMiddleLayer2, roomInfo, tileInfo.CustomMiddle2, rectPos);
- SetCustomLayerDataFromList(MapLayer.CustomTopLayer, roomInfo, tileInfo.CustomTop, rectPos);
-
- //寻找可用传送点
- var maxCount = (roomInfo.Size.X - 2) * (roomInfo.Size.Y - 2);
- var startPosition = roomInfo.Position + roomInfo.Size / 2;
- for (int i = 0; i < maxCount; i++)
- {
- var pos = SpiralUtil.Screw(i) + startPosition;
- if (IsWayTile(MapLayer.AutoFloorLayer, pos.X, pos.Y))
- {
- roomInfo.Waypoints = pos;
- break;
- }
- }
-
- //---------------------- 随机选择预设 ----------------------
- RoomPreinstallInfo preinstallInfo;
- if (EditorPlayManager.IsPlay && roomInfo.RoomType == GameApplication.Instance.DungeonManager.CurrConfig.DesignatedType) //编辑器模式, 指定预设
- {
- preinstallInfo = EditorTileMapManager.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 = world.Random.RandomWeight(weights);
- preinstallInfo = roomInfo.RoomSplit.Preinstall[index];
- }
- }
-
- var roomPreinstall = new RoomPreinstall(roomInfo, preinstallInfo);
- roomInfo.RoomPreinstall = roomPreinstall;
- //执行预处理操作
- roomPreinstall.Pretreatment(world);
- }
-
-
- private IEnumerator _AutoFillAisleTile(AutoTileConfig config, RoomInfo roomInfo, World world)
- {
- foreach (var info in roomInfo.Next)
- {
- yield return _AutoFillAisleTile(config, info, world);
- }
-
- // yield break;
- //铺过道
- foreach (var doorInfo in roomInfo.Doors)
- {
- //必须是正向门
- if (!doorInfo.IsForward)
- {
- continue;
- }
-
- //铺过道
- if (doorInfo.AisleFloorCell != null)
- {
- yield return 0;
-
- //创建image, 这里留两个像素宽高用于描边
- var aisleImage = Image.Create(doorInfo.AisleFloorRect.Size.X, doorInfo.AisleFloorRect.Size.Y, false, Image.Format.Rgba8);
- //image.Fill(new Color(0, 1, 0, 0.2f));
- //填充像素点
- foreach (var p in doorInfo.AisleFloorCell)
- {
- _tileRoot.SetCell(MapLayer.AutoFloorLayer, p, config.Floor.SourceId, config.Floor.AutoTileCoords);
- //_tileRoot.SetCell(MapLayer.CustomTopLayer, p, config.Auto_000_010_000.SourceId, config.Auto_000_010_000.AutoTileCoords);
- aisleImage.SetPixel(p.X - doorInfo.AisleFloorRect.Position.X, p.Y - doorInfo.AisleFloorRect.Position.Y, new Color(1, 1, 1, 0.5882353F));
- }
- //创建texture
- var aisleImageTexture = ImageTexture.CreateFromImage(aisleImage);
- doorInfo.AislePreviewTexture = aisleImageTexture;
- doorInfo.ConnectDoor.AislePreviewTexture = aisleImageTexture;
- }
- }
- }
-
-
- public void GenerateWallAndNavigation(World world, AutoTileConfig config)
- {
- var navigation = new NavigationRegion2D();
- navigation.Name = "Navigation";
- world.NavigationRoot.AddChild(navigation);
- TileMapUtils.GenerateTerrain(_tileRoot, navigation, config);
- }
-
- //设置自动地形层的数据
- private void SetAutoLayerDataFromList(int layer, int sourceId, RoomInfo roomInfo, List<int> data, Vector2I rectPos, TileSetTerrainInfo terrainInfo)
- {
- for (var i = 0; i < data.Count; i += 4)
- {
- var posX = data[i];
- var posY = data[i + 1];
- var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
- var bit = (uint)data[i + 2];
- var type = (byte)data[i + 3];
- var index = terrainInfo.TerrainBitToIndex(bit, type);
- var terrainCell = terrainInfo.GetTerrainCell(index, type);
- var atlasCoords = terrainInfo.GetPosition(terrainCell);
- _tileRoot.SetCell(layer, pos, sourceId, atlasCoords);
- }
- }
-
- //设置自定义层的数据
- private void SetCustomLayerDataFromList(int layer, RoomInfo roomInfo, List<int> data, Vector2I rectPos)
- {
- for (var i = 0; i < data.Count; i += 5)
- {
- var posX = data[i];
- var posY = data[i + 1];
- var sourceId = data[i + 2];
- var atlasCoordsX = data[i + 3];
- var atlasCoordsY = data[i + 4];
- var pos = new Vector2I(roomInfo.Position.X + posX - rectPos.X, roomInfo.Position.Y + posY - rectPos.Y);
- _tileRoot.SetCell(layer, pos, sourceId, new Vector2I(atlasCoordsX, atlasCoordsY));
- }
- }
-
- //填充tile区域
- private void FillRect(int layer, TileCellData data, Vector2 pos, Vector2 size)
- {
- for (int i = 0; i < size.X; i++)
- {
- for (int j = 0; j < size.Y; j++)
- {
- var p = new Vector2I((int)pos.X + i, (int)pos.Y + j);
- _tileRoot.SetCell(layer, p, data.SourceId, data.AutoTileCoords);
- }
- }
- }
-
- //清除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++)
- {
- var p = new Vector2I((int)pos.X + i, (int)pos.Y + j);
- _tileRoot.SetCell(layer, p, 0);
- }
- }
- }
-
- /// <summary>
- /// 返回指定位置的Tile是否为可以行走
- /// </summary>
- private bool IsWayTile(int layer, int x, int y)
- {
- return _tileRoot.GetCellSourceId(layer, new Vector2I(x, y)) != -1;
- }
- }