Howdy, Stranger!

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

Button Class with Sprites

edited July 2012 in Code Sharing Posts: 18

Hello all,
Just thought I'd show what I have for a button class that uses sprites and open it up for improvements or suggestions. Anything would be appreciated. I used some methods from @Reefwing's button tutorial. I hope it's all right :)

Button = class()

function Button:init(btnNorm,btnSel,x,y)
    self.pos = vec2(x,y)
    self.btnNorm = btnNorm
    self.btnSel = btnSel
    self.selected = false
    self.action = nil
    self.w,self.h = spriteSize(self.btnNorm)
end

function Button:draw()
    if self.selected == true then
        sprite(self.btnSel,self.pos.x,self.pos.y,self.w,self.h)
    elseif self.selected == false then
        sprite(self.btnNorm,self.pos.x,self.pos.y,self.w,self.h)
    end
end

function Button:touched(touch)
    if touch.state == BEGAN or touch.state == MOVING then
        if math.abs(self.pos.x - touch.x) <= (self.w/2)
        and math.abs(self.pos.y - touch.y) <= (self.h/2) then
            self.selected = true
        else
            self.selected = false
        end
    elseif touch.state == ENDED then
        if self.selected == true and self.action then
            self.action()
        end
        self.selected = false
    end
end

And here's a little example

-- Use this function to perform your initial setup
function setup()
     print("Hello World!")
     button = Button("Planet Cute:Chest Closed","Planet Cute:Chest Open",WIDTH/2,HEIGHT/2)
     button.action = function() buttonPressed() end
end

function draw()
     -- This sets a dark background color
     background(40, 40, 50)
     button:draw()
end

function buttonPressed()
     print("Button pressed")
end

function touched(touch)
     button:touched(touch)
end

EDIT: Juuuuuust kidding.
Again, any improvements or suggestions are more than welcome.

Comments

  • Posts: 580

    @ChrisF: you can use Codea's spriteSize() function to get the dimensions of a sprite.

  • Posts: 18

    @toadkick Thanks. I did not see that in there. That was far too simple haha.

  • edited July 2012 Posts: 580

    Heh, don't mean to be a pain but you got a bug in your revision...w and h are globals, which is probably not what you want. You probably want to do:

    self.w, self.h = spriteSize(self.btnNorm)
    

    As well as fix any references to them everywhere else.

  • Posts: 18

    Oh no problem. Thanks for your help

  • Posts: 563

    @ChrisF - copying the examples and extending or improving the code is exactly what it is there for. @Simeon wrote the button class, I was just explaining how it works. I will link in this post from the Tutorial so that other people learning can see another approach. That is the beauty of coding, there are lots of ways to skin that cat and the search for the most elegant solution is never ending.

    However, you do raise an interesting point. Is the code on these forums and elsewhere released under any particular licence? I'm assuming it is the DWTHYLWMCJDSM licence (Do What The Hell You Like With My Code Just Don't Sue Me) but perhaps it should be explicitly stated somewhere (if it isn't already). There is probably not too much code being written to run Nuclear Reactors using Codea (yet), so the risk is low but nevertheless...

  • Posts: 123

    Thanks ChrisF, thats what I was looking for. i extended the code a bit to have a matrix of buttons, e.g. As level selector. Maybe its useful for somebody:


    Button = class() function Button:init(btnNorm,btnSel,x,y,sizex, sizey)     self.pos = vec2(x,y)     self.btnNorm = btnNorm     self.btnSel = btnSel     self.selected = false     self.action = nil     --self.w,self.h = spriteSize(self.btnNorm)     self.w = sizex     self.h = sizey end function Button:draw()     if self.selected == true then         sprite(self.btnSel,self.pos.x,self.pos.y,self.w,self.h)     elseif self.selected == false then         sprite(self.btnNorm,self.pos.x,self.pos.y,self.w,self.h)     end end function Button:touched(touch)     if touch.state == BEGAN or touch.state == MOVING then         if math.abs(self.pos.x - touch.x) <= (self.w/2)         and math.abs(self.pos.y - touch.y) <= (self.h/2) then             self.selected = true         else             self.selected = false         end     elseif touch.state == ENDED then         if self.selected == true and self.action then             self.action()         end         self.selected = false     end end -- Use this function to perform your initial setup function setup()      buttons = {}      local button      xPos = 100      for x = 1, 7 do         yPos = 100         for y = 1, 5 do             button = Button("Planet Cute:Chest Closed","Planet Cute:Chest Open",xPos, yPos, 70, 70)             button.action = function() buttonPressed(x, y) end             table.insert(buttons, button)             yPos = yPos + 80         end         xPos = xPos + 80     end end function draw()      -- This sets a dark background color      background(40, 40, 50)     for i = 0, table.maxn(buttons) do         if buttons[i] == nil then         else             buttons[i]:draw()         end     end end function buttonPressed(x, y)      print(string.format("Button pressed %i, %i", x, y)) end function touched(touch)     for i = 0, table.maxn(buttons) do         if buttons[i] == nil then         else             buttons[i]:touched(touch)         end     end end
  • Posts: 18

    @KilamMalik That's interesting. I was actually looking to do the same thing when I had the chance. You made it much easier. Thanks

  • Posts: 77

    @KilamMalik How can you put in each box a random number in the table?

  • Posts: 123

    I dont quite understand your question. In which table do you want a random number?

  • Posts: 77

    @kilamMalik .. To every Button a random number. For example open 5 Buttons and add The Numbers together. The max number wins.

  • Posts: 77

    if one assigns a random number to each box and on opening the box, this number is displayed you can create a game of it.

  • Posts: 123

    Ok, understand. You can add a variable with the number in the button class. In the render function of the button you draw the nimber over the button.

  • Posts: 226

    Nice! With your ideas, I would like to do something like letting out of the treasure box a sprite for using it later, like position it on different places any time... But I'm a newbie... and I hope I'll find the way soon. :-D

  • Posts: 77

    Bellow is an example of two Players

    -- Star selection matox
    -- 
    
    -- Use this function to perform your initial setup
    function setup()
        show1 = 0
        show2 = 0
        show3 = 0
        show4 = 0
        a = 0; c = 0
        b = 0; d = 0
        e = 0; f = 0
        hit = 0
        rects = {}
        w,h = spriteSize("SpaceCute:Star")
        
        for i = 1, 4 do
          rects[i] = {}
          rects[i].x = 100 * i * 1.5
          rects[i].y = 200
          rects[i].id = i
          rects[i].p = math.random(100)
        end
     end  
    
    -- This function gets called once every frame
    function draw()
        -- This sets a dark background color 
        background(40, 40, 50)
    
        -- This sets the line thickness
        strokeWidth(5)
    
        -- Do your drawing here
        drawSprite()
        font("Georgia")
        fontSize(50)
        fill(255)
        text("1. Player           2. Player", 300, 700)
        text(show1,150,600)
        text(show2,450,600)
        text(show3,150,500)
        text(show4,450,500)
        line(100,450,700,450)
        text(e,150,400)
        text(f,450,400)
    end
    
    function drawSprite()
        for i = 1, #rects do
            sprite("SpaceCute:Star", rects[i].x,rects[i].y,80,100)
        end
    end
            
    function touched(touch)
        local TouchX = CurrentTouch.x
        local TouchY = CurrentTouch.y
        if touch.state == ENDED then
            local toRemove = {}
               for i = 1, #rects do
                if TouchX >= (rects[i].x - (w/2))and 
                    TouchX <= (rects[i].x + (w/2)) and 
                    TouchY >= (rects[i].y - (h/2)) and 
                    TouchY <= (rects[i].y + (h/2)) then
                    print(rects[i].id,rects[i].p)
                    hit = hit + 1
                    if hit ==1 then
                        show1 = (rects[i].p)
                    elseif hit == 2 then
                        show2 = (rects[i].p)
                    elseif hit == 3 then
                        show3 = (rects[i].p)
                    elseif hit == 4 then
                        show4 = (rects[i].p)   
                    end
                    a = show1
                    b = show2
                    c = show3
                    d = show4
                    e = a + c
                    f = b + d
                    table.insert(toRemove, i)
                end
            end
            for i = 1, #toRemove do
                table.remove(rects,toRemove[i])
            end
        end
    end
    
  • edited December 2013 Posts: 5

    Hi great class, thank all of you for your efforts.

    I have a question for the main section, how would one go about if you wanted to keep the chest open for a certain amount of time/frames before it changes back to the closed chest?

  • IgnatzIgnatz Mod
    Posts: 5,396

    @Robto - you have revived an 18 month old thread. Please start a new discussion if you want to talk about this.

  • Posts: 5

    Will do, thank you.

This discussion has been closed.