Guest User

Untitled

a guest
Apr 30th, 2025
11
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.59 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using DelaunatorSharp;
  5. using UnityEngine;
  6.  
  7. namespace Frigga
  8. {
  9.     public class HeIsComingGenerator2 : GeneratorBase
  10.     {
  11.         public Vector2Int LevelSize = new Vector2Int(50, 50);
  12.  
  13.         public int RegionCount = 15;
  14.         public int MinRegionDistance = 4;
  15.  
  16.         [IntGridTilePicker] public int PathTile;
  17.         [IntGridTilePicker] public int RegionTile;
  18.         [IntGridTilePicker] public int RegionCenterTile;
  19.  
  20.         private List<IEdge> edges = new List<IEdge>();
  21.  
  22.         protected override IEnumerable<GeneratorProgress> GenerateLayout(GeneratorResult result)
  23.         {
  24.             edges.Clear();
  25.  
  26.             var bounds = new BoundsInt(Vector3Int.zero, new Vector3Int(LevelSize.x, LevelSize.y, 1));
  27.             var points = new HashSet<Vector3Int>();
  28.             var i = 0;
  29.             while (points.Count < RegionCount)
  30.             {
  31.                 if (i > 1000)
  32.                 {
  33.                     break;
  34.                 }
  35.  
  36.                 i++;
  37.                 var center = new Vector3Int(Random.Next(0, LevelSize.x), Random.Next(0, LevelSize.y), 0);
  38.                 if (points.Any(p => (p - center).sqrMagnitude < MinRegionDistance * MinRegionDistance))
  39.                 {
  40.                     continue;
  41.                 }
  42.                 points.Add(center);
  43.             }
  44.  
  45.             var delaunator = new Delaunator(points.Select(p => new Point(p.x, p.y)).Cast<IPoint>().ToArray());
  46.  
  47.             var intGrid = new IntGrid();
  48.             result.IntGrid = intGrid;
  49.  
  50.             // Initialize the grid with RegionTile
  51.             for (int x = 0; x < LevelSize.x; x++)
  52.             {
  53.                 for (int y = 0; y < LevelSize.y; y++)
  54.                 {
  55.                     intGrid.SetTile(new Vector3Int(x, y, 0), RegionTile);
  56.                 }
  57.             }
  58.  
  59.             // First, place all region centers
  60.             // foreach (var point in points) {
  61.             //     intGrid.SetTile(point, RegionCenterTile);
  62.             // }
  63.  
  64.             // Sort edges by length to process shorter edges first
  65.             // This helps ensure that shorter paths are created first, which can help avoid double paths
  66.             var sortedEdges = new List<IEdge>();
  67.             delaunator.ForEachVoronoiEdge(edge => {
  68.                 sortedEdges.Add(edge);
  69.             });
  70.            
  71.             // Sort edges by length (shorter edges first)
  72.             sortedEdges.Sort((a, b) => {
  73.                 float lengthA = Mathf.Sqrt(Mathf.Pow((float)(a.Q.X - a.P.X), 2) + Mathf.Pow((float)(a.Q.Y - a.P.Y), 2));
  74.                 float lengthB = Mathf.Sqrt(Mathf.Pow((float)(b.Q.X - b.P.X), 2) + Mathf.Pow((float)(b.Q.Y - b.P.Y), 2));
  75.                 return lengthA.CompareTo(lengthB);
  76.             });
  77.  
  78.             // Process edges in order of length
  79.             foreach (var edge in sortedEdges)
  80.             {
  81.                 edges.Add(edge);
  82.                 var point1 = new Vector3Int((int) edge.P.X, (int)edge.P.Y, 0);
  83.                 var point2 = new Vector3Int((int) edge.Q.X, (int)edge.Q.Y, 0);
  84.  
  85.                 // Find the shortest path between point1 and point2 using A* pathfinding
  86.                 var path = FindPath(point1, point2, intGrid);
  87.                
  88.                 // Place Path tiles along the path
  89.                 if (path != null)
  90.                 {
  91.                     foreach (var pathPoint in path)
  92.                     {
  93.                         intGrid.SetTile(pathPoint, PathTile);
  94.                         yield return new GeneratorProgress() {
  95.                             IntGrid = intGrid,
  96.                         };
  97.                     }
  98.                 }
  99.             }
  100.  
  101.             yield break;
  102.         }
  103.  
  104.         private List<Vector3Int> FindPath(Vector3Int start, Vector3Int end, IntGrid intGrid)
  105.         {
  106.             // A* pathfinding implementation
  107.             var openSet = new List<PathNode>();
  108.             var closedSet = new HashSet<PathNode>();
  109.             var pathNodes = new Dictionary<Vector3Int, PathNode>();
  110.            
  111.             // Create start node
  112.             var startNode = new PathNode(start, null, 0, GetHeuristic(start, end));
  113.             openSet.Add(startNode);
  114.             pathNodes[start] = startNode;
  115.            
  116.             while (openSet.Count > 0)
  117.             {
  118.                 // Get node with lowest F cost
  119.                 openSet.Sort((a, b) => a.F.CompareTo(b.F));
  120.                 var currentNode = openSet[0];
  121.                
  122.                 // If we reached the end, reconstruct and return the path
  123.                 if (currentNode.Position == end)
  124.                 {
  125.                     return ReconstructPath(currentNode);
  126.                 }
  127.                
  128.                 openSet.RemoveAt(0);
  129.                 closedSet.Add(currentNode);
  130.                
  131.                 // Check neighbors
  132.                 foreach (var neighbor in GetNeighbors(currentNode.Position))
  133.                 {
  134.                     // Skip if out of bounds
  135.                     if (neighbor.x < 0 || neighbor.x >= LevelSize.x ||
  136.                         neighbor.y < 0 || neighbor.y >= LevelSize.y)
  137.                     {
  138.                         continue;
  139.                     }
  140.                    
  141.                     // Calculate G cost (distance from start)
  142.                     // If the neighbor is already a path tile, give it a lower cost
  143.                     float tileCost = 1.2f;
  144.                     if (intGrid.GetTile(neighbor) == PathTile)
  145.                     {
  146.                         // Prefer walking on existing paths by giving them a lower cost
  147.                         tileCost = 1f;
  148.                         Debug.Log($"Walking on existing path at {neighbor}");
  149.                     }
  150.                    
  151.                     float newG = currentNode.G + tileCost;
  152.                    
  153.                     // Get or create neighbor node
  154.                     PathNode neighborNode;
  155.                     if (!pathNodes.TryGetValue(neighbor, out neighborNode))
  156.                     {
  157.                         neighborNode = new PathNode(neighbor, currentNode, newG, GetHeuristic(neighbor, end));
  158.                         pathNodes[neighbor] = neighborNode;
  159.                         openSet.Add(neighborNode);
  160.                     }
  161.                     else if (newG < neighborNode.G)
  162.                     {
  163.                         // This path to neighbor is better than any previous one
  164.                         neighborNode.Parent = currentNode;
  165.                         neighborNode.G = newG;
  166.                         neighborNode.F = neighborNode.G + neighborNode.H;
  167.                     }
  168.                     else if (closedSet.Contains(neighborNode))
  169.                     {
  170.                         // Skip if already in closed set
  171.                         continue;
  172.                     }
  173.                 }
  174.             }
  175.            
  176.             // No path found
  177.             return null;
  178.         }
  179.        
  180.         private List<Vector3Int> ReconstructPath(PathNode endNode)
  181.         {
  182.             var path = new List<Vector3Int>();
  183.             var currentNode = endNode;
  184.            
  185.             while (currentNode != null)
  186.             {
  187.                 path.Add(currentNode.Position);
  188.                 currentNode = currentNode.Parent;
  189.             }
  190.            
  191.             path.Reverse();
  192.             return path;
  193.         }
  194.        
  195.         private float GetHeuristic(Vector3Int a, Vector3Int b)
  196.         {
  197.             // Manhattan distance heuristic
  198.             return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
  199.         }
  200.        
  201.         private List<Vector3Int> GetNeighbors(Vector3Int pos)
  202.         {
  203.             // Return the 4 adjacent neighbors (up, right, down, left)
  204.             return new List<Vector3Int>
  205.             {
  206.                 new Vector3Int(pos.x, pos.y + 1, 0), // Up
  207.                 new Vector3Int(pos.x + 1, pos.y, 0), // Right
  208.                 new Vector3Int(pos.x, pos.y - 1, 0), // Down
  209.                 new Vector3Int(pos.x - 1, pos.y, 0)  // Left
  210.             };
  211.         }
  212.        
  213.         private class PathNode
  214.         {
  215.             public Vector3Int Position;
  216.             public PathNode Parent;
  217.             public float G; // Cost from start to current
  218.             public float H; // Estimated cost from current to end
  219.             public float F; // Total cost (G + H)
  220.            
  221.             public PathNode(Vector3Int pos, PathNode parent, float g, float h)
  222.             {
  223.                 Position = pos;
  224.                 Parent = parent;
  225.                 G = g;
  226.                 H = h;
  227.                 F = G + H;
  228.             }
  229.            
  230.             public override bool Equals(object obj)
  231.             {
  232.                 if (obj is PathNode other)
  233.                 {
  234.                     return Position.Equals(other.Position);
  235.                 }
  236.                 return false;
  237.             }
  238.            
  239.             public override int GetHashCode()
  240.             {
  241.                 return Position.GetHashCode();
  242.             }
  243.         }
  244.  
  245.         private void OnDrawGizmos()
  246.         {
  247.             if (!ShowGizmos || edges == null || edges.Count == 0) return;
  248.  
  249.             Gizmos.color = Color.yellow;
  250.             foreach (var edge in edges)
  251.             {
  252.                 Vector3 start = new Vector3((float)edge.P.X, (float)edge.P.Y, 0);
  253.                 Vector3 end = new Vector3((float)edge.Q.X, (float)edge.Q.Y, 0);
  254.                 Gizmos.DrawLine(start, end);
  255.             }
  256.         }
  257.  
  258.         protected override List<string> ValidateConfiguration()
  259.         {
  260.             return null;
  261.         }
  262.     }
  263. }
  264.  
Add Comment
Please, Sign In to add comment