Page 1 of 1

Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 5:00 pm
by Ptruptrucea
I might be doing this wrong, but when I work on an interface, every time I need a functional button, I basically have to split the code in 2 parts:

-First part of the code deals with drawing the actual button, the graphical changes required by interacting with the button and goes into love.draw() (if the mouse is within the button area, change the button to the hover graphics etc);

-Second part of the code deals with the actual logic of the button and goes into love.mousepressed() or the keypress function or whatever (if the mouse is within the button area, when clicked change the state or do the code etc);


Right now, my code for a button looks kinda like this:

love.draw()
buttonGraphiCode(x, y, width, height)

love.mousepressed(x, y, button)
buttonLogiCode(x, y, buttonPressed)

I have to define and call 2 functions to get the desired results.

Is there a way to do this with a single function?

Re: Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 5:13 pm
by MadByte
Not really no. You need to put the code to render your button into the love.draw callback.. and if your button logic is handled with love.mousepressed then you need to put it there. If you got more then one button I suggest to create some functionality to handle all buttons at once. Something like (pseudo code):

Code: Select all

local buttonManager = ButtonManager()

function love.load()
  -- Create Buttons --
  buttonManager:addButton("Start", x, y, event = function() Gamestate.switch(Game) end)
  buttonManager:addButton("Options", x, y, event = function() Gamestate.switch(OptionsMenu) end)
  buttonManager:addButton("Quit", x, y, event = function() love.event.quit() end)
end

function love.update(dt)
  buttonManager:update(dt)
end

function love.draw()
  buttonManager:draw()
end

function love.mousepressed(...)
  buttonManager:mousepressed(...)
end
And inside the"buttonManager" class you could put all buttons inside one table and loop through them.
edit: fixed a typo.

Re: Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 5:56 pm
by Ptruptrucea
MadByte wrote: And inside the"buttonManager" class you could put all buttons inside one table and loop through them.
If it's not too much bother, may I have an example of that? The project I'm doing right now is to better understand loops and how to work with them, so any help would be appreciated.

Other than that, makes sense. Thanks for the tips.

Re: Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 6:01 pm
by MadByte
Here it is.
ButtonContainerExample.love
(2.04 KiB) Downloaded 167 times
I choose to use classes to show you what I would do to organise this.
The "Container" class can also be used to handle other objects as well.
Hope it's not to much input at once. :death:

Re: Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 6:21 pm
by MadByte
Just in case. Here is the same example but much easier to understand:

Code: Select all

-----------------------
-- Screen Dimensions --
-----------------------
local screenWidth, screenHeight = love.graphics.getDimensions()

------------------------------------------
-- Helper Function to detect Collisions --
------------------------------------------
local function boxCollision(a, b)
return a.x < b.x + b.width and a.x + a.width > b.x and
  a.y < b.y + b.height and a.y + a.height > b.y
end


------------------------------------------
-- The container table with the buttons --
------------------------------------------
local buttons = {
  { 
    name = "Destroy me!",
    x = screenWidth/2-48,
    y = 200,
    width = 96,
    height = 16,
    mouseHover = false,
    onClick = function() print("BUTTON 1 pressed") end,
  },
  { 
    name = "Me too!",
    x = screenWidth/2-48,
    y = 300,
    width = 96,
    height = 16,
    mouseHover = false,
    onClick = function() print("BUTTON 2 pressed") end,
  },
  { 
    name = "Quit",
    x = screenWidth/2-48,
    y = 400,
    width = 96,
    height = 16,
    mouseHover = false,
    onClick = function() love.event.quit() end,
  },
}


-----------------------------------------
-- Loop thorugh and Update the buttons --
-----------------------------------------
local function updateButtons(dt)
  for i=#buttons, 1, -1 do
    local button = buttons[i]
    button.mouseHover = false
    if boxCollision({x=love.mouse.getX(), y=love.mouse.getY(), width=1, height=1}, button) then
      button.mouseHover = true
    end
  end
end


---------------------------------------
-- Loop thorugh and draw the buttons --
---------------------------------------
local function drawButtons()
  for i=#buttons, 1, -1 do
    local button = buttons[i]
    if button.mouseHover then love.graphics.setColor(255, 0, 0)
    else love.graphics.setColor(255, 255, 255) end
    love.graphics.rectangle("line", button.x, button.y, button.width, button.height)
    love.graphics.printf(button.name, button.x, button.y+2, button.width, "center")
    love.graphics.setColor(255, 255, 255)
  end
end


---------------------------------------
-- Loop thorugh and check for clicks --
---------------------------------------
local function mousepressedButtons(x, y, mouseButton)
  for i=#buttons, 1, -1 do
    local button = buttons[i]
    if button.mouseHover and mouseButton == 1 then button.onClick() end
  end
end


--------------------
-- Main Callbacks --
--------------------
function love.update(dt)
  updateButtons(dt)
end


function love.draw()
  drawButtons()
end


function love.mousepressed(...)
  mousepressedButtons(...)
end


function love.keypressed(key)
  if key == "escape" then love.event.quit() end
end

Re: Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 8:13 pm
by Ptruptrucea
Yes, the second example is more clear-cut than the first. In the first one as far as I can tell you included an external library, classic, that deals with classes via metatables. Originally, I stumbled upon this here video. I have no idea what __type or __index are, or why do they need the double underscores beforehand, but I was trying to reproduce that technique with buttons instead of characters.

Don't think it's wise though, me using programming bits that I have no idea how they work. Thanks for your help :) .

Re: Can I keep all of the button code in one place?

Posted: Tue Aug 16, 2016 9:13 pm
by MadByte
Ptruptrucea wrote:Don't think it's wise though, me using programming bits that I have no idea how they work. Thanks for your help :) .
The good thing though - you can learn why and how things work this way. It's easier as it looks :neko:
Ptruptrucea wrote:Yes, the second example is more clear-cut than the first.
Anyway I think the first option would be much cleaner and way easier to maintain when you're working on a real project - especially when working with others.

Good luck with your project.