In my grid-based game, The player clicks on a unit then he moves his finger to determine where this unit should move. I'm using the "Jumper" library for the pathfinding. The code for getting the path works perfectly, but the code for highlighting the path, not so much.
local function onTileTouch( event )
local phase = event.phase
local tile = event.target
if ( phase == "began" ) then
-- I could create the line here
elseif ( phase == "moved" ) then
createPath( tile )
-- Getting the position of the first tile based on where the unit is
local t = tiles[currentSelectedUnit.pos.y][currentSelectedUnit.pos.x]
-- Create the line at the first tile's position
line = display.newLine( t.x, t.y, t.x, t.y )
line:setStrokeColor( 1,0,0 )
line.strokeWidth = 8
-- "foundPath" is a table of tiles of the correct path
for i=1,#foundPath do
line:append( foundPath[i].x,foundPath[i].y )
end
elseif ( phase == "ended" or phase == "cancelled" ) then
end
The line doesn't look right when being created in the "moved" phase. It does, however, look very accurate when being created in the "began" phase and then getting appended during the "moved" phase. But in this case, another extra line gets drawn that doesn't follow the path but gets directly from the start tile to the end tile. My second problem with the "began" phase method, is I don't know how to keep deleting the old line and create a new one with for the new correct path.
Let me know if any extra information is needed.
I'm not sure what exactly you want so I have prepared my own version:
test.lua
local composer = require( 'composer' )
-- Library setup
local Grid = require ( 'jumper.grid' ) -- The grid class
local Pathfinder = require ( 'jumper.pathfinder' ) -- The pathfinder lass
local scene = composer.newScene()
-- First, set a collision map and value for walkable tiles
local board = {
tiles = {},
walkable = 0,
map = {
{0,1,0,0,0},
{0,1,0,1,0},
{0,1,0,0,0},
{0,0,0,0,0},
}
}
local function createPath( startx, starty, endx, endy )
-- Creates a grid object
local grid = Grid( board.map )
-- Creates a pathfinder object using Jump Point Search
local myFinder = Pathfinder( grid, 'JPS', board.walkable )
-- Calculates the path, and its length
local path = myFinder:getPath( startx, starty, endx, endy )
return path
end
function scene:create( event )
local sceneGroup = self.view
local rowNum = #board.map
local colNum = #board.map[1]
local width = 40
local height = width
local margin = 5
local function touch( self, event )
local phase = event.phase
local endTile = event.target
if ( phase == 'began' ) then
board.startTile = endTile
elseif ( phase == 'moved' ) then
if board.startTile ~= endTile then
if ( board.endTile ~= endTile ) then
board.endTile = endTile
local path = createPath( board.startTile.col, board.startTile.row, board.endTile.col, board.endTile.row )
if path then
-- Remove old lines
display.remove( board.lines )
board.lines = nil
-- Create new line
board.lines = display.newLine( sceneGroup, board.startTile.x, board.startTile.y, board.startTile.x, board.startTile.y + 1 )
for node, count in path:nodes() do
local id = colNum * ( node:getY() - 1 ) + node:getX()
local tile = board.tiles[id]
board.lines:append( tile.x, tile.y )
end
end
end
else
-- Remove old lines
display.remove( board.lines )
board.lines = nil
board.endTile = nil
end
elseif ( phase == 'ended' or phase == 'cancelled' ) then
-- Remove old lines
display.remove( board.lines )
board.lines = nil
board.endTile = nil
board.startTile = nil
end
end
for i=1, rowNum do
for j=1, colNum do
local tile = display.newRect( sceneGroup, (width + margin ) * j, ( height + margin ) * i, width, height )
tile.col = j
tile.row = i
tile.touch = touch
-- Add listener and change color for walkable tile
if board.map[i][j] == board.walkable then
tile:addEventListener( 'touch' )
tile:setFillColor( 0, 0.5, 0.5 )
end
local id = colNum * ( i -1 ) + j
board.tiles[id] = tile
end
end
end
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if phase == 'will' then
elseif phase == 'did' then
end
end
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if event.phase == 'will' then
elseif phase == 'did' then
end
end
function scene:destroy( event )
local sceneGroup = self.view
end
scene:addEventListener( 'create', scene )
scene:addEventListener( 'show', scene )
scene:addEventListener( 'hide', scene )
scene:addEventListener( 'destroy', scene )
return scene