我使用Haxe的中点位移算法遇到了困难。我按照here找到的步骤实现了这一点。
首先,创建一个表示空白地图的数组。首先,给四个角一个随机值。
在此方块中,通过平均四个角并添加一个小“错误”或随机值来创建中间点。然后通过平均每个中间的两个角来创建4个边的中点。完成这些步骤后,您将获得4个方格。重复以下步骤:
通过对四个角进行平均并添加一个小“错误”来创建中间点。
- 醇>
通过对每个点之间的两个角进行平均来创建每一边的中点。
每次迭代,使RNG的范围变小。这样原来的几个点可以有很大的变化,但后面的点只能进行微小的调整。这样可以确保图像中的细节数量。
这是我编写的用于执行这些步骤然后规范化值的函数:
public static function generateFloatMatrix(Columns:Int, Rows:Int, RangeModifier:Float = 0.65):Array<Array<Float>>
{
//Blank 2D Array
var matrix:Array<Array<Float>> = InitFloatMatrix(Columns, Rows);
var range:Float = 1;
//Set Values for all four corners
matrix[0][0] = Math.random() * range;
matrix[Rows-1][0] = Math.random() * range;
matrix[0][Columns-1] = Math.random() * range;
matrix[Rows - 1][Columns - 1] = Math.random() * range;
//Calculates the amount of segments in base 2
var length = Math.sqrt((Columns * Columns) + (Rows * Rows));
var power:Int = Std.int(Math.pow(2, Math.ceil(Math.log(length) / Math.log(2))));
//Stores largest calculated value for normalization
var max:Float = 0;
var width:Int = Std.int(Columns);
var height:Int = Std.int(Rows);
var i:Int = 1;
while (i < power)
{
//Segment Size
width = Std.int(Columns / i);
height = Std.int(Rows / i);
for (y in 0...i)
{
for (x in 0...i)
{
//Top Left Coordinates per segment
var left = width * x;
var top = height * y;
//Find Midpoint
var xMid = Math.ceil(left + (width / 2));
var yMid = Math.ceil(top + (height / 2));
//Make sure right and bottom do not go out of bounds
var right:Int = (left + width < Columns ? left + width : Columns - 1);
var bottom:Int = (top + height < Rows ? top + height : Rows - 1);
//Sets midpoint value to average of all four corners.
matrix[yMid][xMid] =
(matrix[top][left] +
matrix[bottom][left] +
matrix[bottom][right] +
matrix[top][right]) / 4;
//trace ("Top: " + top + " - Left: " + left + " - Bottom: " + bottom + " - Right: " + right);
//Adds random value to midpoint
matrix[yMid][xMid] += Math.random() * range;
//Set side values to average of adjacent corners
matrix[top][xMid] = (matrix[top][left] + matrix[top][right]) / 2;
matrix[bottom][xMid] = (matrix[bottom][left] + matrix[bottom][right]) / 2;
matrix[yMid][left] = (matrix[top][left] + matrix[bottom][left]) / 2;
matrix[yMid][right] = (matrix[top][right] + matrix[bottom][right]) / 2;
max = Math.max(matrix[top][left], max);
}
}
//Reduces range
range *= RangeModifier;
i *= 2;
}
//Normalizes all values in matrix
for (y in 0...Rows)
{
for (x in 0...Columns)
{
matrix[y][x] /= max;
}
}
return matrix;
}
如果我使用每个值将每个像素渲染到指定的坐标,则会生成这些图像。所有呈现为白色的像素的值都为0,黑色的值为1。
答案 0 :(得分:1)
您的问题是,如果您的地图尺寸不是2的幂,那么您不必通过计算来点击已填充的像素。例如,如果您的地图宽度为30个单位,则第一遍中的网格宽度为15,第二遍中的网格宽度为7,其中计算基于尚未触及的单位14。
解决方案是使用浮点运算进行所有计算,直到确定单位索引,当然必须是整数:
while (i < power)
{
var width:Float = Columns / i; // Floating-point division
var height:Float = Rows / i;
for (y in 0...i)
{
for (x in 0...i)
{
var left:Int = Math.floor(width * x);
var top:Int = Math.floor(height * y);
var xMid:Int = Math.floor(width * (x + 0.5));
var yMid:Int = Math.floor(height * (y + 0.5));
var right:Int = Math.floor(width * (x +1));
var bottom:Int = Math.floor(height * (y + 1));
//Make sure right and bottom do not go out of bounds
if (right > Columns - 1) right = Columns - 1;
if (bottom > Rows - 1) bottom = Rows - 1;
// Do offset and interpolation stuff
}
}
}
这应该给你一个随机的地图,图纸效果和所有。
(警告:我对Haxe并不熟悉,但已经在Javascript中对此进行了测试,其中没有整数类型。我已经使用了Math-floor
,你在哪里&# 39;我想以Haxe的方式去做。)
最后,我认为你做了太多的传球。我将功率基于两个维度的最大值而不是对角线。您也可以跳过wthe width接近1的最后一步。