私はタイルベースのゲームをプログラミングしており、いくつかの基本的なタイル(草、汚れなど)を持っていますが、タイルが本当にランダムに選択された場合、草/汚れでなければなりません、私はこれを取得します:
私はこれがなぜ起こっているのか理解していますが、私が望むのは、草や土のランダムな連続領域を作成することです。次のような、より意味のあるもの:
私はタイルベースのゲームをプログラミングしており、いくつかの基本的なタイル(草、汚れなど)を持っていますが、タイルが本当にランダムに選択された場合、草/汚れでなければなりません、私はこれを取得します:
私はこれがなぜ起こっているのか理解していますが、私が望むのは、草や土のランダムな連続領域を作成することです。次のような、より意味のあるもの:
回答:
あなたができることは、このようなボロノイマップをランダムに生成することです:
center points
(黒い点を参照)、それらが草か土かをランダムに決定します。center point
が土または草に最も近いかどうかを確認します。以前に行ったことが各タイル(ノイズ)の「コインを弾く」場合、Voronoiダイアグラムを生成すると、より良い結果が得られます。
あなたは、分割することによってこれを改善できるcenter points
にしislands
ていることのアルゴリズムで:
centers points
、それらをとして指定しますleaders
。center points
ます。次に、それらが草か土かを決めます。次に、配列をループ処理し、各タイルがダートポイントまたはグラスポイントに最も近いかどうかを判断します。おそらく、どの部分が難しいか教えてください。
通常、ハイトマップの生成に使用されるperlinノイズを使用できます。 ゲームのパーリンノイズ
次に、高さをアドバイザとして使用して、マップのある領域で草/汚れが発生する可能性がどれだけ高いかを確認できます。
例(0〜256のパーリンノイズ値):値が200を超える場合、草が置かれる可能性は80%(汚れ20%)です。値が100から200の間の場合、草が置かれる可能性は50%(汚れも50%)です。値が100未満の場合、草が配置される可能性は20%(汚れ80%)です。
ここに、セルオートマトンのメソッドの私のバージョンがあります。まず、グリッドをランダムに塗りつぶしてから、このオートマトンのルールを数回実行します
そして、それは洞窟のように見えることになります
このコードを使用して、インデックスをx&y位置に変換して戻すことができます
public int TileIndex(int x, int y)
{
return y * Generator.Instance.Width + x;
}
public Vector2 TilePosition(int index)
{
float y = index / Generator.Instance.Width;
float x = index - Generator.Instance.Width * y;
return new Vector2(x, y);
}
私はこのリストを多くのものに使用しているので、ブールのリストを返すだけです:洞窟、木、花、草、霧、水
private int GetAdjacentCount(List<bool> list, Vector2 p)
{
int count = 0;
for (int y = -1; y <= 1; y++)
{
for (int x = -1; x <= 1; x++)
{
if (!((x == 0) && (y == 0)))
{
Vector2 point = new Vector2(p.x + x, p.y + y);
if (PathFinder.Instance.InsideMap(point))
{
int index = PathFinder.Instance.TileIndex(point);
if (list[index])
{
count++;
}
}
else
{
count++;
}
}
}
}
return count;
}
private List<bool> GetCellularList(int steps, float chance, int birth, int death)
{
int count = _width * _height;
List<bool> list = Enumerable.Repeat(false, count).ToList();
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
Vector2 p = new Vector2(x, y);
int index = PathFinder.Instance.TileIndex(p);
list[index] = Utility.RandomPercent(chance);
}
}
for (int i = 0; i < steps; i++)
{
var temp = Enumerable.Repeat(false, count).ToList();
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
Vector2 p = new Vector2(x, y);
int index = PathFinder.Instance.TileIndex(p);
if (index == -1) Debug.Log(index);
int adjacent = GetAdjacentCount(list, p);
bool set = list[index];
if (set)
{
if (adjacent < death)
set = false;
}
else
{
if (adjacent > birth)
set = true;
}
temp[index] = set;
}
}
list = temp;
}
if ((steps > 0) && Utility.RandomBool())
RemoveSmall(list);
return list;
}