1
0
mirror of https://github.com/kepler155c/opus synced 2024-11-15 05:04:50 +00:00
opus/sys/apis/jumper/pathfinder.lua

105 lines
3.0 KiB
Lua
Raw Normal View History

2016-12-11 19:24:52 +00:00
--[[
2018-01-24 22:39:38 +00:00
The following License applies to all files within the jumper directory.
2016-12-11 19:24:52 +00:00
2018-01-24 22:39:38 +00:00
Note that this is only a partial copy of the full jumper code base. Also,
the code was modified to support 3D maps.
2016-12-11 19:24:52 +00:00
--]]
--[[
This work is under MIT-LICENSE
Copyright (c) 2012-2013 Roland Yonaba.
2018-01-24 22:39:38 +00:00
-- https://opensource.org/licenses/MIT
2016-12-11 19:24:52 +00:00
--]]
local _VERSION = ""
local _RELEASEDATE = ""
if (...) then
2018-01-24 22:39:38 +00:00
-- Dependencies
local _PATH = (...):gsub('%.pathfinder$','')
2016-12-11 19:24:52 +00:00
local Utils = require (_PATH .. '.core.utils')
2018-01-24 22:39:38 +00:00
-- Internalization
local pairs = pairs
local assert = assert
local setmetatable = setmetatable
2016-12-11 19:24:52 +00:00
--- Finders (search algorithms implemented). Refers to the search algorithms actually implemented in Jumper.
-- <li>[A*](http://en.wikipedia.org/wiki/A*_search_algorithm)</li>
2018-01-24 22:39:38 +00:00
local Finders = {
['ASTAR'] = require (_PATH .. '.search.astar'),
}
-- Will keep track of all nodes expanded during the search
-- to easily reset their properties for the next pathfinding call
local toClear = {}
-- Performs a traceback from the goal node to the start node
-- Only happens when the path was found
local Pathfinder = {}
Pathfinder.__index = Pathfinder
function Pathfinder:new(heuristic)
local newPathfinder = {}
setmetatable(newPathfinder, Pathfinder)
self._finder = Finders.ASTAR
self._heuristic = heuristic
return newPathfinder
end
function Pathfinder:setGrid(grid)
self._grid = grid
return self
end
--- Calculates a `path`. Returns the `path` from start to end location
-- Both locations must exist on the collision map. The starting location can be unwalkable.
-- @treturn path a path (array of nodes) when found, otherwise nil
2016-12-11 19:24:52 +00:00
-- @usage local path = myFinder:getPath(1,1,5,5)
2018-01-24 22:39:38 +00:00
function Pathfinder:getPath(startX, startY, startZ, ih, endX, endY, endZ, oh)
2016-12-11 19:24:52 +00:00
self:reset()
2018-01-24 22:39:38 +00:00
local startNode = self._grid:getNodeAt(startX, startY, startZ)
local endNode = self._grid:getNodeAt(endX, endY, endZ)
if not startNode or not endNode then
return nil
end
startNode.heading = ih
endNode.heading = oh
assert(startNode, ('Invalid location [%d, %d, %d]'):format(startX, startY, startZ))
assert(endNode and self._grid:isWalkableAt(endX, endY, endZ),
('Invalid or unreachable location [%d, %d, %d]'):format(endX, endY, endZ))
local _endNode = self._finder(self, startNode, endNode, toClear)
if _endNode then
2016-12-11 19:24:52 +00:00
return Utils.traceBackPath(self, _endNode, startNode)
2018-01-24 22:39:38 +00:00
end
return nil
end
2016-12-11 19:24:52 +00:00
2018-01-24 22:39:38 +00:00
--- Resets the `pathfinder`. This function is called internally between
-- successive pathfinding calls, so you should not
2016-12-11 19:24:52 +00:00
-- use it explicitely, unless under specific circumstances.
2018-01-24 22:39:38 +00:00
-- @class function
2016-12-11 19:24:52 +00:00
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage local path, len = myFinder:getPath(1,1,5,5)
function Pathfinder:reset()
2018-01-24 22:39:38 +00:00
for node in pairs(toClear) do node:reset() end
toClear = {}
2016-12-11 19:24:52 +00:00
return self
end
2018-01-24 22:39:38 +00:00
-- Returns Pathfinder class
2016-12-11 19:24:52 +00:00
Pathfinder._VERSION = _VERSION
Pathfinder._RELEASEDATE = _RELEASEDATE
2018-01-24 22:39:38 +00:00
return setmetatable(Pathfinder,{
__call = function(self,...)
return self:new(...)
end
})
2016-12-11 19:24:52 +00:00
end