#🌏母なる大地を創造する🌏
#🌏実装・環境🌏
開発言語:C++14
コンパイラ | 対応度 | テスト生成 |
---|---|---|
MSVC | None | |
GCC | Wandbox | |
Clang | Wandbox |
#🌏ボロノイ図法で作成🌏
世界生成アルゴリズムはいくつもの種類が存在します。
その中でも今回は**魅力的な形状を生成することに長けている"ボロノイ図法"**を使用します。
#🌏ボロノイ島生成クラス🌏
ボロノイ図の作成と島生成を行う**SimpleVoronoiIsland
**クラスを作成します。
namespace dtl {
template<typename Int>
class SimpleVoronoiIsland;
}
dtl(Dungeon Template Library)名前空間に作成します。
std::vector<std::pair<std::size_t, std::size_t>> point;
std::vector<Int> color;
メンバ変数には、原点の座標(x,y)を記録する**point
**
色情報または各ボロノイの地形種類を記録する**color
**を使用します。
template<typename T_>
constexpr SimpleVoronoiIsland(T_& t_, const std::size_t count_ = 100, const double rbool_ = 0.4, const Int land_ = 1, const Int sea_ = 0) {
create(t_, count_, rbool_, land_, sea_);
}
コンストラクタから生成関数を呼び出します。
ひとまず導入する準備が出来ました。
次は陸地生成の部分を作ります。
#🌏陸地の形状を作成🌏
template<typename T_>
constexpr void create(T_& t_, const std::size_t count_ = 100, const double rbool_ = 0.4, const Int land_ = 1, const Int sea_ = 0) {
for (std::size_t i{}; i < count_; ++i) {
createPoint((t_.empty()) ? 0 : t_.front().size(), t_.size(), rbool_, land_, sea_);
}
createSites(t_, (t_.empty()) ? 0 : t_.front().size(), t_.size());
}
"create関数"
は陸地生成する関数です。
当記事では、create関数
内のcount_変数
を"頂点数PN"、
**rbool_変数
を"陸地確率PB"**と呼びます。
constexpr bool isMakeIsland(const std::size_t w_, const std::size_t h_, const std::size_t numerator_, const std::size_t denominator_) const {
return (point.back().first > (w_ * numerator_ / denominator_) && point.back().first < (w_ * (denominator_ - numerator_) / denominator_)) && (point.back().second > (h_ * numerator_ / denominator_) && point.back().second < (h_ * (denominator_ - numerator_) / denominator_));
}
constexpr void createPoint(const std::size_t w_, const std::size_t h_, const double rbool_, const Int land_, const Int sea_) {
point.emplace_back((std::size_t)rnd((std::int_fast32_t)w_), (std::size_t)rnd((std::int_fast32_t)h_));
if (isMakeIsland(w_, h_, 2, 5) || (rnd.randBool(rbool_) && isMakeIsland(w_, h_, 1, 5)))
color.emplace_back(land_);
else color.emplace_back(sea_);
}
template<typename T_>
constexpr void createSites(T_& t_, const std::size_t w_, const std::size_t h_)const {
std::int_fast32_t ds{}, dist{};
for (std::size_t hh{}, ind{}; hh < h_; ++hh)
for (std::size_t ww{}; ww < w_; ++ww) {
ind = std::numeric_limits<std::size_t>::max();
dist = std::numeric_limits<std::int_fast32_t>::max();
for (std::size_t it{}; it < point.size(); ++it) {
const std::pair<std::size_t, std::size_t>& p{ point[it] };
if ((ds = distanceSqrd(p, (std::int_fast32_t)ww, (std::int_fast32_t)hh)) >= dist) continue;
dist = ds;
ind = it;
}
if (ind != std::numeric_limits<std::size_t>::max()) t_[hh][ww] = color[ind];
}
}
これで基本的な陸地生成は完了です。
次はより複雑な海岸線を作ります。
頂点数PN=300, 陸地確率PB=0.2, ノイズ確率NB=0.0 の場合
頂点数PN=100, 陸地確率PB=0.5, ノイズ確率NB=0.0 の場合
#🌏岸を複雑にする🌏
namespace dtl {
template<typename STL_>
constexpr void noiseShoreBool(STL_& vec_, const double rbool_) {
for (std::size_t i{ 1 }; i < vec_.size(); ++i)
for (std::size_t j{ 1 }; j < vec_[i].size(); ++j) {
if (!rnd.randBool(rbool_) || (vec_[i][j] == vec_[i][j - 1] && vec_[i][j] == vec_[i - 1][j])) continue;
if (vec_[i][j]) vec_[i][j] = false;
else vec_[i][j] = true;
}
}
}
int main() {
std::array<std::bitset<96>, 64> col{{}};
dtl::SimpleVoronoiIsland<bool> diagram(col, 100, 0.5);
dtl::noiseShoreBool(col, 0.5); //ノイズを生成
dtl::outputBoolBitSet(col, "*", " ");
}
岸の部分を**noiseShoreBool関数
によって削り出します。
当記事では、noiseShoreBool関数
内のrbool_変数
を"ノイズ確率NB"**と呼びます。
頂点数PN=300, 陸地確率PB=0.2, ノイズ確率NB=0.5 の場合
頂点数PN=100, 陸地確率PB=0.5, ノイズ確率NB=0.5 の場合
#🌏CUIでの出力🌏
namespace dtl {
template<typename STL_>
constexpr void outputBoolBitSet(const STL_& vec_, const char* const true_str_, const char* const false_str_) {
for (const auto& i : vec_) {
for (std::size_t j = 0; j < i.size(); ++j) {
if (i[j]) std::cout << true_str_;
else std::cout << false_str_;
}
std::cout << std::endl;
}
}
}
int main() {
std::array<std::bitset<96>, 64> col{{}};
dtl::SimpleVoronoiIsland<bool> diagram(col, 100, 0.5);
dtl::noiseShoreBool(col, 0.5);
dtl::outputBoolBitSet(col, "*", " ");
}
コンソールから出力します。
頂点数PN=100, 陸地確率PB=0.5, ノイズ確率NB=0.5 の場合
>> Wandboxで自動生成を試してみる(PC表示で見てね)
🌏実装ライブラリ(ソースコード)🌏
今回解説した地形の自動生成は**"Dungeon Template Library"に"Simple Voronoi Island"**として実装されています。
ぜひ、活用してみてください!
#🌏ソースコードのライセンス🌏
These codes are licensed under CC0.
この記事のソースコードはCC0ライセンスとします。
ぜひ、自由に改変して遊んでみてください。
最後までお読みいただきありがとうございました!
###関連記事
[DTL]ローグライク自動生成(ローグライク穴掘り法)💀
ローグライクダンジョン生成の記事。
[DTL]地形生成(チャンク&中点変位法)🌽
チャンク&中点変位法の世界生成の記事。