4

互いにオーバーラップする乱数のセルを生成するダンジョン生成アルゴリズム (ここで提示され、ここデモ)を実装しようとしています。次に、細胞は押し離されて/分離されてから接続されます。ここで、元のポスター/著者は、領域全体にセルを均一に分散させるために分離ステアリングアルゴリズムを使用していると説明しました。群れのアルゴリズムや分離ステアリングの動作についてあまり経験がなかったため、説明を求めてグーグルに目を向けました(そしてこれを見つけまし)。私の実装(最後に述べた記事に基づく)は次のとおりです。

function pdg:_computeSeparation(_agent)
  local neighbours = 0
  local rtWidth = #self._rooms
  local v =
  {
    x = self._rooms[_agent].startX,
    y = self._rooms[_agent].startY,
    --velocity = 1,
  }

  for i = 1, rtWidth do
    if _agent ~= i then
      local distance = math.dist(self._rooms[_agent].startX, 
                                 self._rooms[_agent].startY, 
                                 self._rooms[i].startX,
                                 self._rooms[i].startY)
      if distance < 12 then
        --print("Separating agent: ".._agent.." from agent: "..i.."")
        v.x = (v.x + self._rooms[_agent].startX - self._rooms[i].startX) * distance
        v.y = (v.y + self._rooms[_agent].startY - self._rooms[i].startY) * distance
        neighbours = neighbours + 1
      end
    end
  end


  if neighbours == 0 then
    return v
  else
    v.x = v.x / neighbours
    v.y = v.y / neighbours
    v.x = v.x * -1
    v.y = v.y * -1
    pdg:_normalize(v, 1)
    return v
  end
end

self._rooms は、グリッド内の部屋の元の X および Y 位置と、その幅と高さ (endX、endY) を含むテーブルです。

問題は、セルをグリッド上にきちんと配置する代わりに、重なっているセルを取得して、それらを 1,1 から距離 +2、距離 +2 の領域に移動することです (私のビデオ [youtube] で見られるように) 。

なぜこれが起こっているのかを理解しようとしています。

必要に応じて、ここでグリッド テーブルを解析し、分離後にセルを分離して塗りつぶします。

function pdg:separate( )
  if #self._rooms > 0 then
    --print("NR ROOMS: "..#self._rooms.."")

    -- reset the map to empty
  for x = 1, self._pdgMapWidth do
    for y = 1, self._pdgMapHeight do
      self._pdgMap[x][y] = 4
    end
  end

  -- now, we separate the rooms
  local numRooms = #self._rooms
  for i = 1, numRooms do
    local v = pdg:_computeSeparation(i)
    --we adjust the x and y positions of the items in the room table
    self._rooms[i].startX = v.x
    self._rooms[i].startY = v.y
    --self._rooms[i].endX = v.x + self._rooms[i].endX 
    --self._rooms[i].endY = v.y + self._rooms[i].endY
  end


  -- we render them again
  for i = 1, numRooms do
    local px = math.abs( math.floor(self._rooms[i].startX) )
    local py = math.abs( math.floor(self._rooms[i].startY) )

    for k = self.rectMinWidth, self._rooms[i].endX do
      for v = self.rectMinHeight, self._rooms[i].endY do
        print("PX IS AT: "..px.." and k is: "..k.." and their sum is: "..px+k.."")
        print("PY IS AT: "..py.." and v is: "..v.." and their sum is: "..py+v.."")
        if k == self.rectMinWidth or 
           v == self.rectMinHeight or 
           k == self._rooms[i].endX or 
           v == self._rooms[i].endY then
          self._pdgMap[px+k][py+v] = 1
        else
          self._pdgMap[px+k][py+v] = 2
        end
      end
    end
  end
end
4

2 に答える 2

1

私もこの生成アルゴリズムを実装しましたが、多かれ少なかれ同じ問題に遭遇しました。私の長方形はすべて左上隅になりました。

私の問題は、速度ベクトルを長さゼロで正規化していたことです。これらを正規化すると、0 で割ると NaN になります。

これを修正するには、速度の長さがゼロであるかどうかをチェックしてから、それ以降の計算で使用します。

これが役立つことを願っています!

于 2013-12-24T19:57:30.483 に答える
0

ええと、それは古い質問だと思いますが、何かに気づいたので、誰かに役立つかもしれません...

ここに問題があると思います:

v.x = (v.x + self._rooms[_agent].startX - self._rooms[i].startX) * distance
v.y = (v.y + self._rooms[_agent].startY - self._rooms[i].startY) * distance

なぜこれらの方程式に距離を掛けるのですか? " (self._rooms[_agent].startX - self._rooms[i].startX)" には既に (二乗) 距離が含まれています! さらに、すべてに " " を掛けるdistanceと、v に保存されている以前の結果が変更されます! 少なくとも「vx」を括弧の外に置くと、結果は高くなり、正規化機能によって修正されます。無駄な計算ですが…

ちなみに、コードは次のようになるはずです。

v.x = v.x + (self._rooms[_agent].startX - self._rooms[i].startX)
v.y = v.y + (self._rooms[_agent].startY - self._rooms[i].startY)

例を挙げます。(0,0) にメイン エージェントがあり、(0,-2)、(-2,0)、(0,2) に 3 つの隣接エージェントがあるとします。分離ステアリング動作は、(1,0) の正規化された方向で、メイン エージェントを X 軸に向かって移動します。結果ベクトルの Y コンポーネントだけに注目しましょう。

数学は次のようになります。

--Iteration 1
v.y = 0 + ( 0 + 2 )
--Iteration 2
v.y = 2 + ( 0 - 0 )
--Iteration 3
v.y = 2 + ( 0 - 2 )
--Result
v.y = 0

これは私たちの理論と一致しています。これはあなたのコードが行うことです:

(note that the distance is always 2)
--Iteration 1
v.y = ( 0 + 0 + 2 ) * 2
--Iteration 2
v.y = ( 4 + 0 - 0 ) * 2
--Iteration 3
v.y = ( 8 + 0 - 2 ) * 2
--Result
v.y = 12

セパレーション ステアリングの挙動が正しければ、これは正しくありません。

于 2014-10-23T23:16:16.933 に答える