Trying to make a table of tile objects and draw each one...

Right now I’m getting “Attempt to perform arithmetic on field “WIDTH” (a nil value)”:

tile = class()
function tile:init(x,y)

 self = {}

self.x = x;

self.y = y;

self.WIDTH = 128

self.HEIGHT = 128

self.draw = tile:draw()

return self

end


function tile:draw()
rect(self.x-self.WIDTH/2, self.y-self.HEIGHT/2, self.WIDTH, self.HEIGHT
end


-- then, outside...

for k = 1, 6 do
    table.insert(self.table, tile:init(12,12))
end

for i, v in ipairs(table) do
    tile:draw()
end

on self.x-self.WIDTH the highlighting disappears… does this mean I’m not allowed to modify those variables?

I just can’t figure this out…



--# Main
function setup()
    tbl = {}
    for k = 1, 6 do
        local tiles = tile(math.random(0,WIDTH),math.random(0,HEIGHT))
    table.insert(tbl, tiles)
end
end

function draw()

for i, v in pairs(tbl) do
    print("table draw"..i)
    tbl[i]:draw()
end

end
--# Test
tile = class()
function tile:init(x,y)



self.x = x;

self.y = y;

self.width= 128

self.height = 128



--return self

end


function tile:draw()
rect(self.x-self.width/2, self.y-self.height/2, self.width, self.height)
end


-- then, outside...

are you sure about commenting out the return self?

If I don’t have the tile set its self to {}, I just get six of the same tile… and if I don’t return self, nothing works

Oh! No class:init(), just class().

Is that a standard Lua feature?

Assigning tiles = tile(x,y) creates an instance of the class and calls init(). So you create a table with instances of class tile.

When a class function is called, say mytile:doSomething(args), then the actual function called is tiles.doSomething(mytile,args). Within the function, the mytile becomes the self variable. This is local to the function, but because it is a table then any assignments to it “just work”.

That is to say, if your code is:

a = class()

function a:init()
end

function a:doSomething(x)
    self.x = x
end

b = a()
b:doSomething(3)
print(b.x)

then at the call b:doSomething(3) what actually is called is a.doSomething(b,3). Inside doSomething, self points to the same table that b points to and thus self.x = 3 updates the x entry of bs table. Thus b.x is now 3 and so the print statement outputs 3.

Now what if we change the code of a:doSomething to:

function a:doSomething(x)
    self = {}
    self.x = x
end

When this is called, self points to the same table as b. But the first line self = {} now reassigned self to point to a new table. This new table gets its x value set to 3 but because the link between self and b is broken, nothing happens to b.

Okay, so that’s why the self = {} line shouldn’t be there.

Incidentally, the return value of an init function is discarded so return self doesn’t do anything.

Next, self.draw = tile:draw(). This actually invokes tile:draw! What you probably wanted here was self.draw = tile.draw, except that you didn’t need this at all because without the self = {} then self.draw is already set to tile.draw.

Then as Briarfox says, calling tile(x,y) invokes tile:init(x,y) automatically and also does some extra stuff which isn’t done if you call the init function itself.