C++
アルゴリズム
数学
ゲーム制作
DungeonGeneration

fmap.gif

世界を創成する闇魔術について解説します。

今回はチャンクを用いた中点変位法(フラクタル)アルゴリズムを使用します。


🌏チャンク生成🌏

chunk.gif

チャンク生成で世界の鱗片を生成します。

今回は16マス×16マスのチャンクを生成しています。


🌏フラクタル島生成クラス🌏

フラクタルの作成と島生成を行うFractalIslandクラスを作成します。


クラス名

namespace dtl {

template<typename Int>
class FractalIsland;
}

dtl(Dungeon Template Library)名前空間に作成します。


コンストラクタ(public)

constexpr explicit FractalIsland(STL_& world_map, std::size_t seed_ = 0, const std::int_fast32_t max_value_ = 255) {

create(world_map, seed_, max_value_);
}

コンストラクタから生成関数を呼び出します。

fmap_b.png

ひとまず導入する準備が出来ました。

次はチャンクを配置して島を作ります。


🌏チャンク配置🌏


worldMapMake関数

constexpr void worldMapMake(const std::size_t x_, const std::size_t y_, const std::size_t size_, const std::size_t t1_, const std::size_t t2_, const std::size_t t3_, const std::size_t t4_, std::array<std::array<Int_, 17>, 17>& map_, const std::size_t max_value_);


標高
名前

0-140

■■青■■

140-150

■■黄■■

150-230

■■緑■■

230-255

■■白■■

chunk.gif

worldMapMake関数でチャンクを生成します。

標高は再起して割り出します。

標高を元に地形を生成します。


チャンク生成関数

constexpr void worldMapMake(const std::size_t x_, const std::size_t y_, const std::size_t size_, const std::size_t t1_, const std::size_t t2_, const std::size_t t3_, const std::size_t t4_, std::array<std::array<Int_, 17>, 17>& map_, const std::size_t max_value_) const noexcept {

if (size_ == 0) return;
const std::size_t vertex_height{ ((t1_ + t2_ + t3_ + t4_) / 4) + static_cast<std::size_t>(2)(rnd((std::int_fast32_t)size_)) };
map_[x_][y_] = ((vertex_height >= max_value_) ? (Int_)max_value_ : (Int_)vertex_height);
const std::size_t s1{ ((t1_ + t2_) / 2) };
const std::size_t s2{ ((t1_ + t3_) / 2) };
const std::size_t s3{ ((t2_ + t4_) / 2) };
const std::size_t s4{ ((t3_ + t4_) / 2) };
map_[x_ + size_][y_] = static_cast<Int_>(s3);
map_[x_ - size_][y_] = static_cast<Int_>(s2);
map_[x_][y_ + size_] = static_cast<Int_>(s4);
map_[x_][y_ - size_] = static_cast<Int_>(s1);
const std::size_t& size{ size_ / static_cast<std::size_t>(2) };
worldMapMake(x_ - size, y_ - size, size, t1_, s1, s2, map_[x_][y_], map_, max_value_);
worldMapMake(x_ + size, y_ - size, size, s1, t2_, map_[x_][y_], s3, map_, max_value_);
worldMapMake(x_ - size, y_ + size, size, s2, map_[x_][y_], t3_, s4, map_, max_value_);
worldMapMake(x_ + size, y_ + size, size, map_[x_][y_], s3, s4, t4_, map_, max_value_);
}

roll.gif

チャンクを貼り付けてワールドを構築します。


🌏岸を複雑にする🌏


ノイズを発生させる

namespace dtl {

template<typename STL_>
constexpr void noiseShoreBool(STL_& stl_, const double rbool_) noexcept {
for (std::size_t i{ 1 }; i < stl_.size(); ++i)
for (std::size_t j{ 1 }; j < stl_[i].size(); ++j) {
if (!rnd.randBool(rbool_) || (stl_[i][j] == stl_[i][j - 1] && stl_[i][j] == stl_[i - 1][j])) continue;
if (stl_[i][j]) stl_[i][j] = false;
else stl_[i][j] = true;
}
}
}

岸の部分をnoiseShoreBool関数によって削り出します。

fshima.png

この生成法では、画面の端を意図的にループさせることが可能です。

また、この手法により"マインクラフト"のようなほぼ無限の大きさを持つワールド生成を作り出すことが出来ます。


🌏完成🌏

fmap.gif

完成です。

"ボロノイ図法"と今回の"チャンク&中点変位法"、

皆さんはどちらがお好きですか?


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

今回解説した地形の自動生成は"Dungeon Template Library""Fractal Island"として実装されています。

ぜひ、活用してみてください!

logo640.gif

fmap3.gif


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

These codes are licensed under CC0.

CC0

この記事のソースコードはCC0ライセンスとします。

ぜひ、自由に改変して遊んでみてください。

最後までお読みいただきありがとうございました!


関連記事

[DTL]ローグライク自動生成(ローグライク穴掘り法)💀

ローグライクダンジョン生成の記事。

[DTL]地形生成(ボロノイ図法)🌏

ボロノイ図法の地形生成の記事。