PuzzleGame/PuzzleGameProject/Assets/Scripts/DungeonGenerator/EvenDisperser.cs

84 lines
No EOL
2.9 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine.UIElements;
using Random = System.Random;
namespace DungeonGenerator
{
public class EvenDisperser
{
private List<Point> _samples = new List<Point>(){new Point(1,1)};
private List<Point> _availablePoints;
public EvenDisperser(int xLength, int yLength, List<Point> excludedPoints = null)
{
_availablePoints = GenerateAvailablePoints(xLength, yLength, excludedPoints ?? new List<Point>());
}
private List<Point> GenerateAvailablePoints(int xLength, int yLength, List<Point> excludedPoints)
{
List<Point> availablePoints = new List<Point>();
for (var x = 0; x < xLength; x++)
{
for (var y = 0; y < yLength; y++)
{
if (!excludedPoints.Contains(new Point(x, y)))
{
availablePoints.Add(new Point(x, y));
}
}
}
return availablePoints;
}
// Can place point so that the x lengt hand y length go out of bounds to the right and down.
public Point GetPoint(int xLength, int yLength)
{
int numCandidates = 50; // Increasing improves results but greatly effects performance.
Random rnd = new Random();
int randomIndex = rnd.Next(0, _availablePoints.Count);
Point bestCandidate = new Point(Int32.MaxValue, Int32.MaxValue);
int bestDistance = 0;
for (var i = 0; i < numCandidates; i++)
{
var candidate = _availablePoints[randomIndex];
var distance = candidate.ManhattanDistance(FindClosest(_samples, candidate));
if (distance > bestDistance)
{
RemoveArea(candidate, xLength, yLength, _availablePoints);
bestCandidate = candidate;
bestDistance = distance;
}
}
_samples.Add(bestCandidate);
return bestCandidate;
}
private Point FindClosest(List<Point> options, Point reference)
{
Point closest = options[0];
foreach (var option in options)
{
if (reference.ManhattanDistance(option) < reference.ManhattanDistance(closest))
{
closest = option;
}
}
return closest;
}
private void RemoveArea(Point topLeft, int xLength, int yLength, List<Point> availablePoints)
{
for (var x = topLeft.X; x < topLeft.X + xLength; x++)
{
for (var y = topLeft.Y; y < topLeft.Y + yLength; y++)
{
availablePoints.Remove(new Point(x, y));
}
}
}
}
}