2013-07-23 10 views
4

Я пытаюсь реализовать алгоритм генерации подземелья (presented here и demo-ed here), который включает в себя создание случайного числа ячеек, которые перекрывают друг друга. Затем клетки отталкиваются/разделяются и затем соединяются. Теперь первоначальный плакат/автор описал, что он использует Алгоритм разделения разделения, чтобы равномерно распределять ячейки по области. У меня не было большого опыта работы с алгоритмом флокирования и/или режимом управления разделением, поэтому я обратился к Google для объяснения (и нашел this). Моя реализация (на основе статьи последней упомянутой) заключается в следующем:Lua Separation Группы алгоритмов перекрытия перекрывают комнаты в один угол

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 (as seen in my video [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 

ответ

1

Я реализовал этот алгоритм генерации, а также, и я наткнулся на более или менее то же самое вопрос. Все мои прямоугольники оказались в углу.

Моя проблема в том, что я нормализую векторы скорости с нулевой длиной. Если вы нормализуете их, вы делите на ноль, что приведет к NaN.

Вы можете исправить это, просто выполнив проверку того, равна ли ваша скорость нулю до ее использования при любых дальнейших расчетах.

Надеюсь, это поможет!

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! Если вы поместите «v.x» за пределы скобки, результат будет только выше, функция нормализации зафиксирует его. Несмотря на то, что какая-то бесполезная расчет ...

Кстати, я уверен, что код должен быть как:

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). Управление рулевым управлением разделяет основной агент на ось X в нормализованном направлении (1,0). Давайте сосредоточимся только на 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 

И если бы я получил поведение разделения рулевого право это не может быть правильным.