タイルマップの生成


25

私はタイルベースのゲームをプログラミングしており、いくつかの基本的なタイル(草、汚れなど)を持っていますが、タイルが本当にランダムに選択された場合、草/汚れでなければなりません、私はこれを取得します:

ゲーム内画像

私はこれがなぜ起こっているのか理解していますが、私が望むのは、草や土のランダムな連続領域を作成することです。次のような、より意味のあるもの:

望ましい結果


1
提案された回答に加えて、独自のセルラーオートマトンエンジンを作成して、そのようなマップを生成できます。オートマトンのルールを変更すると、非常に異なる動作を生成し、非常に異なるタイプのマップを作成できます。たとえば、Lifeに似た2Dオートマトンgievnは、フラッディングルールが「海と島」になり(上記の写真のように)、1267/17のようなルールが美しいラベリンスにつながる可能性があります。
Manu343726 14年

回答:


19

あなたができることは、このようなボロノイマップをランダムに生成することです:

  1. ランダムに選んでcenter points(黒い点を参照)、それらが草か土かをランダムに決定します。
  2. 次に、すべてのタイルについて、それcenter pointが土または草に最も近いかどうかを確認します。
  3. できた!

以前に行ったことが各タイル(ノイズ)の「コインを弾く」場合、Voronoiダイアグラムを生成すると、より良い結果が得られます。

あなたは、分割することによってこれを改善できるcenter pointsにしislandsていることのアルゴリズムで:

  1. の小さなグループを選択しcenters points、それらをとして指定しますleaders
  2. ターンごとにランダムに隣接する未決定の中心点を繰り返し追加します。
  3. できた!

ここに画像の説明を入力してください


1
ありがとう、しかしそれは非常に難しい解決策のようです。
ビルダ14年

2
これはそれほど難しい解決策ではありません。最初にランダムに選択しcenter pointsます。次に、それらが草か土かを決めます。次に、配列をループ処理し、各タイルがダートポイントまたはグラスポイントに最も近いかどうかを判断します。おそらく、どの部分が難しいか教えてください。
wolfdawn 14年

距離を測定します。とにかく、私はあなたに知らせようとします。
ビルダ14年

わかりましたので、いくつかのポイントを生成しました。(dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png)と、このようにルックスを生成するための私のクラス全体そう:dropbox.com/s/pxhn902xqrhtli4/gen.java。しかし、まだ機能しません。
ビルダ14年

3
@ViliXリンクが壊れています
Artur Czajka 14

24

通常、ハイトマップの生成に使用されるperlinノイズを使用できます。 ゲームのパーリンノイズ

次に、高さをアドバイザとして使用して、マップのある領域で草/汚れが発生する可能性がどれだけ高いかを確認できます。

例(0〜256のパーリンノイズ値):値が200を超える場合、草が置かれる可能性は80%(汚れ20%)です。値が100から200の間の場合、草が置かれる可能性は50%(汚れも50%)です。値が100未満の場合、草が配置される可能性は20%(汚れ80%)です。


さて、float(0-1の確率)のarray [] []があり、それを使用して確率でタイルを生成できるとしましょう。しかし、この確率配列をどのように埋めるのでしょうか?配列は(たとえば)400x200ですが、確率値を入力するにはどうすればよいですか?
ビルダ14年

彼は(コインフリップのようなホワイトノイズの代わりに)パーリンノイズでそれを埋めることを提案しています。
wolfdawn 14年

はい、しかしどうすればそれを達成できますか?
ビルダ14年

私が投稿したリンクは、この質問をクリアする可能性があります。最初にノイズを生成してから、このノイズを平滑化します。結果は、タイルマップのさらなる生成に使用できる2次元配列になります。リンク
クリッツ14年

それは本当に良い答えですが、あなたが提示した結果に似た結果を得ることはめったにありません。
wolfdawn 14年

8

ここに画像の説明を入力してください

http://gamedevelopment.tutsplus.com/tutorials/generate-random-cave-levels-using-cellular-automata--gamedev-9664

ここに、セルオートマトンのメソッドの私のバージョンがあります。まず、グリッドをランダムに塗りつぶしてから、このオートマトンのルールを数回実行します

  • 生きている細胞の隣人が2人未満の場合、死にます。
  • 生きているセルに2つまたは3つの生きている隣人がいる場合、生きたままになります。
  • 生きている細胞に3つ以上の生きている隣人がいる場合、死にます。
  • 死んだ細胞にちょうど3人の生きている隣人がいる場合、生きた状態になります。

そして、それは洞窟のように見えることになります

このコードを使用して、インデックスを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;
}

2
コードの動作、リンク、コード自体のサンプルを投稿するのではなく、コードの動作を説明してください。答えは自己完結型である必要があります。リンクが壊れても、それはまだ使用可能です。
ファンドモニカの訴訟

6

マップ上のポイントを選択します。希望のタイルタイプを40などの基本値で配置します。新しく希望するタイルを配置した場所を追跡します。リストに開始点を追加します。

このリストの各ポイントについて、あなたはすべての隣人を訪問します。十分なパワーが残っている間(40から開始)、目的のタイルを追加し、訪問するリストに追加します。あなたが決めた新しいタイルの電力を減らします。最も簡単な=ランダムな低下。リストからタイルにアクセスしたら、削除します。訪問していないが作成したタイルにアクセスして、最初からやり直します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.