Page 1 of 2

Need help with making surface of image clickable.

Posted: Wed Dec 02, 2020 9:31 am
by fragileslime
Hi everyone, new to love2D and lua.
I'm trying to create a game menu but am having trouble with making the surface of a image clickable.

What is expected to happen:
Mouse clicks on image, function runs.

What is happening:
Mouse clicks anywhere, and function does not run but returns error.

Code: Select all

Error: main.lua:23: attempt to index local menubuttonimg' (a boolean value)
What am I doing wrong?

Source Code:

Code: Select all

-- Call Backs --
function love.load()
	x = 500
   	y = 400
	menuscreenimg = love.graphics.newImage("placeholdermenu.png")
	menubuttonimg = love.graphics.newImage("menubutton.png")
	--testimg = love.graphics.newImage("logomario.png")
	--love.graphics.setNewFont(12)
	--love.graphics.setColor(0,0,0)
	--love.graphics.setBackgroundColor(255,255,255)
	-- testing for image collision 
end
-- End of Call Backs -- 

-- Window Resolution --
success = love.window.setMode(1280, 720)
love.window.setTitle("Beta")

-- Mouse input for Menu Selection
function love.mousepressed(mx, my, button, menubuttonimg)
   if button == 1
   and mx >= x and mx < x + menubuttonimg:getWidth()
   and my >= y and my < y + menubuttonimg:getHeight()
   then print("IT WORKED!")
   end
end

-- Menu Screen --
function love.draw()
  love.graphics.draw(menuscreenimg) --1280, 720)
  love.graphics.print("BETA",600, 300)
  love.graphics.draw(menubuttonimg, 500, 400)
  love.graphics.print("Start!", 600, 425)
end

-- For finding mouse position --
--[[
function love.draw()
	mousey = love.mouse.getY()
	mousex = love.mouse.getX()
	love.graphics.print(mousex, mousey, 100, 100)
end
]]

Re: Need help with making surface of image clickable.

Posted: Wed Dec 02, 2020 10:10 am
by zorg
Hi and welcome to the forums.

The code is mostly fine, but there's one issue that's glaring;
As by the wiki page, the mousepressed callback has this synopsis:

Code: Select all

love.mousepressed( x, y, button, istouch, presses )
You are shadowing your "menubuttonimg" variable by writing that as the 4th parameter in there, which is going to be false since you're not dealing with touch events, hence the error.

Leave that out of the function's parameter list, and it will work.

Re: Need help with making surface of image clickable.

Posted: Wed Dec 02, 2020 10:19 am
by fragileslime
zorg wrote: Wed Dec 02, 2020 10:10 am Leave that out of the function's parameter list, and it will work.
Hi, thank you for the warm welcome and reply.
After removing the 4th parameter there is no error but when trying to click on the images surface it seems that the print function does nothing. I changed it from printing through the console and instead printing to the screen although it did not seem to make a difference.

Re: Need help with making surface of image clickable.

Posted: Wed Dec 02, 2020 10:20 am
by Nixola
Printing to the screen during love.mousepressed will not do anything meaningful; the screen is cleared right before love.draw is called and drawn right after that, so anything happening to the screen in any other moment will be discarded. You would need to change the value of a variable or something similar, and have some code in love.draw reacting to that value change.

Re: Need help with making surface of image clickable.

Posted: Wed Dec 02, 2020 10:26 am
by fragileslime
Nixola wrote: Wed Dec 02, 2020 10:20 am Printing to the screen during love.mousepressed will not do anything meaningful; the screen is cleared right before love.draw is called and drawn right after that, so anything happening to the screen in any other moment will be discarded. You would need to change the value of a variable or something similar, and have some code in love.draw reacting to that value change.
Thank you,
After changing the print function to a window close function it seems that everything is working.

I do feel however, the way I'm going about this is kinda sloopy.
Specially when it comes to placing text over the images. ( it is not perfectly aligned)
What would be the preferred way to deal with this whole front end button with images situation?

Re: Need help with making surface of image clickable.

Posted: Wed Dec 02, 2020 9:22 pm
by RNavega
When I want to print some debug string or number, I use the console.
For this you need to create a conf.lua file with the 'console' attribute set to true, the opposite of this: https://github.com/RNavega/2DMeshAnimat ... onf.lua#L2

Then add a...

Code: Select all

io.setvbuf('no')
...at the start of your main.lua script, so that any print() calls immediately output to the console instead of being buffered.
Then you use Lua's print() function (note, it's not love.graphics.print() from LÖVE, it's just Lua's built-in print() ) with the variables that you want to print. Very helpful.

As for aligning text with images, you can find some theory and inspiration from web design:
https://levelup.gitconnected.com/the-cs ... e9bda94455

Treating your button image as a rectangle, how should the text be aligned to it? (You usually want it centered when it's a UI element.)
The formula for getting the coordinates for centered text on a rectangle can be:
textX = imageX + imageWidth/2 - textWidth/2 = imageX + (imageWidth - textWidth) / 2
(And the same for the Y axis, replacing X by Y and width by height).
You can find out the size of printable text using a love.graphics.Font object, it's the :getWidth() method (check the wiki).

Re: Need help with making surface of image clickable.

Posted: Tue Dec 08, 2020 9:41 am
by fragileslime
RNavega wrote: Wed Dec 02, 2020 9:22 pm
Thank you so much!

Have run into a new issue with my code.
The player image does not seem to get drawn/show up.

main.lua

Code: Select all

-- Imports --
require "player"
require "map"
require "conf"

-- Call Backs --
function love.load()
function Player.load()
-- debug --
io.setvbuf('no')
--Player Movement --
function love.update(dt)
	if love.keyboard.isDown('d') then
		Player.x = Player.x + (Player.speed * dt)
			elseif love.keyboard.isDown('a') then
				Player.x = Player.x - (Player.speed * dt)
		    end
		end
	end
end
-- End of Call Backs -- 

-- Window Resolution --
success = love.window.setMode(1280, 720) -- 720p Resolution
love.window.setTitle("Beta") -- Window Title 

-- Menu Screen --
function love.draw()
	menu_screen_img = love.graphics.newImage("/resources/menu/menu.png")
	button_newgame = love.graphics.newImage("/resources/buttons/menubutton.png")
	love.graphics.draw(menu_screen_img) --1280, 720)
	love.graphics.print("BETA",600, 300)
  	love.graphics.draw(button_newgame, 500, 400)
	love.graphics.print("New Game", 600, 425)
end

-- Mouse input for Menu Selection --
x = 500 -- Width for Button "New Game"
y = 400 -- Heigth for Button "New Game"
function love.mousepressed(mx, my, button)
	if button == 1
	and mx >= x and mx < x + button_newgame:getWidth()
	and my >= y and my < y + button_newgame:getHeight()
	then NewGame()  
	end
end

-- New Game Function ==
function NewGame()
	Map1()
	player()
end
map.lua

Code: Select all

-- Map 1 --
function Map1()
	function love.draw()
		love.graphics.clear( )
		map1 = love.graphics.newImage("/resources/maps/map1/Map1.png")
		love.graphics.draw(map1)
	end
end
player.lua

Code: Select all

Player = {}
function player()
	function Player.load()
	function love.load()
		Player.x = 50
		Player.y = 50
		Player.speed = 200
		Player = love.graphics.newImage("/resources/player/spritetemp.png")
			function love.draw()
				love.graphics.draw(Player)
				love.graphics.scale(2, 2) -- Scale Player Sprite
			end
		end
	end
end

Re: Need help with making surface of image clickable.

Posted: Tue Dec 08, 2020 9:50 am
by RNavega
For every 'function' definition there needs to be an 'end' to close it. So when you do something like this:

Code: Select all

-- Call Backs --
function love.load()
function Player.load()
-- debug --
io.setvbuf('no')
--Player Movement --
function love.update(dt)
	if love.keyboard.isDown('d') then
		Player.x = Player.x + (Player.speed * dt)
			elseif love.keyboard.isDown('a') then
				Player.x = Player.x - (Player.speed * dt)
		    end
		end
	end
end
The LuaJIT parser is going to think that love.load() is the top-level function, inside it there's a Player.load() function, and inside that there's a love.update(dt) function, so it interprets things like this:

Code: Select all

-- Call Backs --
function love.load()
    function Player.load()
        -- debug --
        io.setvbuf('no')
        --Player Movement --
        function love.update(dt)
            if love.keyboard.isDown('d') then
                Player.x = Player.x + (Player.speed * dt)
            elseif love.keyboard.isDown('a') then
                Player.x = Player.x - (Player.speed * dt)
            end
        end
    end
end
...which completely messes up with your intended flow. The LÖVE framework will only be able to 'see' your custom .load() callback, and not the .update() callback as it's inside the Player.load() function.

Where did you write this code? You should think of using Notepad++ or Notepad2, they add an indentation level when you hit Enter to go to the next line, so you can tell when you're starting a new block scope. I didn't manually go in and add the blank spaces to align everything in that second example, the code editor did that for me.

Re: Need help with making surface of image clickable.

Posted: Tue Dec 08, 2020 9:54 am
by RNavega
You can see the same mistake in your other files.
How about any time you write a "function somethingsomething()", go ahead and already add the "end" that will close it, just so you don't forget that anything between the name and the end will belong to the body of that function. Then start adding code to the body.

Re: Need help with making surface of image clickable.

Posted: Tue Dec 08, 2020 11:00 am
by fragileslime
Thank you for the info.
I've been using sublime for the IDE.