public static Graph2d CreateRoutingCostMap(List <Room> _exclude, IVector2 _size, int _roomBuffer, int _tunnelMagBuffer, double _tunnelRoutingStrength) { var defCost = _tunnelRoutingStrength * 2d + 1; var routingGraph = new Graph2d(_size, defCost, false); foreach (var room in m_Tilemap.m_Rooms) { if (_exclude.Contains(room)) { //Add special case routing per room shape switch (room.Shape) { //Rect rooms add corners as impassable case Room.ShapeType.Rectangle: foreach (var corner in room.Corners) { routingGraph.SetNodeWeight(corner, double.MaxValue); } break; default: break; } continue; } //Add room walls as impassable with specified buffer List <IVector2> bufferPoly; //Pre-calculate costs for room buffer var cost = new double[_roomBuffer + 1]; for (var buffer = _roomBuffer; buffer > 0; --buffer) { cost[buffer] = defCost + defCost * (_roomBuffer - buffer); } cost[0] = double.MaxValue; //Add room buffer costs for (var buffer = _roomBuffer; buffer >= 0; --buffer) { if (buffer != 0) { var co = new ClipperOffset(); var wallCoords = room.GetWallCoords(true); co.AddPath(Support2D.ToIntPoint(wallCoords), JoinType.jtMiter, EndType.etClosedPolygon); var pt = new PolyTree(); co.Execute(ref pt, buffer); bufferPoly = Support2D.ToIVector2(pt.Childs[0].Contour); var path = Support2D.CreatePath(bufferPoly, true); foreach (var coord in path) { routingGraph.SetNodeWeight(coord, cost[buffer] + routingGraph.GetNodeWeight(coord)); } } else { foreach (var coord in room.GetWallCoords(true)) { routingGraph.SetNodeWeight(coord, cost[0]); } } } } if (_tunnelMagBuffer >= 0 && Settings.CalcRoutingStrength != 0) { //Pre-calcluate costs for tunnel magnetism var tunnelCost = new double[_tunnelMagBuffer + 1]; tunnelCost[0] = 1d; for (var tScaleIdx = 1; tScaleIdx <= _tunnelMagBuffer; ++tScaleIdx) { tunnelCost[tScaleIdx] = tunnelCost[0] + _tunnelRoutingStrength + (tScaleIdx - 1) * (defCost - 1 - _tunnelRoutingStrength) / _tunnelMagBuffer; } foreach (var tunnel in m_Tilemap.m_Tunnels) { for (var tOffset = _tunnelMagBuffer; tOffset >= 0; --tOffset) { //double cost = _defaultCost - _defaultCost/(tOffset + 1); foreach (var path in tunnel.Paths) { if (tOffset > 0) { var solution = new PolyTree(); var co = new ClipperOffset(); co.AddPath(Support2D.ToIntPoint(path.Points), JoinType.jtMiter, EndType.etOpenButt); //co.AddPath(Support2D.ToIntPoint(path.PointsReverse), JoinType.jtSquare, // EndType.etOpenButt); co.Execute(ref solution, tOffset); foreach (var child in solution.Childs) { var tunnelPath = Support2D.CreatePath(Support2D.ToIVector2(child.Contour), true); foreach (var coord in tunnelPath) { if (!routingGraph.IsImpassable(coord)) { var curCost = routingGraph.GetNodeWeight(coord); if (curCost <= defCost && curCost > tunnelCost[tOffset]) { routingGraph.SetNodeWeight(coord, tunnelCost[tOffset]); } } } } } else { foreach (var coord in path.Points) { if (!routingGraph.IsImpassable(coord)) { routingGraph.SetNodeWeight(coord, tunnelCost[0]); } } //routingGraph.ScaleNodeWeight(coord, 0.1f * (float)_defaultCost); } } } } } return(routingGraph); }
//private static IEnumerator Dungeon() //UNITY public static void Dungeon() { GenerateDone = false; m_Generating = true; //TileMap2D.meshRenderer.material.mainTexture = null; //Set Logging action Msg.CreateLog(LOGKEY_MESSAGES, LogVerbosity.HIGH, LogStyle.MESSAGE_ONLY, Settings.ActionForUserMessages); //Set random seed if (Settings.RndSeed == 0) { byte[] rngCont = { 0, 0, 0, 0 }; var rng = RandomNumberGenerator.Create(); rng.GetBytes(rngCont); if (BitConverter.IsLittleEndian) { Array.Reverse(rngCont); } Settings.RndSeed = BitConverter.ToInt32(rngCont, 0); } m_Random = new Random(Settings.RndSeed); var timeStamp = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; Msg.LogDebug(TAG_DEBUG, DebugSettingsToString(), MsgPriLvl.HIGH); var logMsg = "Creating Dungeon... (Seed [ " + Settings.RndSeed + " ])\n Generating Rooms..."; Msg.Log(LOGKEY_MESSAGES, LOGKEY_MESSAGES, logMsg, MsgPriLvl.HIGH); //1. Generate and place rooms =========================================================================== //Set "aspect ratio" of entire dungeon space. var tarAspect = Settings.AspectRatio; if (tarAspect > MAX_ASPECT || tarAspect < 1f / MAX_ASPECT) { //invalid target aspect if (FlipCoin()) { tarAspect = m_Random.NextDouble() * (MAX_ASPECT - 1) + 1; } else { tarAspect = (m_Random.NextDouble() * 1 / MAX_ASPECT) + 1 / MAX_ASPECT; } } Msg.LogDebug(TAG_DEBUG, "Dungeon Map Aspect Ratio: " + tarAspect, MsgPriLvl.HIGH); //Create rooms and place in map m_Tilemap = CreateMapAndPlaceRooms(); logMsg = "Done placing rooms. Creating Tunnels."; Msg.Log(LOGKEY_MESSAGES, LOGKEY_MESSAGES, logMsg, MsgPriLvl.HIGH); //2. Add connectors/Tunnels and Draw to map ==================================================================== m_Tilemap.m_EntryPoint = new IVector2(m_Random.Next(Settings.MapOuterBuffer, m_Tilemap.Dims.x), m_Random.Next(Settings.MapOuterBuffer, m_Tilemap.Dims.y)); //Check special case entry points foreach (var room in m_Tilemap.m_Rooms) { if (room.Shape != Room.ShapeType.Ellipse) { continue; } while (true) { if (room.Bounds.Encapsulates(m_Tilemap.m_EntryPoint) && !room.ContainsCoord(m_Tilemap.m_EntryPoint, true)) { m_Tilemap.m_EntryPoint = new IVector2(m_Random.Next(Settings.MapOuterBuffer, m_Tilemap.Dims.x), m_Random.Next(Settings.MapOuterBuffer, m_Tilemap.Dims.y)); } else { break; } } } Msg.LogDebug(TAG_DEBUG, "Entry point created at " + m_Tilemap.EntryPoint, MsgPriLvl.MED); //yield return TileMap2D.instance.StartCoroutine(CreateTunnels(m_Tilemap.EntryPoint)); //UNITY CreateTunnels(m_Tilemap.EntryPoint); if (m_Tilemap.m_Tunnels == null) { var newSeed = (int)Math.Pow(Settings.RndSeed, 2); Msg.LogDebug(TAG_DEBUG, "Bad Triangulation restarting Dungeon Thread with Seed " + Settings.RndSeed + " trying Seed " + newSeed, MsgPriLvl.HIGH); Settings.RndSeed = newSeed; //yield return Dungeon(); //UNITY //yield break; //UNITY Dungeon(); } //Draw Tunnel walls foreach (var tunnelNet in m_Tilemap.m_Tunnels) { foreach (var path in tunnelNet.Paths) { var solution = new PolyTree(); var co = new ClipperOffset(); co.AddPath(Support2D.ToIntPoint(path.Points), JoinType.jtMiter, EndType.etOpenButt); co.Execute(ref solution, 1); m_Tilemap.m_MapData.DrawClosedPoly(Support2D.ToIVector2(solution.Childs[0].Contour), WallMaterial); } } //Draw Entry Point Walls foreach (var neighbor in m_Tilemap.EntryPoint.Neighbors(true)) { if (m_Tilemap.m_MapData.InBounds(neighbor)) { m_Tilemap.m_MapData[neighbor] = WallMaterial; } } //Draw room walls and floors DrawRooms(m_Tilemap.m_Rooms, ref m_Tilemap.m_MapData); //Draw Tunnel Floor foreach (var tunnel in m_Tilemap.m_Tunnels) { foreach (var path in tunnel.Paths) { m_Tilemap.m_MapData.DrawPath(path.Points, FloorMaterial); } } //Draw Entry Point Floor (in case it landed on a Wall/Corner) m_Tilemap.m_MapData[m_Tilemap.EntryPoint] = FloorMaterial; var wallCount = 0; foreach (var neighbor in m_Tilemap.EntryPoint.Neighbors(false)) { if (m_Tilemap.m_MapData[neighbor] == WallMaterial) { wallCount++; } } if (wallCount == 4) { foreach (var neighbor in m_Tilemap.EntryPoint.Neighbors(false)) { foreach (var wallNeighbor in neighbor.Neighbors(false)) { if (wallNeighbor != m_Tilemap.EntryPoint && m_Tilemap.m_MapData[wallNeighbor] == FloorMaterial) { m_Tilemap.m_MapData[neighbor] = FloorMaterial; goto GoodEntry; } } } } GoodEntry: //Add Doorways CreateDoorways(); var timeStampEnd = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; logMsg = "Dungeon Created in " + (timeStampEnd - timeStamp) + "ms"; //Log(logMsg); Msg.LogDebug(TAG_DEBUG, logMsg, MsgPriLvl.HIGH); GenerateDone = true; m_Generating = false; //m_MapHolder.m_MapData.Compressed = true; Msg.DeleteLog(LOGKEY_MESSAGES); }