0
votes

I kinda understand the basics of OOP with lua using metatables. but things get a little hairy when I am really intending to subclass a display object. I don't believe I can pass the display object itself into the setmetatable function. I'd really like to add extra functions to the display object directly.

for example.. here is my player.lua file

local player = {}
local player_mt = { __index = player }  -- metatable

function player.new( world )    -- constructor

    local obj = display.newRect( world, 0, 0, 20, 20 )
    obj:setFillColor( 1,0,0 )

    local tbl = { obj = obj }
    return setmetatable( tbl, player_mt )
end

function player:fillColor( r,g,b )
    self.obj:setFillColor( r,g,b )
end

function player:setPos( x,y )
    self.obj.x, self.obj.y = x,y
end

return player

this works out okay.. but I'd really like self to refer to my obj variable. When I'm using this "class" I always have to reference the display object by saying player.obj. I'd rather it was just player

any way of accomplishing this or better approaches?

just tried using my shape object directly and calling fillColor on my updated player object. says it cant call fillColor on nil

local player = {}
local player_mt = { __index = player }  -- metatable

function player.new( world )    -- constructor

    local obj = display.newRect( world, 0, 0, 20, 20 )
    obj:setFillColor( 1,0,0 )

    return setmetatable( obj, player_mt )
end

function player:fillColor( r,g,b )
    self:setFillColor( r,g,b )
end

return player
2
Is obj a table? A userdata? Something else? You can forward every non-matching lookup from tbl to obj with your metatable if that's what you want. - Etan Reisner
Then yes you probably can't pass that to setmetatable. You can use __index (or __index chains) to allow for ply:setFillColor(...) to work though ensuring you get the right object passed to the right function with such a chain can be complicated. - Etan Reisner
" I don't believe I can pass the display object itself into the setmetatable function." Have you tried? - Mud
Yes I tried. When calling self on the display object within other methods I get errors. Did you try? - hamobi

2 Answers

1
votes

Try creating like this,

local player= {}

function player.new(params)

  local self = {}
  setmetatable(self, {__index = player})

   local obj = display.newRect( world, 0, 0, 20, 20 )
   obj:setFillColor( 1,0,0 )

  self._obj  = obj  
  return self 
end


function player:fillColor( r,g,b )
  self._obj:setFillColor( r,g,b )
end

return player
0
votes

this is the best way ive found so far of extending the display object directly

local new
local sayName

sayName = function( self )
    print( self.name )
end

new = function( world )
    local player = display.newRect( world, 0, 0, 20, 20 )
    player:setFillColor( 1,0,0 )
    player.name = 'bob'

    player.sayName = sayName
    return player
end

local public = {}
public.new = new
return public