Advertisement
Guest User

A* Pathfinding

a guest
Nov 23rd, 2014
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.43 KB | None | 0 0
  1. local thenodes
  2. local master_node_table, mnt_index
  3. local ai_max_range = math.huge
  4.  
  5. thenodes = workspace:findFirstChild("nodeDir", true)
  6.  
  7.  
  8. function searchByBrick(brick)
  9.     for i, j in pairs(master_node_table) do
  10.         if j.Brick == brick then
  11.             return j.ID
  12.         end
  13.     end
  14.     return nil
  15. end
  16.  
  17. function searchById(id)
  18.     for i, j in pairs(master_node_table) do
  19.         if j.ID == id then
  20.             return j.Brick
  21.         end
  22.     end
  23.     return nil
  24. end
  25.  
  26.  
  27.  
  28. function nodeObjectFromBrick(brick)
  29.     if brick.ClassName ~= "Part" then
  30.         return nil
  31.     end
  32.     local node_index = mnt_index
  33.     master_node_table[node_index] = {
  34.         ID = mnt_index,
  35.         Brick = brick,
  36.         Connections = {}
  37.     }
  38.     for i, child in pairs(brick:GetChildren()) do
  39.         if child.ClassName == "ObjectValue" and child.Name == "connection" then
  40.             local brick2 = child.Value
  41.             local ID = searchByBrick(brick2)
  42.             if ID == nil then
  43.                 mnt_index = mnt_index + 1
  44.                 ID = nodeObjectFromBrick(brick2)
  45.             end
  46.             local con = {
  47.                 ID = ID,
  48.                 G = (master_node_table[ID].Brick.Position - brick.Position).magnitude
  49.             }
  50.             table.insert(master_node_table[node_index].Connections, con)
  51.         end
  52.     end
  53.    
  54.     return node_index
  55. end
  56.  
  57.  
  58. function collectNodes(model)
  59.     master_node_table = {}
  60.     mnt_index = 1
  61.     for i, child in pairs(model:GetChildren()) do
  62.         if child.ClassName == "Part" and searchByBrick(child) == nil then
  63.             nodeObjectFromBrick(child)
  64.             mnt_index = mnt_index + 1
  65.         end
  66.     end
  67. end
  68.  
  69.  
  70. function heuristic(id1, id2)
  71.     local p1 = master_node_table[id1].Brick.Position
  72.     local p2 = master_node_table[id2].Brick.Position
  73.     return (p1 - p2).magnitude
  74. end
  75.  
  76.  
  77. function len(t)
  78.     local l = 0
  79.     for i, j in pairs(t) do
  80.         if j ~= nil then
  81.             l = l + 1
  82.         end
  83.     end
  84.     return l
  85. end
  86.  
  87.  
  88. function getPath(t, n)
  89.     if t[n] == nil then
  90.         return {n}
  91.     else
  92.         local t2 = getPath(t, t[n])
  93.         table.insert(t2, n)
  94.         return t2
  95.     end
  96. end
  97.  
  98.  
  99. function AStar(startID, endID)
  100.     --local now = tick()
  101.     local closed = {}
  102.     local open = {startID}
  103.     local previous = {}
  104.     local g_score = {}
  105.     local f_score = {}
  106.    
  107.     g_score[startID] = 0
  108.     f_score[startID] = heuristic(startID, endID)
  109.    
  110.     while len(open) > 0 do
  111.         local current, current_i = nil, nil
  112.         for i, j in pairs(open) do
  113.             if current == nil then
  114.                 current = j
  115.                 current_i = i
  116.             else
  117.                 if j ~= nil then
  118.                     if f_score[j] < f_score[current] then
  119.                         current = j
  120.                         current_i = i
  121.                     end
  122.                 end
  123.             end
  124.         end
  125.        
  126.         if current == endID then
  127.             local path = getPath(previous, endID)
  128.             local ret = {}
  129.             for i, j in pairs(path) do
  130.                 table.insert(ret, master_node_table[j].Brick)
  131.             end
  132.             --print("Time taken for AStar to run: "..tostring(tick() - now))
  133.             return ret
  134.         end
  135.        
  136.         open[current_i] = nil
  137.         table.insert(closed, current)
  138.        
  139.         for i, j in pairs(master_node_table[current].Connections) do
  140.             local in_closed = false
  141.             for k, l in pairs(closed) do
  142.                 if l == j.ID then
  143.                     in_closed = true
  144.                     break
  145.                 end
  146.             end
  147.             if in_closed == false then
  148.                 local tentative_score = g_score[current] + j.G
  149.                 local in_open = false
  150.                 for k, l in pairs(open) do
  151.                     if l == j.ID then
  152.                         in_open = true
  153.                         break
  154.                     end
  155.                 end
  156.                 if in_open == false or tentative_score < g_score[j.ID] then
  157.                     previous[j.ID] = current
  158.                     g_score[j.ID] = tentative_score
  159.                     f_score[j.ID] = g_score[j.ID] + heuristic(j.ID, endID)
  160.                     if in_open == false then
  161.                         table.insert(open, j.ID)
  162.                     end
  163.                 end
  164.             end
  165.         end
  166.     end
  167.     --print("Time taken for AStar to run: "..tostring(tick() - now))
  168.     return nil
  169. end
  170.  
  171.  
  172.  
  173. function getNearestNode(position,returnBrick,dir)
  174.     local nodeDir = dir
  175.     local smallest = ai_max_range
  176.     local nodes = {}
  177.     if type(dir) ~= "table" then
  178.         nodeDir = dir:children()
  179.     end
  180.     for k,v in pairs(nodeDir) do
  181.         if v:IsA("BasePart") then
  182.             local dist
  183.             dist = (position.Position - v.Position).magnitude
  184.             nodes[searchByBrick(v)] = dist
  185.             if dist <= smallest then
  186.                 smallest = dist
  187.             end
  188.         end
  189.     end
  190.     for k,v in pairs(nodes) do
  191.         print(k)
  192.         if v <= smallest then
  193.             if returnBrick then
  194.                 return searchById(k)
  195.             else
  196.                 return k
  197.             end
  198.         end
  199.     end
  200. end
  201.  
  202.  
  203.  
  204. collectNodes(thenodes)  --generate nodegraph
  205. local start = getNearestNode(workspace.Start, true, thenodes)
  206. local goal = getNearestNode(workspace.Goal, true, thenodes)
  207.  
  208. local path = AStar(searchByBrick(start), searchByBrick(goal)) --returns table of parts(nodes), in order from start to goal
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement