I just started learning Lua and LOVE2D, I'm trying to make text input boxes, I've got 4 instances within an array and I'm trying to call their draw function within the love.draw()
TextBox = {
x = 0,
y = 0,
width = 256,
height = 64,
text = '',
active = false,
colors = {
background = { 186, 163, 182, 220 },
text = { 20, 20, 20, 255 },
border = { 48, 44, 50, 230 },
activeborder = { 236, 234, 115, 240 }
}
}
function TextBox:init(o, x, y)
local o = {}
o.parent = self
o.x = x
o.y = y
return o
end
function TextBox:draw_self()
-- Draw the box
love.graphics.setColor(unpack(TextBox.colors.background))
love.graphics.rectangle('fill',
textBoxArray[i].x, textBoxArray[i].y,
TextBox.width, TextBox.height)
...
end
main.lua :
function love.load()
...
textBoxArray = {}
for i=1,4 do
... -- Declaring xx and yy here
textBoxArray[i] = TextBox:init(nil, 40+xx, 40+yy)
end
end
function love.draw()
for i=1,4 do
textBoxArray[i]:draw_self()
end
end
I get an error when I try to call :draw_self(), :init() works just fine and I couldn't figure out what the issue might be. What's the proper way to call a method when the instance is within an array?
textBoxArray[i]:draw_self()is the correct way to call a "method" iftextBoxArray[i]has been set up properly:obj:method(...)is (roughly) just syntactic sugar forobj.method(obj, ...). That is, indexingobjwith the string"method"must return a method which takesobjas the first parameter.This isn't the case though; your constructor doesn't set a metatable. Let's take a look:
After this,
ohas fieldsx,yandparent. Accessing any other field will yieldnil. In particular,textBoxArray[i].draw_selfwill benilfor alli. You're thus trying to call anilvalue, which throws an error.o.parentdoesn't have any special effect (assuming you're not using an OOP library). Instead, the standard pattern is to doself.__index = selffollowed bysetmetatable(o, self). (There are various ways to vary this pattern. For example you might want to separate the metatable and the class table, and you might not want to do an "unnecessary"self.__index = selfin every constructor call. A nice property of this "standard pattern" is that it makes inheritance easy though.)Side note: The unused
oparameter doesn't make sense. If you want to allow passing an existing table, useo = o or {}rather thanlocal o = {}. Otherwise, just remove the parameter.Let's take a look at
draw_selfnow:The "method" is called
draw_self, yet you're operating on the globalTextBoxtable except for the usage oftextBoxArray[i]. Both of these should be completely replaced with usage ofself. Currently you're using method syntactic sugar (function TextBox:init(...)is equivalent toTextBox.init = function(self, ...)- it adds an implicitselfparameter) here despite not usingselfat all.Your
love.loadis fine. Yourlove.initis also fine except for theoquirk; depending on how you refactor your constructor, you'll probably want to remove the unusednilvalue.