Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using DelaunatorSharp;
- using UnityEngine;
- namespace Frigga
- {
- public class HeIsComingGenerator2 : GeneratorBase
- {
- public Vector2Int LevelSize = new Vector2Int(50, 50);
- public int RegionCount = 15;
- public int MinRegionDistance = 4;
- [IntGridTilePicker] public int PathTile;
- [IntGridTilePicker] public int RegionTile;
- [IntGridTilePicker] public int RegionCenterTile;
- private List<IEdge> edges = new List<IEdge>();
- protected override IEnumerable<GeneratorProgress> GenerateLayout(GeneratorResult result)
- {
- edges.Clear();
- var bounds = new BoundsInt(Vector3Int.zero, new Vector3Int(LevelSize.x, LevelSize.y, 1));
- var points = new HashSet<Vector3Int>();
- var i = 0;
- while (points.Count < RegionCount)
- {
- if (i > 1000)
- {
- break;
- }
- i++;
- var center = new Vector3Int(Random.Next(0, LevelSize.x), Random.Next(0, LevelSize.y), 0);
- if (points.Any(p => (p - center).sqrMagnitude < MinRegionDistance * MinRegionDistance))
- {
- continue;
- }
- points.Add(center);
- }
- var delaunator = new Delaunator(points.Select(p => new Point(p.x, p.y)).Cast<IPoint>().ToArray());
- var intGrid = new IntGrid();
- result.IntGrid = intGrid;
- // Initialize the grid with RegionTile
- for (int x = 0; x < LevelSize.x; x++)
- {
- for (int y = 0; y < LevelSize.y; y++)
- {
- intGrid.SetTile(new Vector3Int(x, y, 0), RegionTile);
- }
- }
- // First, place all region centers
- // foreach (var point in points) {
- // intGrid.SetTile(point, RegionCenterTile);
- // }
- // Sort edges by length to process shorter edges first
- // This helps ensure that shorter paths are created first, which can help avoid double paths
- var sortedEdges = new List<IEdge>();
- delaunator.ForEachVoronoiEdge(edge => {
- sortedEdges.Add(edge);
- });
- // Sort edges by length (shorter edges first)
- sortedEdges.Sort((a, b) => {
- float lengthA = Mathf.Sqrt(Mathf.Pow((float)(a.Q.X - a.P.X), 2) + Mathf.Pow((float)(a.Q.Y - a.P.Y), 2));
- float lengthB = Mathf.Sqrt(Mathf.Pow((float)(b.Q.X - b.P.X), 2) + Mathf.Pow((float)(b.Q.Y - b.P.Y), 2));
- return lengthA.CompareTo(lengthB);
- });
- // Process edges in order of length
- foreach (var edge in sortedEdges)
- {
- edges.Add(edge);
- var point1 = new Vector3Int((int) edge.P.X, (int)edge.P.Y, 0);
- var point2 = new Vector3Int((int) edge.Q.X, (int)edge.Q.Y, 0);
- // Find the shortest path between point1 and point2 using A* pathfinding
- var path = FindPath(point1, point2, intGrid);
- // Place Path tiles along the path
- if (path != null)
- {
- foreach (var pathPoint in path)
- {
- intGrid.SetTile(pathPoint, PathTile);
- yield return new GeneratorProgress() {
- IntGrid = intGrid,
- };
- }
- }
- }
- yield break;
- }
- private List<Vector3Int> FindPath(Vector3Int start, Vector3Int end, IntGrid intGrid)
- {
- // A* pathfinding implementation
- var openSet = new List<PathNode>();
- var closedSet = new HashSet<PathNode>();
- var pathNodes = new Dictionary<Vector3Int, PathNode>();
- // Create start node
- var startNode = new PathNode(start, null, 0, GetHeuristic(start, end));
- openSet.Add(startNode);
- pathNodes[start] = startNode;
- while (openSet.Count > 0)
- {
- // Get node with lowest F cost
- openSet.Sort((a, b) => a.F.CompareTo(b.F));
- var currentNode = openSet[0];
- // If we reached the end, reconstruct and return the path
- if (currentNode.Position == end)
- {
- return ReconstructPath(currentNode);
- }
- openSet.RemoveAt(0);
- closedSet.Add(currentNode);
- // Check neighbors
- foreach (var neighbor in GetNeighbors(currentNode.Position))
- {
- // Skip if out of bounds
- if (neighbor.x < 0 || neighbor.x >= LevelSize.x ||
- neighbor.y < 0 || neighbor.y >= LevelSize.y)
- {
- continue;
- }
- // Calculate G cost (distance from start)
- // If the neighbor is already a path tile, give it a lower cost
- float tileCost = 1.2f;
- if (intGrid.GetTile(neighbor) == PathTile)
- {
- // Prefer walking on existing paths by giving them a lower cost
- tileCost = 1f;
- Debug.Log($"Walking on existing path at {neighbor}");
- }
- float newG = currentNode.G + tileCost;
- // Get or create neighbor node
- PathNode neighborNode;
- if (!pathNodes.TryGetValue(neighbor, out neighborNode))
- {
- neighborNode = new PathNode(neighbor, currentNode, newG, GetHeuristic(neighbor, end));
- pathNodes[neighbor] = neighborNode;
- openSet.Add(neighborNode);
- }
- else if (newG < neighborNode.G)
- {
- // This path to neighbor is better than any previous one
- neighborNode.Parent = currentNode;
- neighborNode.G = newG;
- neighborNode.F = neighborNode.G + neighborNode.H;
- }
- else if (closedSet.Contains(neighborNode))
- {
- // Skip if already in closed set
- continue;
- }
- }
- }
- // No path found
- return null;
- }
- private List<Vector3Int> ReconstructPath(PathNode endNode)
- {
- var path = new List<Vector3Int>();
- var currentNode = endNode;
- while (currentNode != null)
- {
- path.Add(currentNode.Position);
- currentNode = currentNode.Parent;
- }
- path.Reverse();
- return path;
- }
- private float GetHeuristic(Vector3Int a, Vector3Int b)
- {
- // Manhattan distance heuristic
- return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
- }
- private List<Vector3Int> GetNeighbors(Vector3Int pos)
- {
- // Return the 4 adjacent neighbors (up, right, down, left)
- return new List<Vector3Int>
- {
- new Vector3Int(pos.x, pos.y + 1, 0), // Up
- new Vector3Int(pos.x + 1, pos.y, 0), // Right
- new Vector3Int(pos.x, pos.y - 1, 0), // Down
- new Vector3Int(pos.x - 1, pos.y, 0) // Left
- };
- }
- private class PathNode
- {
- public Vector3Int Position;
- public PathNode Parent;
- public float G; // Cost from start to current
- public float H; // Estimated cost from current to end
- public float F; // Total cost (G + H)
- public PathNode(Vector3Int pos, PathNode parent, float g, float h)
- {
- Position = pos;
- Parent = parent;
- G = g;
- H = h;
- F = G + H;
- }
- public override bool Equals(object obj)
- {
- if (obj is PathNode other)
- {
- return Position.Equals(other.Position);
- }
- return false;
- }
- public override int GetHashCode()
- {
- return Position.GetHashCode();
- }
- }
- private void OnDrawGizmos()
- {
- if (!ShowGizmos || edges == null || edges.Count == 0) return;
- Gizmos.color = Color.yellow;
- foreach (var edge in edges)
- {
- Vector3 start = new Vector3((float)edge.P.X, (float)edge.P.Y, 0);
- Vector3 end = new Vector3((float)edge.Q.X, (float)edge.Q.Y, 0);
- Gizmos.DrawLine(start, end);
- }
- }
- protected override List<string> ValidateConfiguration()
- {
- return null;
- }
- }
- }
Add Comment
Please, Sign In to add comment