Guest User

Untitled

a guest
Sep 9th, 2025
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.34 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using DelaunatorSharp;
  6. using UnityEngine;
  7.  
  8. namespace Frigga
  9. {
  10.     public class HeIsComingGenerator2 : GeneratorBase
  11.     {
  12.         public Vector2Int LevelSize = new Vector2Int(50, 50);
  13.  
  14.         public int RegionCount = 15;
  15.         public int MinRegionDistance = 4;
  16.         public int BorderSize = 5;
  17.  
  18.         [IntGridTilePicker] public int PathTile;
  19.         [IntGridTilePicker] public int RegionTile;
  20.         [IntGridTilePicker] public int RegionCenterTile;
  21.  
  22.         private List<IEdge> edges = new List<IEdge>();
  23.         private List<Vector3Int> doublePaths = new List<Vector3Int>();
  24.         private HashSet<Vector3Int> generatedPoints = new HashSet<Vector3Int>();
  25.  
  26.         protected override IEnumerable<GeneratorProgress> GenerateLayout(GeneratorResult result)
  27.         {
  28.             ShowGizmos = true;
  29.  
  30.             edges.Clear();
  31.             doublePaths.Clear();
  32.             generatedPoints.Clear();
  33.  
  34.             var bounds = new BoundsInt(Vector3Int.zero, new Vector3Int(LevelSize.x, LevelSize.y, 1));
  35.             var points = new HashSet<Vector3Int>();
  36.             var i = 0;
  37.             while (points.Count < RegionCount)
  38.             {
  39.                 if (i > 1000)
  40.                 {
  41.                     break;
  42.                 }
  43.  
  44.                 i++;
  45.                 var center = new Vector3Int(Random.Next(0, LevelSize.x - 2 * BorderSize) + BorderSize, Random.Next(0, LevelSize.y - 2 * BorderSize) + BorderSize, 0);
  46.                 if (points.Any(p => (p - center).sqrMagnitude < MinRegionDistance * MinRegionDistance))
  47.                 {
  48.                     continue;
  49.                 }
  50.                 points.Add(center);
  51.                 generatedPoints.Add(center);
  52.             }
  53.  
  54.             var delaunator = new Delaunator(points.Select(p => new Point(p.x, p.y)).Cast<IPoint>().ToArray());
  55.  
  56.             var intGrid = new IntGrid();
  57.             result.IntGrid = intGrid;
  58.  
  59.             for (int j = 0; j < 100; j++)
  60.             {
  61.                 yield return new GeneratorProgress() {
  62.                     IntGrid = intGrid,
  63.                 };
  64.             }
  65.  
  66.             // Initialize the grid with RegionTile
  67.             for (int x = 0; x < LevelSize.x; x++)
  68.             {
  69.                 for (int y = 0; y < LevelSize.y; y++)
  70.                 {
  71.                     intGrid.SetTile(new Vector3Int(x, y, 0), RegionTile);
  72.                 }
  73.             }
  74.  
  75.             // First, place all region centers
  76.             // foreach (var point in points) {
  77.             //     intGrid.SetTile(point, RegionCenterTile);
  78.             // }
  79.  
  80.             // Sort edges by point coordinates
  81.             var sortedEdges = new List<IEdge>();
  82.             delaunator.ForEachVoronoiEdge(edge => {
  83.                 sortedEdges.Add(edge);
  84.             });
  85.            
  86.             // Sort edges by point coordinates from top-left to bottom-right
  87.             sortedEdges.Sort((a, b) => {
  88.                 // First compare P points by Y in descending order (highest Y first)
  89.                 int pCompare = b.P.Y.CompareTo(a.P.Y);
  90.                 if (pCompare != 0) return pCompare;
  91.                 // Then by X in ascending order (left to right)
  92.                 pCompare = b.P.X.CompareTo(a.P.X);
  93.                 if (pCompare != 0) return pCompare;
  94.                
  95.                 // If P points are equal, compare Q points
  96.                 int qCompare = b.Q.Y.CompareTo(a.Q.Y);
  97.                 if (qCompare != 0) return qCompare;
  98.                 return a.Q.X.CompareTo(b.Q.X);
  99.             });
  100.            
  101.             // Process edges in order of length
  102.             foreach (var edge in sortedEdges)
  103.             {
  104.                 var point = new Vector3Int((int) edge.P.X, (int)edge.P.Y, 0);
  105.                 intGrid.SetTile(point, PathTile);
  106.             }
  107.  
  108.             edges.AddRange(sortedEdges);
  109.  
  110.             // Process edges in order of length
  111.             var p = 0;
  112.             foreach (var edge in sortedEdges)
  113.             {
  114.                 p++;
  115.                 var point1 = new Vector3Int((int) edge.P.X, (int)edge.P.Y, 0);
  116.                 var point2 = new Vector3Int((int) edge.Q.X, (int)edge.Q.Y, 0);
  117.  
  118.                 // Find the shortest path between point1 and point2 using A* pathfinding
  119.                 var path = FindPath3(point1, point2, intGrid);
  120.                
  121.                 // Place Path tiles along the path
  122.                 if (path != null)
  123.                 {
  124.                     foreach (var pathPoint in path)
  125.                     {
  126.                         intGrid.SetTile(pathPoint, PathTile);
  127.                         // yield return new GeneratorProgress() {
  128.                         //     IntGrid = intGrid,
  129.                         // };
  130.                     }
  131.  
  132.                     if (p % 3 == 0)
  133.                     {
  134.                         yield return new GeneratorProgress() {
  135.                             IntGrid = intGrid,
  136.                         };
  137.                     }
  138.  
  139.                 }
  140.             }
  141.  
  142.             // After all paths are generated, find double paths
  143.             // doublePaths = FindDoublePaths(intGrid);
  144.  
  145.             // ShowGizmos = false;
  146.  
  147.             yield break;
  148.         }
  149.        
  150.         private List<Vector3Int> FindPath3(Vector3Int start, Vector3Int end, IntGrid intGrid) {
  151.             var current = start;
  152.             var path = new List<Vector3Int>
  153.             {
  154.                 current
  155.             };
  156.  
  157.             var i = 0;
  158.             var direction = GetNextDirection(start, end);
  159.             while (true) {
  160.                
  161.                 if (current == end) {
  162.                     break;
  163.                 }
  164.  
  165.                 if (current + GetNextDirection(current, end) == end)
  166.                 {
  167.                     path.Add(end);
  168.                     break;
  169.                 }
  170.                
  171.                 if (WouldCauseDoublePath(current, direction, intGrid, path, out var perpendicularCurrent))
  172.                 {
  173.                     current = perpendicularCurrent;
  174.                 }
  175.                
  176.                 var next = current + direction;
  177.                 current = next;
  178.                 path.Add(current);
  179.                
  180.                 var currentDifference = end - current;
  181.                 var mult = currentDifference.x * direction.x + currentDifference.y * direction.y;
  182.                 var nextDirection = GetNextDirection(current, end);
  183.                 if (mult == 0 /*&& !WouldCauseDoublePath(current, nextDirection, intGrid, path, out var _)*/) {
  184.                     direction = GetNextDirection(current, end);
  185.                 }
  186.  
  187.                 i++;
  188.                 if (i > 100)
  189.                 {
  190.                     // throw new Exception("Infinite loop");
  191.                     return path;
  192.                  
  193.                 }
  194.             }
  195.  
  196.             return path;
  197.         }
  198.  
  199.         private bool WouldCauseDoublePath(Vector3Int current, Vector3Int direction, IntGrid intGrid, List<Vector3Int> path, out Vector3Int perpendicularCurrent)
  200.         {
  201.             // var currentPath = IsPath(current);
  202.             // var nextPath = IsPath(current + direction);
  203.             perpendicularCurrent = Vector3Int.zero;
  204.             for (var j = 0; j < 2; j++) {
  205.                 var factor = j == 0 ? 1 : -1;
  206.                 var perpendicularDirection = new Vector3Int(direction.y * factor, direction.x * factor, 0);
  207.  
  208.                 var currentPerpendicularPath = IsPath(current + perpendicularDirection);
  209.                 var nextPerpendicularPath = IsPath(current + perpendicularDirection + direction);
  210.  
  211.                 if (currentPerpendicularPath && nextPerpendicularPath)
  212.                 {
  213.                     perpendicularCurrent = current + perpendicularDirection;
  214.                     return true;
  215.                 }
  216.             }
  217.            
  218.             return false;
  219.  
  220.             bool IsPath(Vector3Int position)
  221.             {
  222.                 return intGrid.GetTile(position) == PathTile || path.Contains(position);
  223.             }
  224.         }
  225.  
  226.         private Vector3Int GetNextDirection(Vector3Int start, Vector3Int end) {
  227.             var difference = end - start;
  228.             return Mathf.Abs(difference.x) > Mathf.Abs(difference.y) ? new Vector3Int((int) Mathf.Sign(difference.x), 0, 0) : new Vector3Int(0, (int) Mathf.Sign(difference.y), 0);
  229.         }
  230.        
  231.         private List<Vector3Int> ReconstructPath(PathNode endNode)
  232.         {
  233.             var path = new List<Vector3Int>();
  234.             var currentNode = endNode;
  235.            
  236.             while (currentNode != null)
  237.             {
  238.                 path.Add(currentNode.Position);
  239.                 currentNode = currentNode.Parent;
  240.             }
  241.            
  242.             path.Reverse();
  243.             return path;
  244.         }
  245.        
  246.         private class PathNode
  247.         {
  248.             public Vector3Int Position;
  249.             public PathNode Parent;
  250.             public float G; // Cost from start to current
  251.             public float H; // Estimated cost from current to end
  252.             public float F; // Total cost (G + H)
  253.            
  254.             public PathNode(Vector3Int pos, PathNode parent, float g, float h)
  255.             {
  256.                 Position = pos;
  257.                 Parent = parent;
  258.                 G = g;
  259.                 H = h;
  260.                 F = G + H;
  261.             }
  262.            
  263.             public override bool Equals(object obj)
  264.             {
  265.                 if (obj is PathNode other)
  266.                 {
  267.                     return Position.Equals(other.Position);
  268.                 }
  269.                 return false;
  270.             }
  271.            
  272.             public override int GetHashCode()
  273.             {
  274.                 return Position.GetHashCode();
  275.             }
  276.         }
  277.  
  278.         private void OnDrawGizmos()
  279.         {
  280.             if (!ShowGizmos) return;
  281.  
  282.             // Draw edges
  283.             if (edges != null && edges.Count > 0)
  284.             {
  285.                 Gizmos.color = Color.yellow;
  286.                 foreach (var edge in edges)
  287.                 {
  288.                     Vector3 start = new Vector3((int)edge.P.X, (int)edge.P.Y, 0);
  289.                     Vector3 end = new Vector3((int)edge.Q.X, (int)edge.Q.Y, 0);
  290.                     var correction = new Vector3(0.5f, 0.5f);
  291.                     Gizmos.DrawLine(start + correction, end + correction);
  292.                 }
  293.             }
  294.  
  295.             // Draw generated points
  296.             if (generatedPoints != null && generatedPoints.Count > 0)
  297.             {
  298.                 Gizmos.color = Color.cyan;
  299.                 foreach (var point in generatedPoints)
  300.                 {
  301.                     var center = new Vector3(point.x + 0.5f, point.y + 0.5f, 0f);
  302.                     Gizmos.DrawSphere(center, 0.5f);
  303.                 }
  304.             }
  305.  
  306.             // Draw double paths
  307.             if (doublePaths != null && doublePaths.Count > 0)
  308.             {
  309.                 Gizmos.color = new Color(1f, 0f, 0f, 0.8f); // Semi-transparent red
  310.                 foreach (var pos in doublePaths)
  311.                 {
  312.                     var center = new Vector3(pos.x + 1f, pos.y + 1f, 0f);
  313.                     Gizmos.DrawCube(center, new Vector3(2f, 2f, 0.1f));
  314.                 }
  315.             }
  316.         }
  317.  
  318.         protected override List<string> ValidateConfiguration()
  319.         {
  320.             return null;
  321.         }
  322.     }
  323. }
  324.  
Add Comment
Please, Sign In to add comment