Touch issue?

I must be doing something wrong in the touch function because it is throwing an error. Anybody know what needs to change? Ty in advance!

The draw function works but touching a tile throws this:

error: [string “Map = class()…”]:52: bad argument #1 to ‘pairs’ (table expected, got nil)

function setup()
    file = os.getenv("HOME").."/Documents/Dropbox.spritepack/map1.txt.png"
    BattleMap = Map(file)
end

function draw()
    background(0,0,0)
    BattleMap:draw()
end

function touched(touch)
    Map:touched(touch)
end

Map = class()

function Map:init(file)
    self.Tile = {}
    counter = 1
    io.input(io.open(file,"r"))

    for FileLine in io.lines() do
        print(i)
        local thistile = split(FileLine, ",")
        --self.Tile[counter] = {}
            
        local x = tonumber (thistile[1])
        local y = tonumber (thistile[2])
        local terrain = thistile[3]
        local cost = tonumber (thistile[4])
        local vp = thistile[5]
        local feature = thistile[6]
        local owner = thistile[7]
        --local rivern = thistile[8]
        --local rivere = thistile[9] 
        --local rivers = thistile[10]
        --local riverw = thistile[11]
        --local roadn = thistile[12]
        --local roade = thistile[13]
        --local roads = thistile[14]
        --local roadw = thistile[15]

        self.Tile[counter] = Tile(x, y, terrain, cost, vp, feature, owner)

        print(self.Tile[counter].x)
        print(self.Tile[counter].y)
        print(self.Tile[counter].terrain)
        print(self.Tile[counter].owner)
        
        counter = counter + 1
        self.tilecount = counter
    end
end

function Map:draw()
    counter = 1
    for i,v in pairs(self.Tile) do
        self.Tile[counter]:draw()

        counter = counter + 1
    end
end

function Map:touched(touch)
    counter = 1
    for i,v in pairs(self.Tile) do
        self.Tile[counter]:touched(touch)

        counter = counter + 1
    end
end

function split(str, div)
    if (div=='') then 
        return false
    end

    local pos,arr = 0,{}

    -- for each divider found
    for st,sp in function() return string.find(str,div,pos,true) end do
        -- Attach chars left of current divider
        table.insert(arr,string.sub(str,pos,st-1)) 
        pos = sp + 1 -- Jump past current divider
    end
    
    -- Attach chars right of last divider
    table.insert(arr,string.sub(str,pos)) 
    return arr
end

--draw horizontal lines of the grid
--for y=1,MapHeight,1 do
--    local line = display.newLine(1, y*SquareSize, SquareSize*MapWidth, y*SquareSize)
--    line:setColor( 255, 0, 0, 128)
--    line.width = 2
--    GameBoard:insert(line)
--end

--draw vertical lines of the grid
--for x=1,MapWidth,1 do
--    local line = display.newLine(x*SquareSize, 1, x*SquareSize, SquareSize*MapHeight)
--    line:setColor( 255, 0, 0, 128)
--    line.width = 2
--    GameBoard:insert(line)
--end

Tile = class()

function Tile:init(x, y, terrain, cost, vp, feature, owner)
    self.x = x
    self.y = y
    self.terrain = terrain
    self.cost = cost
    self.vp = vp
    self.feature = feature
    self.owner = owner
    self.imgpath = "Dropbox:" .. terrain
    self.image = readImage(self.imgpath)
end

function Tile:draw()
    sprite(self.image, self.x * 48, self.y * 48, 48, 48)
end

function Tile:touched(touch)
    if self:hit(touch.x, touch.y) and touch.state == ENDED then
        print("touched tile: " ..self.x..","..self.y) 
    end
end

function Tile:hit(point)
    if point.x > (self.x - self.width) and
       point.x < (self.x + self.width) and
       point.y > (self.y - self.height) and
       point.y < (self.y + self.height) then
    return true
    end        
    return false
end

@Gib I can’t run your code because of the file, but should Map:touched(touch) be BattleMap:touched(touch)

When you are looping through your tables you don’t need to explicitly put the counter in. This taken care of for you. For example in your map:draw function the variable v is the same as your self.Tile[counter] call. Use this instead:

    for i,v in pairs(self.Tile) do
        v:draw()
    end

@dave1707 Your right. But now since I changed it the error is:

error: [string “Tile = class()…”] 26: attempt to index local ‘point’ (a number value)

@West thanks I’ll fix that.

oh, self.width needs setting, i assumed that was an innate property of a thing :). I need to search for how to extract the height and width of my loaded sprite image. I think.

@Gib In function Tile:touched(touch) you’re calling self:hit( touch.x, touch.y), but function Tile:hit(point) only receives one variable. Change self:hit to self:hit(vec2(touch.x,touch.y)) .

@Gib Then you don’t have self.width and self.height defined in the Tile class.

@Gib You can do this in Tile:init

self.width=self.image.width  
self.height=self.image.height

Then you can use self.width and self.height in Tile:draw

@Gib Here are more changes that should work.


function Tile:draw()
    sprite(self.image,self.x*self.width,self.y*self.height,self.width,self.height)
end

function Tile:touched(touch)
    if touch.state==ENDED then
        if self:hit(vec2(touch.x, touch.y)) then
            print("touched tile: " ..self.x..","..self.y) 
        end
    end
end

function Tile:hit(point)
    if point.x > (self.x*self.width - self.width/2) and
       point.x < (self.x*self.width + self.width/2) and
       point.y > (self.y*self.height - self.height/2) and
       point.y < (self.y*self.height + self.height/2) then
    return true
    end        
    return false
end

@dave1707 Ah thanks! I understand now and its working great. :slight_smile: