Page 2 of 2

Re: Help with buttons

Posted: Sun Oct 05, 2014 8:11 am
by Doctory
billythecodingkid wrote:I implemented

Code: Select all

for i,v in ipairs(t) do 
    table.remove(t, i) 
end
in love.update() and it does remove them but it does it with a second delay so I'm going to try what you said doc
using that in love.update would delete all buttons no matter what.

Re: Help with buttons

Posted: Sun Oct 05, 2014 8:43 am
by micha
billythecodingkid wrote:I implemented

Code: Select all

for i,v in ipairs(t) do 
    table.remove(t, i) 
end
in love.update() and it does remove them but it does it with a second delay so I'm going to try what you said doc
Removing all table entries this way does not work, because the keys are rearranged during iteration.
When you remove the first entry, then all of the others are moved such that the former second entry is now the first, and so on. But the loop continues at item 2. So after running this code, only about the half of all elements are removed. That may be the reason, why it takes a moment to remove all buttons: The process spreads out over multiple frames.

Here are three possible solutions:
1) Replace the table by an empty table:

Code: Select all

t = {}
2) Or traverse the table backwards:

Code: Select all

for i = #t,1,-1 do
  table.remove(t,i)
end
3) Or do not use the table.remove:

Code: Select all

for i=1,#t do
  t[i] = nil
end

Re: Help with buttons

Posted: Sun Oct 05, 2014 8:58 am
by artofwork
I have no idea why you used a for loop to create buttons anyway I fixed the problem by creating a class to draw out the buttons I also made some changes to some of the files i'll list them here & upload a working love file.

main.lua

Code: Select all

width=love.graphics.getWidth()
height=love.graphics.getHeight()
function love.load()
Button = require'code/button' -- since this is loaded 1st we can call it anywhere :)
require 'code/menu'
require 'code/imgLoader'
require 'code/game'
--require 'code/death'
--require 'code/player'
--require 'code/enemy'
--require 'code/sound'
gamestate = "menu" -- has to be global, so we stick it inside love.load 
menu.load()
game.load()
mx = 1
my = 1
end

function love.mousepressed(x, y, button )
	newGame:mousepressed(x, y, button)
	quit:mousepressed(x, y, button)
	controls.q1:mousepressed(x, y, button)
	mx = x
	my = y
end


function love.update()
	if newGame.state == true then
		gamestate = "playing"
		newGame.state = false
	end
	if controls.q1.state == true then
		-- this controls the fight button
		controls.q1.state = false
	end
	if quit.state == true then
		gamestate = "menu"
		quit.state = false
	end
	
end


function love.draw()
	if gamestate == "menu" then
		menu.draw()
	elseif gamestate == "playing" then
		game.draw()
	end
	love.graphics.print("FPS "..love.timer.getFPS( ), 10, 10) -- no need to add tostring()
	love.graphics.print(string.format("Click X %0f", mx), 10, 150)
	love.graphics.print(string.format("Click Y %0f", my), 10, 170)
end

function love.keypressed(key)
	if key == "escape" then
		gamestate="menu"
	end
end
menu.lua

Code: Select all

menu = {}

function menu.load()
	newGame = Button(210,175, "Start", "l", "/imgs/button.png")  --New Game
	quit = Button(210,210, "Quit", "l", "/imgs/button.png")  --Quit
end



function menu.draw()
	love.graphics.draw(title,0,0)
	newGame:draw()
	quit:draw()
end
game.lua

Code: Select all

game={}
turn=true

function game.load()
    controls = {q1,q1x,q1y,q1t}
    controls.q1 = Button(366,277, "Fight", "l", "/imgs/button.png")
end

function game.draw()
	love.graphics.draw(backround,0,0)
	love.graphics.draw(player,70,78)
	controls.q1:draw()
end
I created this buttons class a while back but modified it to suit your needs :)

button.lua

Code: Select all

Button = {}
Button.__index = Button

setmetatable(Button, {
    __call = function(cls, ...)
        return cls.new(...)
    end,
})

function Button.new(x, y, text, button, image)
    local self = setmetatable({}, Button)
    self.x = x or 0 
    self.y = y or 0
	self.image = love.graphics.newImage(image)
	self.width = self.image:getWidth()
	self.height = self.image:getHeight()
	self.text = text or "button"
	self.textPos = {}
    self.textPos.x = self.x - (font:getWidth(self.text) / 2) + (self.width / 2)
    self.textPos.y = self.y + 5
    self.button = button or "l"
    self.state = false
    return self
end
   
function Button:draw()		
	love.graphics.draw(self.image, self.x, self.y)
	love.graphics.print(self.text, self.textPos.x, self.textPos.y)
end
   

function Button:mousepressed(x, y, button)
	mx, my = love.mouse.getPosition()
	if self.button == button and self.state == false then 
		if mx > self.x and mx < (self.x + self.width) then
			if my > self.y and my < (self.y + self.height) then
				self.state = true -- see
			end
		end
	else
		self.state = false
	end
end
   
return Button

Re: Help with buttons

Posted: Sun Oct 05, 2014 10:23 am
by billythecodingkid
artofwork wrote:I have no idea why you used a for loop to create buttons anyway I fixed the problem by creating a class to draw out the buttons I also made some changes to some of the files i'll list them here & upload a working love file.

main.lua

Code: Select all

width=love.graphics.getWidth()
height=love.graphics.getHeight()
function love.load()
Button = require'code/button' -- since this is loaded 1st we can call it anywhere :)
require 'code/menu'
require 'code/imgLoader'
require 'code/game'
--require 'code/death'
--require 'code/player'
--require 'code/enemy'
--require 'code/sound'
gamestate = "menu" -- has to be global, so we stick it inside love.load 
menu.load()
game.load()
mx = 1
my = 1
end

function love.mousepressed(x, y, button )
	newGame:mousepressed(x, y, button)
	quit:mousepressed(x, y, button)
	controls.q1:mousepressed(x, y, button)
	mx = x
	my = y
end


function love.update()
	if newGame.state == true then
		gamestate = "playing"
		newGame.state = false
	end
	if controls.q1.state == true then
		-- this controls the fight button
		controls.q1.state = false
	end
	if quit.state == true then
		gamestate = "menu"
		quit.state = false
	end
	
end


function love.draw()
	if gamestate == "menu" then
		menu.draw()
	elseif gamestate == "playing" then
		game.draw()
	end
	love.graphics.print("FPS "..love.timer.getFPS( ), 10, 10) -- no need to add tostring()
	love.graphics.print(string.format("Click X %0f", mx), 10, 150)
	love.graphics.print(string.format("Click Y %0f", my), 10, 170)
end

function love.keypressed(key)
	if key == "escape" then
		gamestate="menu"
	end
end
menu.lua

Code: Select all

menu = {}

function menu.load()
	newGame = Button(210,175, "Start", "l", "/imgs/button.png")  --New Game
	quit = Button(210,210, "Quit", "l", "/imgs/button.png")  --Quit
end



function menu.draw()
	love.graphics.draw(title,0,0)
	newGame:draw()
	quit:draw()
end
game.lua

Code: Select all

game={}
turn=true

function game.load()
    controls = {q1,q1x,q1y,q1t}
    controls.q1 = Button(366,277, "Fight", "l", "/imgs/button.png")
end

function game.draw()
	love.graphics.draw(backround,0,0)
	love.graphics.draw(player,70,78)
	controls.q1:draw()
end
I created this buttons class a while back but modified it to suit your needs :)

button.lua

Code: Select all

Button = {}
Button.__index = Button

setmetatable(Button, {
    __call = function(cls, ...)
        return cls.new(...)
    end,
})

function Button.new(x, y, text, button, image)
    local self = setmetatable({}, Button)
    self.x = x or 0 
    self.y = y or 0
	self.image = love.graphics.newImage(image)
	self.width = self.image:getWidth()
	self.height = self.image:getHeight()
	self.text = text or "button"
	self.textPos = {}
    self.textPos.x = self.x - (font:getWidth(self.text) / 2) + (self.width / 2)
    self.textPos.y = self.y + 5
    self.button = button or "l"
    self.state = false
    return self
end
   
function Button:draw()		
	love.graphics.draw(self.image, self.x, self.y)
	love.graphics.print(self.text, self.textPos.x, self.textPos.y)
end
   

function Button:mousepressed(x, y, button)
	mx, my = love.mouse.getPosition()
	if self.button == button and self.state == false then 
		if mx > self.x and mx < (self.x + self.width) then
			if my > self.y and my < (self.y + self.height) then
				self.state = true -- see
			end
		end
	else
		self.state = false
	end
end
   
return Button
Thanks, this was really helpful. Didn't know you could do the buttons like that.