I get the same error each time I try to run a project

This is my (less fleshed out with comments) class file:

function block:init(x,y)

self.x = x

self.y = y

end

function block:draw()

fill(…)

rect(self.x, self.y,10,10)

end

I can create an instance of block, but when I try to call it’s draw() function in the main draw() it gives me two copies of the same error saying saying:
‘[string “block = class()…”]:17:attempt to index local ‘self’ (a nil value)
Pausing playback’

What is going on? I can’t see any errors.

Cheers guys.

PS. It is being called with the parameters 30 and 30 in the setup() function.

Let me know if I left out anything important!

Edit: I added linebreaks for readability, is there anything like a [code] tag on these here forums?

*When I say every time I try to run a project, I mean I try to run any of my own projects! :smiley:

Also is there any documentation on the library which you’re using for classes? Apart from the bitbucket documentation which is pretty much unreadable at the moment D:

The following should work, does your code look something like this?

Block class file:


block = class()

function block:init(x,y)
    self.x = x
    self.y = y
end

function block:draw()
    fill(255,0,0)
    rect(self.x, self.y,10,10)
end

Main class file


function setup()
    b = block(30,30)
end

function draw()
    background(0)
    b:draw()
end

Ahhh I see my problem! I’ve been trying to call the method using the . operator, like in C++!

Thanks Simeon! Nick Falkner recommended Codify to me; so far it’s amazing :smiley:

Thanks Tempest! Nick was one of my lecturer’s at Adelaide :slight_smile:

The : operator passes the object into the function as “self,” which is why you get the “self is nil” error when using the . operator.

You can think of this:


function block:draw()
    rect( self.x, self.y, 10, 10 )
end

-- Calling draw...

b.draw() 

As equivalent to this:


function block.draw( self )
    rect( self.x, self.y, 10, 10 )
end

-- Calling draw...

b.draw( b ) 

It’s not technically equivalent, as “b” isn’t evaluated twice, as it is in the latter case. But it is very similar.

I’m facing a similar puzzle. In the Bit Invader example, the StreamingLines class does the following:
(a) in Init(), creates an empty table called self.lines
(b) in Update(), uses table.insert(self.lines,StreamLine()) to populate the table with instances of the StreamLine class.
(c) in various places uses the idiom
for i,v in ipairs(self.lines) do
v:foo()
end
to do something to each instance of StreamLine

When I try to exactly parallel these steps in my own project I get the “self is nil” error when I get to step (c). Any idea what code in Bit Invader, not included in the above, keeps this error from happening over there?

Are you perhaps calling a method with dot (.) instead of colon (:). That is

myObject.method() -- "self is nil" error

myObject:method() -- OK

Well it was a different typo, but the net effect was the same.
Appologies for making a mountain out of a molehill.

@KIM - this looks ok to me - please post the code that calls the class as well

Btw, you can format your code with three ~ on the line before, and the line after the code

Sorry!

Calling class

function MainMenu:init()
    btnStart = Button("Start Game", WIDTH/2, HEIGHT/2)
end

function MainMenu:draw()
    btnStart:draw()
end

I added print statements in the Button:init routine showing that the values are being added.
I don’t see anything wrong except the text isn’t in the box. You have to change textMode or rectMode.


function setup()
    btnStart = Button("Start Game", WIDTH/2, HEIGHT/2)
end

function draw()
    background(40,40,50)
    btnStart:draw()
end

Button=class()

function Button:init(name, x, y)
    self.x = x 
    self.y = y 
    self.name = name 
    fontSize(20) 
    self.width, self.height = textSize(self.name)
    print("original",self.width,self.height) 
    self.width = self.width + 22 -- won't add this 22 pixels 
    self.height = self.height + 15 -- same won't add 15 pixels 
    print("added",self.width,self.height) 
end
 
function Button:draw() 
    fontSize(20) 
    fill( 0, 0, 0, 100) 
    rect( self.x, self.y, self.width, self.height) -- works but as I said without added pixels to width and height 
    fill( 255, 255, 255, 255) 
    text(self.name, self.x, self.y) 
end
 
function Button:checkIn(x,y) 
    cx = self.x -- can't see self.x. It's saying that it is a nil value 
    cy = self.y -- same as x 
    ch = self.height/2 -- trying to do math on nil value 
    cw = self.width/2 -- same ... nothing important is next 
end

I have a similar problem. In button class I have

function Button:init(name, x, y) self.x = x self.y = y self.name = name fontSize(20) self.width, self.height = textSize(self.name) self.width = self.width + 22 -- won't add this 22 pixels self.height = self.height + 15 -- same won't add 15 pixels end
function Button:draw() fontSize(20) fill( 0, 0, 0, 100) rect( self.x, self.y, self.width, self.height) -- works but as I said without added pixels to width and height fill( 255, 255, 255, 255) text(self.name, self.x, self.y) end
function Button:checkIn(x,y) cx = self.x -- can't see self.x. It's saying that it is a nil value cy = self.y -- same as x ch = self.height/2 -- trying to do math on nil value cw = self.width/2 -- same ... nothing important is next end
please can you help me? Why it won’t work?
sorry for prev post

I have rectMode(CENTER) in Button:draw() before rect. I don’t know why it won’t use in draw function the same width and height as it is on the end of init function.

Would like to know why in checkIn function I can’t declare cx with self.x :frowning:

ok… found the problem with width and height… my bad… had to declare font(face) befor checking size of it

but still don’t know why can’t declare cx with self.x :confused:
gettin
error: [string “Button = class()…”]:34: attempt to index local ‘self’ (a number value)

where 34 line is right now print(self.x) in checkIn before cx declaration

Ok… Found a solution or just wrote it right now

Here is my Button Class (still working on it)

Button = class()

function Button:init(name, x,y, col, width, height)
    self.x = x
    self.y = y
    self.name = name
    self.state = "NORMAL"
    fontSize(20)
    font("Copperplate-Bold")
    self.width, self.height = textSize(self.name)
    self.width = self.width + 45
    self.height = self.height + 15
end

function Button:draw()
    fontSize(20)
    fill(0, 0, 0, 100)
    rectMode(CENTER)
    rect(self.x, self.y, self.width, self.height)
    fill(255,255,255,255)
    text(self.name,self.x, self.y)
end

function Button:touched(touch)
    if (Button:checkIn(touch.x, touch.y, self.x, self.y, self.width, self.height)) then
        if (touch.state == BEGAN) then
            print("Began by " .. self.name)
        elseif (touch.state == MOVING) then
            print("Moving by " .. self.name)
        elseif (touch.state == ENDED) then
            print("Ended by " .. self.name)
        end
    end
end

function Button:checkIn(x,y,sx,sy,w,h)
     if( x > (sx - w/2) and y > (sy - h/2) and x < (sx + w/2) and y < (sy + h/2)) then
        return true
    else
        return false
    end
end

I had to pass self.x, self.y, self.width and self.height variables to the checkIn function and now it’s working as it should

Anyway thanks for help :slight_smile:

In the main class you were using . instead of :?

Anyways, try and not bump dead threads, if you have a question like this and the only places where they’ve been asked were over a month ago, don’t bother and just make a new thread.