Problem with "rec()" not recognizing self variables

Title explains everything
here’s my code:

player = class()

function player:load()
    self.position = vec2(WIDTH/2, HEIGHT/2)
    self.diameter = 20
end

function player:update()
    self.y = 1
    self.x = 1
end

function player:draw()
    pushStyle()
    noStroke()
    fill(255, 255, 255, 255)
    rectMode(CENTER)
    rect(self.x, self.y, self.diameter, self.diameter)
    popStyle()
end

Output log says
Player:20: Bad argument #1 to ‘rect’ (number expected, got nil)

but when I replace the self variables with numbers I get a correctly drawn rectangle

player:load() should be player:init()

@Exyon You didn’t provide any code on how you’re using the player class. Here’s some code to use your player class. Also, I added a playerA class to show how I think the class should be used. You were probably getting errors because you weren’t setting self.x and self.y to any values. Without seeing all your code, I can’t say what you were doing wrong.

viewer.mode=FULLSCREEN

function setup()  
    p1=player()
    p1:load()
    p1:update()  
    
    p2=playerA()    
end

function draw()
    background(0)
    p1:draw()
    p2:draw()
end

player = class()

function player:load()
    self.position = vec2(WIDTH/2, HEIGHT/2)
    self.diameter = 20
end

function player:update()
    self.y = 100
    self.x = 100
end

function player:draw()
    pushStyle()
    noStroke()
    fill(255,0,0)
    rectMode(CENTER)
    rect(self.x, self.y, self.diameter, self.diameter)
    popStyle()
end



playerA = class()

function playerA:init()
    self.position = vec2(WIDTH/2, HEIGHT/2)
    self.diameter = 20
end

function playerA:draw()
    pushStyle()
    noStroke()
    fill(0,255,0)
    rectMode(CENTER)
    rect(self.position.x, self.position.y, self.diameter, self.diameter)
    popStyle()
end

There was about 2 other erros after that one lol
Got them all fixed though, thank you
The problem was that I didn’t have player:update in the draw function.
I don’t understand the problem though, did it not recognize the self because it wasn’t in the same main function, or because it was only being called once in setup and the rest of the frames it was set to nil?

oh and how do I create layers?
A later in the front for buttons and one in the back for character and background?

@Exyon It didn’t recognize self.x or self.y because as you said, you didn’t call player:update. You don’t really create layers, you just draw them in the order you want them to appear. If you want something to appear over something else, whatever you draw first is behind what you draw last.

@dave1707 so i’ll draw my buttons first, then my scene?
Also, when creating a function like;

function box(a)
      line(a.x, a.y, a.x + a.width, a.y + a.height)
end

how do I find “a” x and y values?

and height, width ?

@Exyon Heres an example showing your box using a.x, a.y, a.width, and a.height and an easier way to draw a box (boxA). If you want your buttons to be on top of your scene, draw your scene first, then your buttons.

viewer.mode=STANDARD

function setup()  
    stroke(255)
    strokeWidth(2)
end

function draw()
    background(0)
    
    box({x=200,y=200,width=100,height=100})
    
    boxA(300,400,100,100)
end

function box(a)
    line(a.x, a.y, a.x, a.y + a.height)
    line(a.x, a.y, a.x + a.width, a.y)
    line(a.x+a.width, a.y, a.x+a.width, a.y+a.height)
    line(a.x, a.y+a.height, a.x+a.width, a.y+a.height)
end

function boxA(x,y,w,h)
    noFill()
    rect(x,y,w,h)
end

@Exyon Here’s an example of putting buttons over a scene using a class. Press each button.

viewer.mode=STANDARD

function setup()  
    rectMode(CENTER)
    pressed=""
    b1=button(WIDTH/2,400,100,50,"Button 1")
    b2=button(WIDTH/2,200,100,50,"Button 2")
end

function draw()
    background(0)
    sprite(asset.builtin.Cargo_Bot.Startup_Screen,WIDTH/2,HEIGHT/2)
    b1:draw()
    b2:draw()
    text(pressed,200,300)
end

function touched(t)
    b1:touched(t)
    b2:touched(t)
end

button=class()

function button:init(x,y,w,h,t)
    self.x=x
    self.y=y
    self.w=w
    self.h=h
    self.txt=t
end

function button:draw()
    fill(255, 136, 0)
    rect(self.x,self.y,self.w,self.h)
    fill(255)
    text(self.txt,self.x,self.y)    
end

function button:touched(t)
    if t.state==BEGAN then
        if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
                t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
            pressed=self.txt.." pressed"
        end                
    end
    if t.state==ENDED then
        pressed=""
    end
end

@dave1707 That’s a little helpful, what i’m trying to do is draw a box around a selected object, for example.

a would be the button in collision

function collision(a)
    if a.x + a.width > CurrentTouch.x and a.x < CurrentTouch.x and a.y + a.height > CurrentTouch.y and a.y < CurrentTouch.y
    return true else
        return false
    end
end

function box(a)
    strokeWidth(10)
    stroke(255, 0, 0)
    line(a.x, a.x + a.width, a.y, a.y + a.height)
end

function buttons:draw()
    self.img = readImage(asset.builtin.UI.Grey_Slider_Up)
    Up = mesh()
    Up.texture = self.img
    Up:addRect(self.x,self.y + 50,24,24)
end

if collision(Up) == true then
    box(Up):draw()
end

this isn’t the code im using but it’s what i want
there might be some wrong things with it
but simplified, I just want the collision function to have a box around (A) and detect if a touch position is inside it, then if it is, draw a box around it

@Exyon I don’t understand what your code is trying to do or what you’re trying to do. You say you want a box around A, then if a touch is inside the box, draw a box around it. Can you explain more of what you’re trying to do.

@dave1707 yes sorry, i want a function to detect when the touch x and y position are inside an object, and if it is, i want a box to be draw around it. Doesn’t have to draw a box around itself, it just has to output a true or false.

@Exyon Here’s something. Tap inside the box. Tap outside to clear.

viewer.mode=FULLSCREEN

function setup()  
    rectMode(CENTER)
    x,y=WIDTH/2,HEIGHT/2
    tx,ty=0,0
    xv,yv=2,2
    stroke(255)
    strokeWidth(2)
    noFill()
end

function draw()
    background(0)
    sprite(asset.builtin.Planet_Cute.Character_Horn_Girl,x,y)
    rect(x,y,100,100)
    x=x+xv
    y=y+yv
    if x<1 or x>WIDTH then
        xv=-xv
    end
    if y<1 or y>HEIGHT then
        yv=-yv
    end
    if z then
        rect(x,y,120,120)
    end
end

function touched(t)
    if t.state==BEGAN then
        z=false
        if t.x>x-50 and t.x<x+50 and t.y>y-50 and t.y<y+50 then
            z=true
        end
    end
end

Yes perfect, thank you. I’ll let you know how it goes

@dave1707 Well, new problem. I have 4 buttons, I need a single function that I can add to every button, doesn’t need to draw a box around them, just need to output true or false. I tried your example but in order to use it i would need a class for each button. I need something more compact
here’s how my buttons are made-

buttons = class()

function buttons:init()
    self.x = WIDTH/4 - 50
    self.y = HEIGHT/4 + 25
    self.size = 40
end

function buttons:draw()
    
    self.img = readImage(asset.builtin.UI.Grey_Slider_Up)
    
    Up = mesh()
    Up.texture = self.img
    Up:addRect(self.x,self.y + 50,24,24)
    
    Down = mesh()
    Down.texture = self.img
    Down:addRect(self.x,self.y - 50,24,24,3.15)
    
    Right = mesh()
    Right.texture = self.img
    Right:addRect(self.x + 50,self.y,24,24,-1.55)
    
    Left = mesh()
    Left.texture = self.img
    Left:addRect(self.x - 50,self.y,24,24,1.55)
    
    
    Up:draw()
    Down:draw()
    Right:draw()
    Left:draw()
    

btw, I liked how simple you made the girl bounce around the screen on your example

@Exyon You don’t need a class for each button. A button class works for 1 to how many buttons you need. Here’s that class for 4 buttons, up, down, left, right.

viewer.mode=FULLSCREEN

function setup()
    rectMode(CENTER)
    pressed=""
    up=button(WIDTH/2,400,100,50,"Up")
    down=button(WIDTH/2,200,100,50,"Down")
    left=button(WIDTH/2-100,300,100,50,"Left")
    right=button(WIDTH/2+100,300,100,50,"Right")
end

function draw()
    background(0)
    up:draw()
    down:draw()
    left:draw()
    right:draw()
    text(pressed,WIDTH/2,HEIGHT-200)
end

function touched(t)
    up:touched(t)
    down:touched(t)
    left:touched(t)
    right:touched(t)
end

button=class()

function button:init(x,y,w,h,t)
    self.x=x
    self.y=y
    self.w=w
    self.h=h
    self.txt=t
end

function button:draw()
    fill(255, 136, 0)
    rect(self.x,self.y,self.w,self.h)
    fill(255)
    text(self.txt,self.x,self.y)
end

function button:touched(t)
    if t.state==BEGAN then
        if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
        t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
            pressed=self.txt
        end
    end
    if t.state==ENDED then
        pressed=""
    end
end

@dave1707 Wow you’re awesome, very quick. I only need 4 buttons, but if i need more i’ll use your example. how would I use a picture for a button?

@Exyon Instead of using rect and text, use sprite to show the picture. Of course you’ll have to adjust the picture to the size you want.

@Exyon Here’s the above code using sprites.

viewer.mode=FULLSCREEN

function setup()
    rectMode(CENTER)
    pressed=""
    up=button(WIDTH/2,400,60,60,"up",asset.builtin.Cargo_Bot.Command_Grab)
    down=button(WIDTH/2,200,60,60,"down",asset.builtin.Cargo_Bot.Command_Grab)
    left=button(WIDTH/2-100,300,60,60,"left",asset.builtin.Cargo_Bot.Command_Left)
    right=button(WIDTH/2+100,300,60,60,"right",asset.builtin.Cargo_Bot.Command_Right)
end

function draw()
    background(0)
    up:draw(-50)
    down:draw(50)
    left:draw(50)
    right:draw(50)
    text(pressed,WIDTH/2,HEIGHT-200)
end

function touched(t)
    up:touched(t)
    down:touched(t)
    left:touched(t)
    right:touched(t)
end

button=class()

function button:init(x,y,w,h,t,i)
    self.x=x
    self.y=y
    self.w=w
    self.h=h
    self.txt=t
    self.img=i
end

function button:draw(v)
    sprite(self.img,self.x,self.y,v)
end

function button:touched(t)
    if t.state==BEGAN then
        if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
        t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
            pressed=self.txt
        end
    end
    if t.state==ENDED then
        pressed=""
    end
end