Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Problem with "rec()" not recognizing self variables

in Questions Posts: 31

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

Comments

  • Posts: 565

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

  • dave1707dave1707 Mod
    Posts: 8,671

    @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
    
  • edited November 20 Posts: 31

    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?

  • Posts: 31

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

  • dave1707dave1707 Mod
    Posts: 8,671

    @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.

  • Posts: 31

    @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?

  • Posts: 31

    and height, width ?

  • dave1707dave1707 Mod
    Posts: 8,671

    @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
    
  • dave1707dave1707 Mod
    Posts: 8,671

    @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
    
  • Posts: 31

    @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

  • dave1707dave1707 Mod
    Posts: 8,671

    @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.

  • Posts: 31

    @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.

  • dave1707dave1707 Mod
    edited November 21 Posts: 8,671

    @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
    
  • Posts: 31

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

  • edited November 21 Posts: 31

    @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

  • dave1707dave1707 Mod
    Posts: 8,671

    @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
    
  • Posts: 31

    @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?

  • dave1707dave1707 Mod
    Posts: 8,671

    @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.

  • dave1707dave1707 Mod
    Posts: 8,671

    @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
    
  • Posts: 31

    @dave1707 Hi sorry, was already midnight for me by the time i got to creating sprites for the button. I got it working in the end tho. So now I need help with something else, the four buttons will move my main character up, down, left and right, but I need the characters to stay centered in the middle of the screen. I looked into the translate() and push/pop matrix, but for some reason the whole screen moves, and all at different speeds. could you provide an example with the buttons moving the character around a scene with the character centered? thanks

  • dave1707dave1707 Mod
    Posts: 8,671

    Here’s a scrolling background. Also, you don’t have to lift your finger as you move it from button to button.

    viewer.mode=FULLSCREEN
    
    function setup()
        dx,dy=WIDTH/2,HEIGHT/2
        pressed=vec2(0,0)
        up=button(WIDTH/2,150,60,60,0,-1,asset.builtin.Cargo_Bot.Command_Grab)
        down=button(WIDTH/2,50,60,60,0,1,asset.builtin.Cargo_Bot.Command_Grab)
        left=button(WIDTH/2-50,100,60,60,1,0,asset.builtin.Cargo_Bot.Command_Left)
        right=button(WIDTH/2+50,100,60,60,-1,0,asset.builtin.Cargo_Bot.Command_Right)
        img=image(2000,2000)
        stroke(255)
        strokeWidth(2)
        setContext(img)
        background(0)
        for z=1,2000,50 do
            line(z,0,z,2000)
            line(0,z,2000,z)
        end
        for z=1,50 do
            sprite(asset.builtin.Platformer_Art.Coin,math.random(2000),math.random(2000))
        end
        setContext()
    end
    
    function draw()
        background(0)
        pushMatrix()
        translate(dx,dy)
        sprite(img,0,0)
        translate()
        popMatrix()
        sprite(asset.builtin.Platformer_Art.Guy_Standing,WIDTH/2,HEIGHT/2)
        up:draw(-50)
        down:draw(50)
        left:draw(50)
        right:draw(50)
        dx=dx+pressed.x
        dy=dy+pressed.y
    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,dx,dy,i)
        self.x=x
        self.y=y
        self.w=w
        self.h=h
        self.dir=vec2(dx,dy)
        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 or t.state==CHANGED 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.dir
            end
        end
        if t.state==ENDED then
            pressed=vec2(0,0)
        end
    end
    
  • Posts: 31

    wow, perfect. you've probably made over 60% of my game so far haha. I'll credit you in it.

  • Posts: 31

    @dave1707 Hi, finally finished drawing all my sprites, and got everything working how i wanted it to. I wanted to share how it looks for you, how and where do I do it?

  • dave1707dave1707 Mod
    Posts: 8,671

    @Exyon You can post it here for everyone to see. If you don’t want to post it, then that’s OK.

  • Posts: 31

    @dave1707 It says " "FullSizeRender.mov" is not allowed. "

  • dave1707dave1707 Mod
    Posts: 8,671

    @Exyon You didn’t say it was a movie. I thought you would post code. In that case you don’t have to post anything.

  • Posts: 31

    @dave1707 Ohh, then you'd have to download the sprites i used as well.

  • Posts: 31

    I might also give away my code because I'll be moving to unity. don't think anyone would want it though haha

  • dave1707dave1707 Mod
    Posts: 8,671

    Nice job rotating the character as he moves. That would be a nice beginning for anyone who wants to make a game with it if you give it away.

  • Posts: 31

    @dave1707 Thanks! I'll clean it up a bit, might see if i can implement an item and inventory system, and stop there

Sign In or Register to comment.