mirror of
				https://github.com/kepler155c/opus
				synced 2025-10-30 23:23:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			120 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| --[[
 | |
|   The following License applies to all files within the jumper directory.
 | |
| 
 | |
|   Note that this is only a partial copy of the full jumper code base. Also,
 | |
|   the code was modified to support 3D maps.
 | |
| --]]
 | |
| 
 | |
| --[[
 | |
| This work is under MIT-LICENSE
 | |
| Copyright (c) 2012-2013 Roland Yonaba.
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| of this software and associated documentation files (the "Software"), to deal
 | |
| in the Software without restriction, including without limitation the rights
 | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in
 | |
| all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | |
| THE SOFTWARE.
 | |
| --]]
 | |
| 
 | |
| local _VERSION = ""
 | |
| local _RELEASEDATE = ""
 | |
| 
 | |
| if (...) then
 | |
| 
 | |
|   -- Dependencies
 | |
|   local _PATH = (...):gsub('%.pathfinder$','')
 | |
| 	local Utils     = require (_PATH .. '.core.utils')
 | |
| 
 | |
|   -- Internalization
 | |
|   local pairs = pairs
 | |
|   local assert = assert
 | |
|   local setmetatable = setmetatable
 | |
| 
 | |
| 	--- Finders (search algorithms implemented). Refers to the search algorithms actually implemented in Jumper.
 | |
| 	-- <li>[A*](http://en.wikipedia.org/wiki/A*_search_algorithm)</li>
 | |
|   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
 | |
| 	-- @usage local path = myFinder:getPath(1,1,5,5)
 | |
|   function Pathfinder:getPath(startX, startY, startZ, ih, endX, endY, endZ, oh)
 | |
| 		self:reset()
 | |
|     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
 | |
| 			return Utils.traceBackPath(self, _endNode, startNode)
 | |
|     end
 | |
|     return nil
 | |
|   end
 | |
| 
 | |
|   --- Resets the `pathfinder`. This function is called internally between
 | |
|   -- successive pathfinding calls, so you should not
 | |
| 	-- use it explicitely, unless under specific circumstances.
 | |
|   -- @class function
 | |
| 	-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
 | |
| 	-- @usage local path, len = myFinder:getPath(1,1,5,5)
 | |
| 	function Pathfinder:reset()
 | |
|     for node in pairs(toClear) do node:reset() end
 | |
|     toClear = {}
 | |
| 		return self
 | |
| 	end
 | |
| 
 | |
|   -- Returns Pathfinder class
 | |
| 	Pathfinder._VERSION = _VERSION
 | |
| 	Pathfinder._RELEASEDATE = _RELEASEDATE
 | |
|   return setmetatable(Pathfinder,{
 | |
|     __call = function(self,...)
 | |
|       return self:new(...)
 | |
|     end
 | |
|   })
 | |
| end
 | 
