mirror of
				https://github.com/kepler155c/opus
				synced 2025-10-31 15:43:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			102 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| --- The Grid class.
 | |
| -- Implementation of the `grid` class.
 | |
| -- The `grid` is a implicit graph which represents the 2D
 | |
| -- world map layout on which the `pathfinder` object will run.
 | |
| -- During a search, the `pathfinder` object needs to save some critical values.
 | |
| -- These values are cached within each `node`
 | |
| -- object, and the whole set of nodes are tight inside the `grid` object itself.
 | |
| 
 | |
| if (...) then
 | |
| 
 | |
| 	-- Dependencies
 | |
| 	local _PATH = (...):gsub('%.grid$','')
 | |
| 
 | |
| 	-- Local references
 | |
| 	local Utils = require (_PATH .. '.core.utils')
 | |
| 	local Node = require (_PATH .. '.core.node')
 | |
| 
 | |
| 	-- Local references
 | |
| 	local setmetatable = setmetatable
 | |
| 
 | |
| 	-- Offsets for straights moves
 | |
| 	local straightOffsets = {
 | |
| 		{x = 1, y = 0, z = 0} --[[W]], {x = -1, y =  0, z =  0}, --[[E]]
 | |
| 		{x = 0, y = 1, z = 0} --[[S]], {x =  0, y = -1, z =  0}, --[[N]]
 | |
| 		{x = 0, y = 0, z = 1} --[[U]], {x =  0, y = -0, z = -1}, --[[D]]
 | |
| 	}
 | |
| 
 | |
| 	local Grid = {}
 | |
| 	Grid.__index = Grid
 | |
| 
 | |
| 	function Grid:new(dim)
 | |
| 		local newGrid = { }
 | |
| 		newGrid._min_x, newGrid._max_x = dim.x, dim.ex
 | |
| 		newGrid._min_y, newGrid._max_y = dim.y, dim.ey
 | |
| 		newGrid._min_z, newGrid._max_z = dim.z, dim.ez
 | |
| 		newGrid._nodes = { }
 | |
| 		newGrid._width = (newGrid._max_x-newGrid._min_x)+1
 | |
| 		newGrid._height = (newGrid._max_y-newGrid._min_y)+1
 | |
| 		newGrid._length = (newGrid._max_z-newGrid._min_z)+1
 | |
| 		return setmetatable(newGrid,Grid)
 | |
| 	end
 | |
| 
 | |
| 	function Grid:isWalkableAt(x, y, z)
 | |
| 		local node = self:getNodeAt(x,y,z)
 | |
| 		return node and node.walkable ~= 1
 | |
| 	end
 | |
| 
 | |
| 	function Grid:getWidth()
 | |
| 		return self._width
 | |
| 	end
 | |
| 
 | |
| 	function Grid:getHeight()
 | |
| 		 return self._height
 | |
| 	end
 | |
| 
 | |
| 	function Grid:getNodes()
 | |
| 		return self._nodes
 | |
| 	end
 | |
| 
 | |
| 	function Grid:getBounds()
 | |
| 		return self._min_x, self._min_y, self._min_z, self._max_x, self._max_y, self._max_z
 | |
| 	end
 | |
| 
 | |
| 	--- Returns neighbours. The returned value is an array of __walkable__ nodes neighbouring a given `node`.
 | |
| 	-- @treturn {node,...} an array of nodes neighbouring a given node
 | |
| 	function Grid:getNeighbours(node)
 | |
| 		local neighbours = {}
 | |
| 		for i = 1,#straightOffsets do
 | |
| 			local n = self:getNodeAt(
 | |
| 				node.x + straightOffsets[i].x,
 | |
| 				node.y + straightOffsets[i].y,
 | |
| 				node.z + straightOffsets[i].z
 | |
| 			)
 | |
| 			if n and self:isWalkableAt(n.x, n.y, n.z) then
 | |
| 				neighbours[#neighbours+1] = n
 | |
| 			end
 | |
| 		end
 | |
| 
 | |
| 		return neighbours
 | |
| 	end
 | |
| 
 | |
|  function Grid:getNodeAt(x,y,z)
 | |
| 		if not x or not y or not z then return end
 | |
| 		if Utils.outOfRange(x,self._min_x,self._max_x) then return end
 | |
| 		if Utils.outOfRange(y,self._min_y,self._max_y) then return end
 | |
| 		if Utils.outOfRange(z,self._min_z,self._max_z) then return end
 | |
| 
 | |
| 		-- inefficient
 | |
| 		if not self._nodes[y] then self._nodes[y] = {} end
 | |
| 		if not self._nodes[y][x] then self._nodes[y][x] = {} end
 | |
| 		if not self._nodes[y][x][z] then self._nodes[y][x][z] = Node:new(x,y,z) end
 | |
| 		return self._nodes[y][x][z]
 | |
| 	end
 | |
| 
 | |
| 	return setmetatable(Grid,{
 | |
| 		__call = function(self,...)
 | |
| 			return self:new(...)
 | |
| 		end
 | |
| 	})
 | |
| 
 | |
| end
 | 
