[解決済み] Perlin Noiseを用いた2D地形生成(タイルベース)
質問
基本的に「2次元のサイドビュー」的なゲーム(シミュレーション)に取り組んでいるアプリケーションのために、パーリンノイズについて調べています。私はperlin noiseがどのように機能するか完全に理解しているわけではありませんが、一般的なアイデアは持っています。
この記事でコードを見つけました。 パーリンノイズ しかし、土地は想像通りとても平らです。そこで、Perlinのノイズが発生すると考え、上記のサイトにあるコードを使用しましたが、ノイズを固体/空気タイルに変換する方法がよくわかりません。
ご覧の通り、あまりリアルな地形ではありません。
山や丘のような地形にしたいです。
タイル配列を反復して、ノイズを上記に変える方法がよくわかりません。
現在、私はタイル配列(2次元)をこのように反復していますが、最初の画像からわかるように、それはタイルが固体であるかどうかをランダムにするだけで、なだらかな丘や山を作ることはありません。
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の「チャンク」の右側には別のチャンクがあり、このチャンクと一致させる必要があり、その次のチャンクも同様です。チャンクは前と同じであるべきではなく、別々のチャンクでないように見せかけるだけです。
どんなことでもご相談ください。ありがとうございました。
アップデイト
私は、Perlinの関数を、以下のように変更しました。 これ とphresnelが提案したものを実装しました。
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
をそれぞれ
ノイズ
そうしないと、すべてのチャンクが同じになってしまうので、今は次のようになっています。
ご覧のように、地形は以前よりも私の望むものになっていますが、まだあまり似ていないようです。 リアル 地形があまり滑らかでないのですが、全体的な見た目を滑らかにするために、何かできることはありますか? なだらかな丘 と 平野
そのノイズ値の下にあるタイルの作成を削除して、そのノイズ値が見やすくなるようにしました。 範囲
ご覧の通り、見た目は問題ありません。ただ、擬似乱数値のように見えないように、値を「平滑化」する必要があります。また、左側にある最初のチャンクがずっと同じ値であることも不思議です。
ありがとうございます。
解決方法は?
あなたの結果は、島、大陸、池、海があるという点では問題ないでしょう。パーリンノイズは、非ランダムな地形を生成するのに役立ちます。
あなたは基本的に、ノイズ関数の(数学的に)無限の解像度を、ブロックの非常に限定された解像度とともに、たった2種類のタイルの離散集合に縮小しています。そう考えると、あなたの結果は問題ないように思えます。
違うことをすると、結果が良くなるかもしれません。例えば、タイルグラフィックの間にラープを入れるなどです。
// 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関数を任意のtile-countに一般化することができます。
シャープエッジのもう一つの可能性は、次のようなものです。 ボロノイ図 (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-noise関数になります)など、あらゆるものにノイズを使うことができます。
コメントについて編集します。
連続した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-levelsをフルに活用する。
ノイズ関数は非常に柔軟です。もし青を減らして緑を増やしたいなら、定数項を下げればいいだけです。
if(h < 0) -> blue
を実行します。
if(h < -0.25) -> blue
.
1: 私は3D地形レンダリングに興味があるので、この方法は試したことがありません( picogen.org )
関連
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない