島の削除
私は自分のゲームでこの種のことを以前にやったことがあります。外側の島を取り除くためのプロセスは基本的に次のとおりでした。
- 最初に、マップの中心が常にメインランドに属し、各ピクセルが「土地」または「水」(つまり異なる色)で始まることを保証する必要があります。
- 次に、マップの中心から始まり、「土地」タイル全体に広がる4方向の塗りつぶしを行います。この塗りつぶしがアクセスしたすべてのピクセルを、「MainLand」などの異なるタイプとしてマークします。
- 最後に、マップ全体を調べて、残りの「ランド」ピクセルを「水」に変換して、他の島を取り除きます。
湖の削除
島内の穴(または湖)を取り除くことに関しては、同様のプロセスを行いますが、マップの隅から開始し、代わりに「水」タイルに広がります。これにより、「海」を他の水タイルと区別することができ、以前の島を取り除くようにそれらを取り除くことができます。
例
私はどこかにここに持っていることを塗りつぶしの私の実装を掘り起こしてみましょう(私は確信してありますよので、免責事項、私は、効率を気にしませんでした多くのそれを実装するためのより効率的な方法で):
private void GenerateSea()
{
// Initialize visited tiles list
visited.Clear();
// Start generating sea from the four corners
GenerateSeaRecursive(new Point(0, 0));
GenerateSeaRecursive(new Point(size.Width - 1, 0));
GenerateSeaRecursive(new Point(0, size.Height - 1));
GenerateSeaRecursive(new Point(size.Width - 1, size.Height - 1));
}
private void GenerateSeaRecursive(Point point)
{
// End recursion if point is outside bounds
if (!WithinBounds(point)) return;
// End recursion if the current spot is a land
if (tiles[point.X, point.Y].Land) return;
// End recursion if this spot has already been visited
if (visited.Contains(point)) return;
// Add point to visited points list
visited.Add(point);
// Calculate neighboring tiles coordinates
Point right = new Point(point.X + 1, point.Y);
Point left = new Point(point.X - 1, point.Y);
Point up = new Point(point.X, point.Y - 1);
Point down = new Point(point.X, point.Y + 1);
// Mark neighbouring tiles as Sea if they're not Land
if (WithinBounds(right) && tiles[right.X, right.Y].Empty)
tiles[right.X, right.Y].Sea = true;
if (WithinBounds(left) && tiles[left.X, left.Y].Empty)
tiles[left.X, left.Y].Sea = true;
if (WithinBounds(up) && tiles[up.X, up.Y].Empty)
tiles[up.X, up.Y].Sea = true;
if (WithinBounds(down) && tiles[down.X, down.Y].Empty)
tiles[down.X, down.Y].Sea = true;
// Call the function recursively for the neighboring tiles
GenerateSeaRecursive(right);
GenerateSeaRecursive(left);
GenerateSeaRecursive(up);
GenerateSeaRecursive(down);
}
ゲームで湖を取り除くための最初のステップとしてこれを使用しました。それを呼び出した後、私がしなければならないことは次のようなものでした:
private void RemoveLakes()
{
// Now that sea is generated, any empty tile should be removed
for (int j = 0; j != size.Height; j++)
for (int i = 0; i != size.Width; i++)
if (tiles[i, j].Empty) tiles[i, j].Land = true;
}
編集
コメントに基づいていくつかの追加情報を追加します。サーチスペースが大きすぎる場合、アルゴリズムの再帰バージョンを使用するときにスタックオーバーフローが発生する可能性があります。ここにスタックオーバーフローのリンク(pun意図:-))をアルゴリズムの非再帰バージョンに使用し、Stack<T>
代わりに(私の答えに一致するC#でも使用しますが、他の言語に簡単に適応できる必要があります)リンクも)。