Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- 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;
- public int BorderSize = 5;
- [IntGridTilePicker] public int PathTile;
- [IntGridTilePicker] public int RegionTile;
- [IntGridTilePicker] public int RegionCenterTile;
- private List<IEdge> edges = new List<IEdge>();
- private List<Vector3Int> doublePaths = new List<Vector3Int>();
- private HashSet<Vector3Int> generatedPoints = new HashSet<Vector3Int>();
- protected override IEnumerable<GeneratorProgress> GenerateLayout(GeneratorResult result)
- {
- ShowGizmos = true;
- edges.Clear();
- doublePaths.Clear();
- generatedPoints.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 - 2 * BorderSize) + BorderSize, Random.Next(0, LevelSize.y - 2 * BorderSize) + BorderSize, 0);
- if (points.Any(p => (p - center).sqrMagnitude < MinRegionDistance * MinRegionDistance))
- {
- continue;
- }
- points.Add(center);
- generatedPoints.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;
- for (int j = 0; j < 100; j++)
- {
- yield return new GeneratorProgress() {
- 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 point coordinates
- var sortedEdges = new List<IEdge>();
- delaunator.ForEachVoronoiEdge(edge => {
- sortedEdges.Add(edge);
- });
- // Sort edges by point coordinates from top-left to bottom-right
- sortedEdges.Sort((a, b) => {
- // First compare P points by Y in descending order (highest Y first)
- int pCompare = b.P.Y.CompareTo(a.P.Y);
- if (pCompare != 0) return pCompare;
- // Then by X in ascending order (left to right)
- pCompare = b.P.X.CompareTo(a.P.X);
- if (pCompare != 0) return pCompare;
- // If P points are equal, compare Q points
- int qCompare = b.Q.Y.CompareTo(a.Q.Y);
- if (qCompare != 0) return qCompare;
- return a.Q.X.CompareTo(b.Q.X);
- });
- // Process edges in order of length
- foreach (var edge in sortedEdges)
- {
- var point = new Vector3Int((int) edge.P.X, (int)edge.P.Y, 0);
- intGrid.SetTile(point, PathTile);
- }
- edges.AddRange(sortedEdges);
- // Process edges in order of length
- var p = 0;
- foreach (var edge in sortedEdges)
- {
- p++;
- 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 = FindPath3(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,
- // };
- }
- if (p % 3 == 0)
- {
- yield return new GeneratorProgress() {
- IntGrid = intGrid,
- };
- }
- }
- }
- // After all paths are generated, find double paths
- // doublePaths = FindDoublePaths(intGrid);
- // ShowGizmos = false;
- yield break;
- }
- private List<Vector3Int> FindPath3(Vector3Int start, Vector3Int end, IntGrid intGrid) {
- var current = start;
- var path = new List<Vector3Int>
- {
- current
- };
- var i = 0;
- var direction = GetNextDirection(start, end);
- while (true) {
- if (current == end) {
- break;
- }
- if (current + GetNextDirection(current, end) == end)
- {
- path.Add(end);
- break;
- }
- if (WouldCauseDoublePath(current, direction, intGrid, path, out var perpendicularCurrent))
- {
- current = perpendicularCurrent;
- }
- var next = current + direction;
- current = next;
- path.Add(current);
- var currentDifference = end - current;
- var mult = currentDifference.x * direction.x + currentDifference.y * direction.y;
- var nextDirection = GetNextDirection(current, end);
- if (mult == 0 /*&& !WouldCauseDoublePath(current, nextDirection, intGrid, path, out var _)*/) {
- direction = GetNextDirection(current, end);
- }
- i++;
- if (i > 100)
- {
- // throw new Exception("Infinite loop");
- return path;
- }
- }
- return path;
- }
- private bool WouldCauseDoublePath(Vector3Int current, Vector3Int direction, IntGrid intGrid, List<Vector3Int> path, out Vector3Int perpendicularCurrent)
- {
- // var currentPath = IsPath(current);
- // var nextPath = IsPath(current + direction);
- perpendicularCurrent = Vector3Int.zero;
- for (var j = 0; j < 2; j++) {
- var factor = j == 0 ? 1 : -1;
- var perpendicularDirection = new Vector3Int(direction.y * factor, direction.x * factor, 0);
- var currentPerpendicularPath = IsPath(current + perpendicularDirection);
- var nextPerpendicularPath = IsPath(current + perpendicularDirection + direction);
- if (currentPerpendicularPath && nextPerpendicularPath)
- {
- perpendicularCurrent = current + perpendicularDirection;
- return true;
- }
- }
- return false;
- bool IsPath(Vector3Int position)
- {
- return intGrid.GetTile(position) == PathTile || path.Contains(position);
- }
- }
- private Vector3Int GetNextDirection(Vector3Int start, Vector3Int end) {
- var difference = end - start;
- 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);
- }
- 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 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) return;
- // Draw edges
- if (edges != null && edges.Count > 0)
- {
- Gizmos.color = Color.yellow;
- foreach (var edge in edges)
- {
- Vector3 start = new Vector3((int)edge.P.X, (int)edge.P.Y, 0);
- Vector3 end = new Vector3((int)edge.Q.X, (int)edge.Q.Y, 0);
- var correction = new Vector3(0.5f, 0.5f);
- Gizmos.DrawLine(start + correction, end + correction);
- }
- }
- // Draw generated points
- if (generatedPoints != null && generatedPoints.Count > 0)
- {
- Gizmos.color = Color.cyan;
- foreach (var point in generatedPoints)
- {
- var center = new Vector3(point.x + 0.5f, point.y + 0.5f, 0f);
- Gizmos.DrawSphere(center, 0.5f);
- }
- }
- // Draw double paths
- if (doublePaths != null && doublePaths.Count > 0)
- {
- Gizmos.color = new Color(1f, 0f, 0f, 0.8f); // Semi-transparent red
- foreach (var pos in doublePaths)
- {
- var center = new Vector3(pos.x + 1f, pos.y + 1f, 0f);
- Gizmos.DrawCube(center, new Vector3(2f, 2f, 0.1f));
- }
- }
- }
- protected override List<string> ValidateConfiguration()
- {
- return null;
- }
- }
- }
Add Comment
Please, Sign In to add comment