世界を創成する闇魔術について解説します。
今回はチャンクを用いた中点変位法(フラクタル)アルゴリズムを使用します。
チャンク生成で世界の鱗片を生成します。
今回は16マス×16マスのチャンクを生成しています。
#🌏フラクタル島生成クラス🌏
フラクタルの作成と島生成を行うFractalIslandクラスを作成します。
namespace dtl {
template<typename Int>
class FractalIsland;
}
dtl(Dungeon Template Library)名前空間に作成します。
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_);
}
コンストラクタから生成関数を呼び出します。
ひとまず導入する準備が出来ました。
次はチャンクを配置して島を作ります。
#🌏チャンク配置🌏
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 | 山 | ■■白■■ |
**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_);
}
チャンクを貼り付けてワールドを構築します。
#🌏岸を複雑にする🌏
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関数
**によって削り出します。
この生成法では、画面の端を意図的にループさせることが可能です。
また、この手法により**"マインクラフト"**のようなほぼ無限の大きさを持つワールド生成を作り出すことが出来ます。
#🌏完成🌏
完成です。
"ボロノイ図法"と今回の"チャンク&中点変位法"、
皆さんはどちらがお好きですか?
🌏実装ライブラリ(ソースコード)🌏
今回解説した地形の自動生成は**"Dungeon Template Library"に"Fractal Island"**として実装されています。
ぜひ、活用してみてください!
#🌏ソースコードのライセンス🌏
These codes are licensed under CC0.
この記事のソースコードはCC0ライセンスとします。
ぜひ、自由に改変して遊んでみてください。
最後までお読みいただきありがとうございました!
###関連記事
[DTL]ローグライク自動生成(ローグライク穴掘り法)💀
ローグライクダンジョン生成の記事。
[DTL]地形生成(ボロノイ図法)🌏
ボロノイ図法の地形生成の記事。