LoginSignup
262
121

More than 3 years have passed since last update.

バイオームのプロシージャル生成 - パーリンノイズアルゴリズム

Last updated at Posted at 2019-06-30

🌏母なる大地を創造する🌏

PN512

今回はパーリンノイズ法を用いたバイオーム生成について簡単に解説します。

🌏パーリンノイズとは🌏

"パーリンノイズ"は地形生成に適した"ノイズアルゴリズム"です。
あの超有名なゲームである"マインクラフト"でも使われています。

また、マインクラフトのワールドでは バイオームを生成 しており
様々な生物群系 を取り入れています。

mcp
ゲームで使用されるパーリンノイズの例

🌏前回紹介した生成の応用🌏

[DTL]地形生成(パーリンノイズ法)🌏
で紹介したパーリンノイズ法による地形自動生成を用いてバイオームを作っていきます。

pib pii

🌏バイオームを作るために必要なモノ🌏

バイオーム生成には
"年平均気温"と"年降水量"に近似した2つの変数が必要です。

PN512
実世界のバイオームの大まかな区分はこんな感じ。

🌏バイオーム変数を定義🌏

main関数
 using shape_t = std::uint_fast8_t;
 constexpr std::size_t size_x{ 512 };
 constexpr std::size_t size_y{ 512 };
 //温度
 std::unique_ptr<float[][size_x] > temperature(new(std::nothrow) float[size_y][size_x]);
 dtl::shape::PerlinIsland<float>(6.0, 8, -20.0f, 60.0f).draw(temperature, size_x, size_y);
 //降水量
 std::unique_ptr<std::uint_fast16_t[][size_x] > amount_of_rainfall(new(std::nothrow) std::uint_fast16_t[size_y][size_x]);
 dtl::shape::PerlinIsland<std::uint_fast16_t>(6.0, 8, 0, 4500).draw(amount_of_rainfall, size_x, size_y);
 //標高
 std::unique_ptr<shape_t[][size_x] > elevation(new(std::nothrow) shape_t[size_y][size_x]);
 dtl::shape::PerlinIsland<shape_t>(6.0, 8, 200).draw(elevation, size_x, size_y);
 //バイオーム
 std::unique_ptr<shape_t[][size_x] > biome(new(std::nothrow) shape_t[size_y][size_x]);

PN512
"年平均気温"と"年降水量"に近似した2つの変数を作成しました。
処理がしやすいように単純にしています。
この2つの変数を用いてバイオーム分けしていきます。

ここで、標高といったまた別の変数が定義されていますが
これは 陸地と海を区別するため に用います。

🌏バイオームを生成🌏

main関数
 for (std::size_t row{}; row < size_y; ++row)
  for (std::size_t col{}; col < size_x; ++col) {

   //海
   if (elevation[row][col] < 90) biome[row][col] = 0;
   //ツンドラ
   else if (temperature[row][col] < -5.0f) biome[row][col] = 1;
   //砂漠
   else if (amount_of_rainfall[row][col] < 500) biome[row][col] = 2;
   else if (amount_of_rainfall[row][col] < 1500) {
    //ステップ
    if (temperature[row][col] < 20.0f) biome[row][col] = 3;
    //サバンナ
    else biome[row][col] = 4;
   }
   //針葉樹林
   else if (temperature[row][col] < 3.0f) biome[row][col] = 5;
   //夏緑樹林
   else if (temperature[row][col] < 12.0f) biome[row][col] = 6;
   //照葉樹林
   else if (temperature[row][col] < 20.0f) biome[row][col] = 7;
   //雨緑樹林
   else if (amount_of_rainfall[row][col] < 2500) biome[row][col] = 8;
   //亜熱帯多雨林
   else if (temperature[row][col] < 24.0f) biome[row][col] = 9;
   //熱帯多雨林
   else biome[row][col] = 10;
  }

図の数値通りにバイオーム分けするプログラムを書きます。

PN512
"年平均気温"と"年降水量"のみで作成したバイオーム。

PN512
"年平均気温"と"年降水量"と"標高"を用いて作成したバイオーム。
海と陸地を分けている。

🌏バイオーム画像の保存🌏

main関数
 dtl::storage::FilePNG<shape_t>("file_sample_biome.png", 3).write(biome, size_x, size_y, [](const shape_t value, unsigned char* const color) {
  switch (value) {
  //海
  case 0:
   color[0] = 41;color[1] = 40;color[2] = 159;
   break;
  //ツンドラ
  case 1:
   color[0] = 218;color[1] = 217;color[2] = 225;
   break;
  //砂漠
  case 2:
   color[0] = 223;color[1] = 203;color[2] = 140;
   break;
  //ステップ
  case 3:
   color[0] = 188;color[1] = 205;color[2] = 146;
   break;
  //サバンナ
  case 4:
   color[0] = 164;color[1] = 143;color[2] = 50;
   break;
  //針葉樹林
  case 5:
   color[0] = 97;color[1] = 154;color[2] = 96;
   break;
  //夏緑樹林
  case 6:
   color[0] = 101;color[1] = 163;color[2] = 56;
   break;
  //照葉樹林
  case 7:
   color[0] = 9;color[1] = 100;color[2] = 5;
   break;
  //雨緑樹林
  case 8:
  //亜熱帯多雨林
  case 9:
  //熱帯多雨林
  case 10:
   color[0] = 43;color[1] = 84;color[2] = 41;
   break;
  }
  });
 return 0;
}

生成したバイオームの画像をPNG形式で保存します。
これで出力は完了です。

🌏完成🌏

無事に実装できました。

PN512

🌏実装ライブラリ(ソースコード)🌏

今回解説した地形自動生成は"Dungeon Template Library""PerlinIsland"として実装されています。
ぜひ、活用してみてください!

logo640.gif

🌏ソースコードのライセンス🌏

These codes are licensed under CC0.
CC0

この記事のソースコードはCC0ライセンスとします。
ぜひ、自由に改変して遊んでみてください。

"いいね"をつけてくださると大変励みになります。
最後までお読みいただきありがとうございました!

262
121
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
262
121