Howdy, Stranger!

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

Low FPS with Vega's Button Class

edited July 2012 in General Posts: 266

does any one else experience low fps when using @Vega's mesh button class. If I have six buttons the fps drop by 10. Any fix to this?
it drops even more when I add in a physics object.

Tagged:

Comments

  • Posts: 179

    I need to work on a fix. The problem is with calling recolor() every frame, which was not a brilliant plan. It actually should only be called once initially, then when touch begins, then when touch ends. I will work on it later today when I have time. Thanks for reminding me.

  • Posts: 179

    Ok, that was actually an easy fix. I just added a few recolor() calls and killed the one in the draw function. Here is the updated source:

    --Much faster version of button class by Vega
    button = class()
    function button:init(text,location,width,height)
        self.state = "normal"
        self.text = text
        self.textColor = color(255,255,255,192)
        self.location = location
        self.width = width
        self.height = height
        self.visible = true
        self.fontSize = 28
        self.font = "ArialRoundedMTBold"
        self.color1 = color(255, 255, 255, 96)
        self.color2 = color(128,128,128,32)
        self.presscolor1 = color(192, 224, 224, 128)
        self.presscolor2 = color(96, 192, 224, 128)
        self.verts = self:createVerts(self.width, self.height)
        self.myMesh = mesh()
        self.myMesh.vertices = triangulate(self.verts)
        self.vertColor = {}
        self:recolor()
    end
    function button:setColors(c1,c2,p1,p2)
        self.color1 = c1
        self.color2 = c2
        self.presscolor1 = p1
        self.presscolor2 = p2
        self:recolor()
    end
    function button:textOptions(fn, sz, col)
        self.font = fn
        self.fontSize = sz
        self.textColor = col
    end
    function button:draw()
        if self.visible == true then
            pushMatrix()
            translate(self.location.x,self.location.y)
            self.myMesh:draw()
            fill(self.textColor)
            fontSize(self.fontSize)
            font(self.font)
            text(self.text, self.width/2,self.height/2)
            self:drawLines(self.verts)
            popMatrix()
        end
    end
    function button:touched(touch)
        if self.visible then
            if touch.x >= self.location.x and touch.x <= self.location.x + self.width and touch.y >= self.location.y and touch.y <= self.location.y + self.height then
                if touch.state == BEGAN then
                    self.state = "pressing"
                    self:recolor()
                elseif touch.state == ENDED then
                    if self.state == "pressing" then
                        self.state = "normal"
                        self:recolor()
                        print "pressed."
                    end
                end
            else
                self.state = "normal"
                self:recolor()
            end
        end
    end
    function button:createVerts(w,h)
        local r
        local v = {}
        if w > 100 or h > 100 then
            if w>=h then r = round(h/100) else r = round(w/100) end
        else
            r = 1
        end
        v[1] = vec2(w,6*r)
        v[2] = vec2(w-r,4*r)
        v[3] = vec2(w-2*r,2*r)
        v[4] = vec2(w-4*r,r)
        v[5] = vec2(w-6*r,0)
        v[6] = vec2(6*r,0)
        v[7] = vec2(4*r,r)
        v[8] = vec2(2*r,2*r)
        v[9] = vec2(r,4*r)
        v[10] = vec2(0,6*r)
        v[11] = vec2(0,h-6*r)
        v[12] = vec2(r,h-4*r)
        v[13] = vec2(2*r,h-2*r)
        v[14] = vec2(4*r,h-r)
        v[15] = vec2(6*r,h)
        v[16] = vec2(w-6*r,h)
        v[17] = vec2(w-4*r,h-r)
        v[18] = vec2(w-2*r,h-2*r)
        v[19] = vec2(w-r,h-4*r)
        v[20] = vec2(w,h-6*r)
        return v
    end
    function button:drawLines(v)
        noSmooth()
        strokeWidth(1)
        stroke(0, 0, 0, 192)
        for i=1, #v-1 do
            line(v[i].x,v[i].y,v[i+1].x,v[i+1].y)
        end
        line(v[#v].x,v[#v].y,v[1].x,v[1].y)   
    end
    function button:recolor()
        local lt, dk
        if self.state == "normal" then 
            lt = self.color1
            dk = self.color2
        else
            lt = self.presscolor1
            dk = self.presscolor2
        end
        for i=1,3 * #self.verts - 6 do
            if self.myMesh.vertices[i].y > self.height/2 then
                self.vertColor[i] = lt
            else
                self.vertColor[i] = dk
            end
        end
        self.myMesh.colors = self.vertColor
    end
    function round(v)
        return math.floor(v + 0.5)
    end
    
  • edited August 2012 Posts: 266

    I used your updated button class but I noticed a bug. while it did up the FPS to 60 instead of 20, the quality of my physics injects and sprites diminished. I'll post two pictures for further detail.
    http://d.pr/i/aFB4
    http://d.pr/i/3BVQ

  • Posts: 179

    I am guessing that it is because of the noSmooth call I make in the draw lines function. Try adding a pushStyle and PopStyle to that function, so that it becomes:

    function button:drawLines(v)
        pushStyle()
        noSmooth()
        strokeWidth(1)
        stroke(0, 0, 0, 192)
        for i=1, #v-1 do
            line(v[i].x,v[i].y,v[i+1].x,v[i+1].y)
        end
        line(v[#v].x,v[#v].y,v[1].x,v[1].y)   
        popStyle()
    end
    

    I believe that should do it, but I'm not completely sure.

  • Posts: 266

    yeah that's it. thankss

  • Posts: 563

    Nice - I will update the tute with the new @Vega class button (sounds like a Destroyer). The low frame rates hadn't been an issue for me since I only had 3 buttons and not much happening on the screen.

  • edited August 2012 Posts: 68

    Are the changes that @Vega made here also in github?
    I want to add a link in a "buttons" aside I'm doing for my site.

  • Posts: 666

    If you add an array of actions, the button can be made generic so that multiple instances can be made to fire, but call seperate functions. This way I can create many buttons and have all their code seperated away from the Vega class. I haven't seen any way to do this before, so I thought I'd mention it here.

    Adds to the Button class: (uppercased it as a preference)
    Init (last line)

    self.action = {} 
    

    touched(), last line after self:recolor in ENDED.

    if (table.getn(self.action) == 0) then print ('No action defined') else self.action[1]() end
    

    Main class:
    My button declaration in setup() now has a second line;

    mybtn.action ={mybtnclicked}  ---call the mybtnclicked code when clicked!
    

    Finally, I have the payload function in main. We can put this in another file and have all our payloads in a different location.

    function mybtnclicked()
      print("clicked")
    end
    
  • Posts: 2,161

    Surely you just create multiple instances of the class, each with their own callback. Or maybe I'm misunderstanding what you're trying to do.

  • edited August 2012 Posts: 666

    no, that's what this code was doing - making multiple instances of a class each with a seperate callback. the problem was the callback; without creating a new class file for each function. Maybe there is a better way to do this, but my goal is to:

    In Setup:

    1.  dynamically create any buttons that I need, and set the visible state;
    2.  write the code that I need each button to do as a function (for convienence, in a master "business logic" file of sorts);
    3.  tie the button to the function with some intelligent function name
    

    What I do NOT want to do is create a new class each time I need button functionality and hardcode into the button class the possible derivations of what a button press is doing.

    I was unable to fathom how to do what I wanted without writing all this funky callback code myself; was there a better way?

  • Posts: 2,161

    So then you pass the callback function as one of the initialisation arguments. Change the following lines:

    function button:init(text,location,width,height,callback)
    

    add to the init function

    self.callback = callback
    

    and change button:touched so that instead of print("pressed.") it reads self.callback()

    Then you initialse it something like:

    bttn = button("press me",vec2(WIDTH/2,HEIGHT/2),20,30, function () print ("I'm a speckled hen.") end)
    
  • edited August 2012 Posts: 666

    OIC - after doing some additional research (into class.lua, actually) and reading this, it looks like anything that can be a function IS a function, even though it looks like a variable. So, "callback" is a function. I noticed that since you are passing the function on instantiation (last line above). Seems that if I wrote the function as

    function cb()
    print("speckled...")
    end
    

    I'd instantiate with

    bttn = button("press me",vec2(WIDTH/2,HEIGHT/2),20,30, cb) 
    

    This also explains that mysterious doNothing I keep seeing peppered through peoples' code!

Sign In or Register to comment.