地図/気まぐれ/プロシージャル生成

物を撒く — オブジェクト配置

宝箱や敵や木を盤面に置く。一様乱数でそのまま撒くと、点が固まったり重なったりする。互いに一定の距離を空けて撒くと、まんべんなく散って、しかも格子のようには整列しない散らばりになる。

ブルーノイズ。点どうしが最小距離を保ち、近距離の偏りが消えた撒き方。低周波の成分が薄く、高周波(細かい揺らぎ)が支配的なスペクトルから来た名前。最小距離 r を全点で守る配置がポアソンディスク分布で、候補点を投げては近すぎたら捨てる素朴版が dart throwing。Robert Bridson の 2007 年のアルゴリズムは格子で近傍だけを調べ、線形時間で同じ分布を撒く。網膜の視細胞や印刷のスクリーン点もこの分布に近い。

候補点と、すでに置いた全部の点との距離を測り、radius より近い相手が一つでもあれば棄却する。距離はルートを取らず二乗どうしで比べる。平方根を一つ取るより、大小の比較だけなら二乗のまま済む。

// すでに置いた点と近すぎないか。距離は二乗のまま比べる
const ok = (x, y) => {
  for (const p of points) {
    const dx = p.x - x
    const dy = p.y - y
    if (dx * dx + dy * dy < radius * radius) return false // 近すぎ → 棄却
  }
  return true
}

候補をランダムに出しては ok に通し、通った点だけ points に積む。これを何千回も試すと、どの点も互いに radius 以上離れた散らばりに収束する。下は床マスク(明るい所を床とみなすノイズ場)を一枚かませて、isFloor が偽の壁の上には点を置かない。歩ける所だけに配置する制限が一行で入る。

radius を大きくすると点がまばらに、小さくすると密になる。どの点も互いに radius より離れているので、一様乱数で撒いたときの団子状の偏りが消える。isFloor を生成したマップに差し替えると、床の上だけに間隔を空けて物が撒かれる。場所ごとに radius を変えれば撒く密度が変わり、影響マップで配置を制御する形になる。