Buttons touch function problem

I was playing around with my button class and project, and decided to move the function of a touch of the button from the draw function into the touched(touch) function, and it stopped working. It will still work in the draw function, but I was just wondering why not the touched function.

--# Main
-- Button

-- Main

rectMode(RADIUS)
spriteMode(RADIUS)

function setup()
    
    --aloader = SpritelyLoader()
    --[[
    createbutton = loadstring( readProjectData("Button"))
    button = createbutton()
      ]]
    button = Images:getButton()
    
    buttonX = Button("X",WIDTH - 35,HEIGHT - 15,35,15,25,255,0,0,button,close)
    buttonKeyboardOpen = Button("Keyboard",WIDTH - 50,HEIGHT - 75,50,15,15,90,175,250,button,showKeyboard)
    buttonAlert = Button("Alert",WIDTH - 50,HEIGHT - 125,50,15,15,90,175,250,button,alert,"You pressed the alert button. Alert! Alert! Alert!")
    
    allButton = AllButton({buttonX,buttonKeyboardOpen,buttonAlert})
    
    parameter.watch("buttonAlert.pressed")
    parameter.watch("buttonAlert.released")
    
    
    
end

function touched(touch)
    
end

function draw()
    
    background(127, 127, 127, 255)
    
    -- Button
    buttonX:draw()
    buttonKeyboardOpen:draw()
    buttonAlert:draw()
    
    fill(255, 255, 255, 255)
    rect(WIDTH/2,HEIGHT/2,100,100)
    
    pushStyle()
    fill(255, 0, 0, 255)
    ellipse(CurrentTouch.x,CurrentTouch.y,10)
    popStyle()
    
end


--# Button
-- Button

Button = class()

function Button:init(name,x,y,width,height,fontsize,colourR,colourG,colourB,buttonImage,buttonFunction,buttonFunction01)
    
    self.name = name
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.fontsize = fontsize
    self.colourR = colourR
    self.colourG = colourG
    self.colourB = colourB
    self.buttonImage = buttonImage
    self.buttonFunction = buttonFunction
    self.buttonFunction01 = buttonFunction01
    self.buttonFunction02 = buttonFunction02
    self.buttonFunction03 = buttonFunction03
    self.buttonFunction04 = buttonFunction04
    
    self.pressed = "No"
    self.released = "No"
    
end

function Button:touched(touch)
    --if CurrentTouch.state == ENDED
    --then self.pressed = "No"
    --end
    if pressedField(self.x,self.y,self.width,self.height) == true then
        self.pressed = "Yes"
    end
    if releasedField(self.x,self.y,self.width,self.height) == true and self.pressed == "Yes" then
        
        self.released = "Yes"
        self.pressed = "No"
        else self.released = "No"
        self.pressed = "No"
    end
    
    if self.released == "Yes"
    then if self.buttonFunction01 == nil
        then self.buttonFunction()
            else
            if self.buttonFunction04 ~= nil
            then self.buttonFunction(self.buttonFunction01,self.buttonFunction02,self.buttonFunction03,self.buttonFunction04)
            end
            if self.buttonFunction03 ~= nil
            then self.buttonFunction(self.buttonFunction01,self.buttonFunction02,self.buttonFunction03)
            end
            if self.buttonFunction02 ~= nil
            then self.buttonFunction(self.buttonFunction01,self.buttonFunction02)
            end
            if self.buttonFunction01 ~= nil
            then self.buttonFunction(self.buttonFunction01)
            end
        end
    end
end

function Button:draw()
    
    pushStyle()
    tint(self.colourR,self.colourG,self.colourB,225)
    sprite(self.buttonImage,self.x,self.y,self.width,self.height)
    noTint()
    fill(255, 255, 255, 255)
    fontSize(self.fontsize)
    text(self.name,self.x,self.y)
    popStyle()
    
end

--# ButtonAll
-- ControllerAll

-- Forwards each touch event to all the controllers in the table
-- passed to the constructor
 
AllButton = class(Button)
 
function AllButton:init(button)
   self.button = button
end
 
function AllButton:touched(t)
   for _, c in pairs(self.button) do
       c:touched(t)
   end
end
 
function AllButton:draw()
   for _, c in pairs(self.button) do
       c:draw()
   end
end
 

--# Functions
-- Functions

function pressedField(x,y,width,height)
    if CurrentTouch.x <= x + width and CurrentTouch.x >= x - width and CurrentTouch.y <= y + height and CurrentTouch.y >= y - height and CurrentTouch.state == BEGAN
    then return true
    else return false end
end

function releasedField(x,y,width,height)
    if CurrentTouch.x <= x + width and CurrentTouch.x >= x - width and CurrentTouch.y <= y + height and CurrentTouch.y >= y - height and CurrentTouch.state == ENDED
    then return true
    else return false end
end

There is an image tab for the local image of the button, but unless you want to load this code up, it has no use.

Looking at the code under the Button class, there is a touched(touch) function containing some code. This code used to be at the end of the draw function for the button, where it works. It does not work while in the touched function. Should it be changed to fit in the touched function, or should it stay in the draw function?

Add self.button:touched(touch) to the body of the touched() function in main.

wow, can’t believe I didn’t do that. I must have been distracted really badly, then. :slight_smile:

Does it really need the (touched) bit in brackets? I normally don’t add that in.

BTW, it is still not working.

im not sure I understand your question?

It’s not self.button:touched(touch) you need to add to the touch function, but button.button:touched(touch)' or buttonX.button:touched(touch)', or the same for your other two buttons.

And as Seraph says, you need to check if the touch is on one of those buttons. There is quite a bit of code on the forum (and the internet) for doing that.

Yes, the self was my mistake, you weren’t in a class.

It also appears your images:getButton doesn’t exist in the snippet you gave us anyways, I downloaded and ran your code and buttonX:touched(touch) works, however the logic in pressedField() appears to be wrong, as neither it or releasedField are ever fired, so that’s probably your next problem.

Perhaps the best thing to do is add the buttons to a table, eg the Buttons class could have a table within it, like so

Button = class()
Button.list={}   ----NEW

function Button:init(...etc)
    table.insert(Button.list,self)   ---NEW
    --code as before

This shared table will hold addresses for all the button objects. Then you can check whether any of them have been touched, simply by adding this function in the Button class…

function Button.IfButtonPressed(touch)
    for _,b in pairs(Button.list) do
        if touch.x>=b.x and touch.x<=b.x+b.width and
           touch.y>=b.y and touch.y<=b.y+b.height then
                --do whatever button b requires, then
                return true --tells touched that we hit a button
        end
    end
    return false --if we got this far, no button was pressed, return false
end

…and putting this in the touched function

--if a button is pressed, it will be handled in the Button class, 
--and will return true, so nothing more to do here
--note we use a full stop not a colon to call this function
--because it does not belong to a particular button 
if Button.IfButtonPressed(touch) then return end --button was pressed
--no button touched, check for any other 
--touches if you want

Thanks for the help again, @Ignatz, and you to, @Serapth.

@CayDay47 - the benefit of a table like I suggested above is that it keeps your main code very simple, just a single line in the touched function, and it also makes it very easy to add or remove buttons without changing any code.

On thing leads to another… where does the touch.x and the touch.y come from? Sometimes, I also see t.x and t.y in the projects of others, which I assume has replaced the former.

have a look in the built in reference

I am aware of the built in reference, however when I use touch in code, or your raw example above, it doesn’t work.

@CayDay47 Here’s a simple example of a button.


displayMode(FULLSCREEN)

function setup()
    rectMode(CENTER)
    x=WIDTH/2
    y=HEIGHT/2
    w=100
    h=50   
    str1="" 
end

function draw()
    background(0)
    fill(255)
    rect(x,y,w,h)
    fill(255,0,0)
    text("Press here",x,y)
    text(str1,x,y+200)
end

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

@CayDay47 touch and t are just variable names, you could name them hippo or turnip if you wanted to. The name of the touch variable you’re using is defined in the parenthesis after your function name, i.e. function touched(name_of_touch_variable_here)

If I used touch in one project, would I have to use touch for every touch variable? Also, would the same apply for t?

I don’t understand your question. Could you explain a little more please?

What you do in one project has no effect on another project. You can use touched(t) in one project and touched(touch) in another or whatever name you want to use instead of t and touch.

I think what @CayDay47 is asking, is if the parameter names need to be the same across every project / tab / function - and the answer is no.

Imagine in one tab / project you have a function called touched

function touched(t)
    if t.state ... end
end

Then in a different project you could have

function touched(myTouch)
    if myTouch.state ... end
end

Providing you reference the named parameter consistently across each function it doesn’t matter what you call it - however most people use either “t” or “touch” by convention simply because it makes the code more readable and there is less likely hood of errors - because if you mis-spell myTouch for instance (ie mytouch or MyTouch) then Lua will most likely NOT report it as an error - it’ll just think you’re referencing a different global variable of that name and those bugs can be really hard to track down.

One last thing - regarding parameter names, consider the following…

function buttonPress(myTouch)
   print(myTouch)
end

function touched(t)
   print(t)
   buttonPress(t)
end

In this instance the touched function is called by Codea with a table representing the touch event that just happened - inside the touched function you refer to it via the parameter “t”, however when you call the buttonPress() function yourself you pass “t” as the parameter / argument to the buttonPress() function. However “inside” buttonPress() this value is referred to as “myTouch”, it’s still the same data (compare the output from above if you want to be sure), but it’s just the name that’s used inside the buttonPress() function to refer to it.

Careful naming of functions, parameters and variables can make all the difference between easy to read / use code and a hard to read / even harder to use pile of c***

Hope this helps.