6

私は、基本的に「2次元の側面図」に見えるゲーム(シミュレーション)に取り組んでいるアプリケーションのパーリンノイズを調べています。パーリン ノイズがどのように機能するかは完全には理解していませんが、一般的な考え方は理解できます。

コードPerlin Noiseでこの記事を見つけたので、前にそれを与えることにしました。現時点でワールド ジェネをセットアップする方法は、各「チャンク」に 16x16 のタイルがあり、Y >= HEIGHT / 2 の場合にすべてを作成すると述べたところです。 tiles 'solid' else 'air' なのでうまくいきます.. しかし、ご想像のとおり、土地は非常に平らです。そこにパーリン ノイズが入ると思ったので、上記の Web サイトにあるコードを使用しましたが、ノイズをソリッド/エア タイルに変換する方法がわかりません。

あなたが見ることができるように、非常に現実的な地形ではありません ここに画像の説明を入力

地形が以下のようになることをもっと探しています。山となだらかな丘のように見えるはずです)鋭いエッジは気にしません(正方形) ここに画像の説明を入力

タイル配列を反復してノイズを上に変える方法がわかりません

現時点では、タイル配列 (2d) をそのように反復処理していますが、最初の図からわかるように、タイルが固体であるかどうかをランダム化するだけで、なだらかな丘や山は作成されません。

for(int Y = 0;Y < HEIGHT;++Y) {
    for(int X = 0;X < WIDTH;++X) {
        Tile Tile;
        if(noise(X,Y) < 0) {
            Tile.Type = BLOCK;
        } else {
            Tile.Type = Air;
        }

        // Then I push the Tile on to a vector

また、この 16x16 の「チャンク」の右側には、このチャンクと一致させる必要がある別のチャンクがあり、その後の次のチャンクについても同じことが言えます。チャンクは以前と同じであってはなりません。意味がある場合は、別々のチャンクではないように見えるようにするだけです。

どんな助けでも大歓迎です!ありがとうございました

アップデート

パーリン関数をこれに変更し、フレネルが提案したものを実装しました:

    PerlinNoise *test=new PerlinNoise(0.25, 6);    //0.25 is Persistance 6 is Octaves

        float f,h;
        float seed = 804.343;

        for (int X=0; X!=MAP_WIDTH; ++X) {

            f = test->GetNoise((X * ChunkX) * seed);

            h = f * MAP_HEIGHT + (MAP_HEIGHT / 2);

            for (int y=0; y<h; ++y) {
                Tile tempTile;
                tempTile.Tile = TILE_NONE;
                Tiles[X][y] = tempTile;
            }
            for (int y=h; y<MAP_HEIGHT; ++y) {
                Tile tempTile;
                tempTile.TileID = TILE_BLOCK;
                Tiles[X][y] = tempTile;
            }
        }

これを行った後、見た目がずっと良くなりました。X * ChunkXノイズについて、すべてのチャンクが同じではないかのように、次のようになりました。 ここに画像の説明を入力

ご覧のとおり、地形は以前よりも希望どおりになりましたが、実際の地形のようには見えません。滑らかではないため、なだらかなを作成するために全体的な外観を滑らかにするためにできることはありますか?平原

そのノイズ値の下でのタイルの作成を削除したので、範囲が見やすくなりました ここに画像の説明を入力

ご覧のように問題ないように見えますが、疑似乱数のように見えないように、値を「平滑化」するだけで済みます。また、左側に表示されている最初のチャンクが途中で同じ値を持っているのも不思議です。

ありがとう。

4

1 に答える 1

4

島、大陸、池、海があるという点で、結果は良好です。パーリン ノイズは、ランダムでない文字のランダムな地形を生成するのに役立ちます。

基本的に、ノイズ関数の (数学的に) 無限の解像度を、ブロックの非常に限られた解像度と共に、2 つの異なるタイルの離散セットに減らします。それを考えると、あなたの結果は問題ないようです。

さまざまなことが結果を改善する可能性があります。たとえば、タイル グラフィックの間で次のように lerp します。

// Exemplary p-code, fine-tuning required
Color color_at (x, y) {
    Real u = x / width, v = y / height
    Real  f  = min (max(noise(u,v), 0), 1);
    Color c  = water*f + hill*(1-f);
    return c;
}

任意のタイル数に対して lerp 関数を一般化できます。

鋭いエッジの別の可能性は、ボロノイ図 (1)に触発されています。上記と同じ関数がありますが、補間する代わりに、ノイズの値に最も近いタイルを取得します。

Color color_at (x, y) {
    Real u = x / width, v = y / height
    Real  f  = min (max(noise(u,v), 0), 1);
    if (f<0.5) return water;
    else return hill;
}

これは、ピクセル単位で行うことを除いて、あなたのものと同じです。繰り返しますが、これは一般化できます。

適切な設定ができたら、すべてにノイズを使用できます: 植物/樹木の分布、敵の分布、アニメーション (これは 1d ノイズ関数になります) などです。


あなたのコメントと同じように編集してください:

連続した 1D 地形:

古典的な 2D ジャンプ アンド ランのような側面図が必要な場合は、1D ノイズ関数を考えて、0 から画像幅まで反復し、各ストップでノイズ関数のサンプルfを取得し、 fをスクリーン空間に変換します。上のすべてのピクセルは空の一部になり、下のすべてのピクセルはタイルから取得されます。

for (int x=0; x!=width; ++x) {

    // Get noise value:
    f = noise1d (x/width);
    h = f * height + (height/2);  // scale and center at screen-center

    // Select tile:
    Tile *tile;
    if (h < waterLimit) {
        h    = waterLimit;
        tile = waterTile;
    } else {
        tile = terrainTile;
    }

    // Draw vertical line:
    for (int y=0; y<h; ++y)
        setPixel (x, y, skyColor(x,y));
    for (int y=h; y<height; ++y)
        setPixel (x, y, tileColor(x,y, tile));
}

繰り返しますが、模範的な疑似コードです。

現在のセットアップでの完全な 2d レベル:

ノイズ機能は非常に柔軟です。青を減らして緑を増やしたい場合は、定数項を下げてください。つまり、 の代わりにif(h < 0) -> blueを実行してくださいif(h < -0.25) -> blue


1: 私は 3D 地形レンダリングに興味があるので、このアプローチを試したことはありません ( picogen.org )

于 2012-04-19T09:59:42.550 に答える