using System; namespace Assets.Scripts.LevelGeneration { public class PlasmaFractal { public double Roughness { get; private set; } public double BigSize { get; private set; } private readonly Random _random = new Random(); // generates and returns the plasma fractal public double[,] Generate(int width, int height, double roughness) { var points = new double[width + 1, height + 1]; var c1 = _random.NextDouble(); var c2 = _random.NextDouble(); var c3 = _random.NextDouble(); var c4 = _random.NextDouble(); Roughness = roughness; BigSize = width + height; DivideGrid(ref points, 0, 0, width, height, c1, c2, c3, c4); return points; } private void DivideGrid(ref double[,] points, double x, double y, double width, double height, double c1, double c2, double c3, double c4) { var newWidth = Math.Floor(width / 2); var newHeight = Math.Floor(height / 2); if (width > 1 || height > 1) { var middle = ((c1 + c2 + c3 + c4) / 4) + Displace(newWidth + newHeight); var edge1 = ((c1 + c2) / 2); var edge2 = ((c2 + c3) / 2); var edge3 = ((c3 + c4) / 2); var edge4 = ((c4 + c1) / 2); middle = Rectify(middle); edge1 = Rectify(edge1); edge2 = Rectify(edge2); edge3 = Rectify(edge3); edge4 = Rectify(edge4); DivideGrid(ref points, x, y, newWidth, newHeight, c1, edge1, middle, edge4); DivideGrid(ref points, x + newWidth, y, width - newWidth, newHeight, edge1, c2, edge2, middle); DivideGrid(ref points, x + newWidth, y + newHeight, width - newWidth, height - newHeight, middle, edge2, c3, edge3); DivideGrid(ref points, x, y + newHeight, newWidth, height - newHeight, edge4, middle, edge3, c4); } else { var c = (c1 + c2 + c3 + c4) / 4; points[(int)x, (int)y] = c; if (width == 2) { points[(int)x + 1, (int)y] = c; } if (height == 2) { points[(int)x, (int)y + 1] = c; } if (width == 2 && height == 2) { points[(int)x + 1, (int)y + 1] = c; } } } private static double Rectify(double number) { if (number < 0) { number = 0; } else if (number > 1.0) { number = 1.0; } return number; } private double Displace(double smallSize) { var max = smallSize / BigSize * Roughness; return (_random.NextDouble() - 0.5) * max; } } }