Scroll Bar Going Too Far

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
NobodysSon
Prole
Posts: 28
Joined: Tue Oct 30, 2012 10:37 pm

Scroll Bar Going Too Far

Post by NobodysSon » Fri Jan 11, 2019 5:54 am

I've been trying to get a simple scroll bar functioning for a word puzzle game I am working on but I have run into a problem that I can't seem to wrap my head around how to solve. The scroll bar works but it runs the text right off the screen. I would like to be at the end of the text at the same time the scroll bar reaches its lower limit but I am off by (seemingly) exactly one screen worth.

Would someone be so kind as to take a look and point out where my problem is before I go permanently cross-eyed trying to find it myself?

Code: Select all

function love.load()
	-- Load font
	fontSize = 48
	font = love.graphics.newFont("calibri.ttf",fontSize)
	love.graphics.setFont(font)


	wordList = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}

	scrollBar = {x = 760, y = 0, width = 30, height = 160, position = 1, active = false}

	listStart = scrollBar.position

	windowWidth,windowHeight = love.window.getMode()
end

function love.draw()

	local listEnd

	-- Determine which lines will be displayed
	-- 13 lines of text fit on the screen
	if #wordList <=13 then 
		listEnd = #wordList
	else
	     listEnd = listStart + 13
	     	if listEnd > #wordList then
	     		listEnd = #wordList
	     	end
	end

	-- Display word list
	local dy = 0
	if #wordList > 0 then
		for w = listStart,listEnd do
			love.graphics.print(wordList[w],0,dy)
			dy = dy + 42
		end
	end

	-- Display scroll bar
	love.graphics.rectangle("fill",scrollBar.x,scrollBar.y,scrollBar.width,scrollBar.height)

end

function love.update(dt)

end

function love.mousepressed(x, y, button)
	if button == 1 then
		-- Is the scroll bar being clicked on?
		if (x >= scrollBar.x and x <= scrollBar.x+scrollBar.width) then
			if (y >= scrollBar.y and y <= scrollBar.y+scrollBar.height) then
				scrollBar.active = true
			end
		end
	end
end

function love.mousereleased(x,y,button)
	scrollBar.active = false
end

function love.mousemoved(x, y, dx, dy)
	-- Is the scrollbar active while the mouse is moving?
	if scrollBar.active == true then
		-- Keep the scrollbar on the screen
		if scrollBar.y + dy >= 0 and scrollBar.y + dy <= windowHeight-scrollBar.height then
			scrollBar.y = scrollBar.y + dy
			local factor
			factor = math.floor((windowHeight-scrollBar.height)/#wordList)
			scrollBar.position = math.floor(scrollBar.y/factor)+1
			listStart = scrollBar.position
		end
	end
end

Nelvin
Citizen
Posts: 79
Joined: Mon Sep 12, 2016 7:52 am
Location: Germany

Re: Scroll Bar Going Too Far

Post by Nelvin » Fri Jan 11, 2019 7:59 am

You missed to subtract the visible words in your calculation

Code: Select all

function love.load()
	-- Load font
	fontSize = 48
	font = love.graphics.newFont("calibri.ttf",fontSize)
	love.graphics.setFont(font)


	wordList = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}

    scrollBar = {x = 760, y = 0, width = 30, height = 160, position = 1, active = false}

	listStart = scrollBar.position

    windowWidth,windowHeight = love.window.getMode()
end

function love.draw()

	local listEnd

	-- Determine which lines will be displayed
	-- 13 lines of text fit on the screen
	if #wordList <=13 then
		listEnd = #wordList
	else
	     listEnd = listStart + 13
	     	if listEnd > #wordList then
	     		listEnd = #wordList
	     	end
	end

	-- Display word list
	local dy = 0
	if #wordList > 0 then
		for w = listStart,listEnd do
			love.graphics.print(wordList[w],0,dy)
			dy = dy + 42
		end
	end

	-- Display scroll bar
	love.graphics.rectangle("fill",scrollBar.x,scrollBar.y,scrollBar.width,scrollBar.height)

end

function love.update(dt)

end

function love.mousepressed(x, y, button)
	if button == 1 then
		-- Is the scroll bar being clicked on?
		if (x >= scrollBar.x and x <= scrollBar.x+scrollBar.width) then
			if (y >= scrollBar.y and y <= scrollBar.y+scrollBar.height) then
				scrollBar.active = true
			end
		end
	end
end

function love.mousereleased(x,y,button)
	scrollBar.active = false
end

function love.mousemoved(x, y, dx, dy)
	-- Is the scrollbar active while the mouse is moving?
	if scrollBar.active == true then
		-- Keep the scrollbar on the screen
		if scrollBar.y + dy >= 0 and scrollBar.y + dy <= windowHeight-scrollBar.height then
			scrollBar.y = scrollBar.y + dy
			local factor
			factor = ((windowHeight-scrollBar.height)/(#wordList-14))
			scrollBar.position = math.floor(scrollBar.y/factor + 0.5) + 1
			listStart = scrollBar.position
		end
	end
end

User avatar
NobodysSon
Prole
Posts: 28
Joined: Tue Oct 30, 2012 10:37 pm

Re: Scroll Bar Going Too Far

Post by NobodysSon » Fri Jan 11, 2019 4:42 pm

:megagrin: Thank you for being my second pair of eyes, Nelvin! I cannot say how many times I missed that.

One question: I noticed you added an additional 0.5 to the calculation of the scrollbar's position:

Code: Select all

scrollBar.position = math.floor(scrollBar.y/factor + 0.5) + 1
I removed it to see if I could see the difference but didn't notice one. What was your purpose there?

User avatar
zorg
Party member
Posts: 2597
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Scroll Bar Going Too Far

Post by zorg » Fri Jan 11, 2019 7:42 pm

math.floor(x + .5) (and math.ceil(x - .5) for negative numbers) helps with rounding issues where x might be close enough to some number point 5 decimal, e.g. 1.5 should be rounded towards 2, but math.floor(1.5) will floor it to 1.0 instead, because that's what it's supposed to do; 1.5 + .5 = 2, so that gets floored to 2.

There are many rounding algorithms, but lua only has floor and ceil, so this way, you're simulating rounding the way people are accustomed to it.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

Nelvin
Citizen
Posts: 79
Joined: Mon Sep 12, 2016 7:52 am
Location: Germany

Re: Scroll Bar Going Too Far

Post by Nelvin » Fri Jan 11, 2019 8:28 pm

In addition to what zorg mentioned, the reason I've added it to the calculation is, it makes the first move half the size of what's generally required to scroll the list by one element and the same for the last one.
Without it, the last element will only appear at the very last possible scrollbar position. You can see the difference much better when you reduce the list of words to 15 elements and test it with and without the +0.5.

User avatar
NobodysSon
Prole
Posts: 28
Joined: Tue Oct 30, 2012 10:37 pm

Re: Scroll Bar Going Too Far

Post by NobodysSon » Sat Jan 12, 2019 6:21 pm

Thank you for the explanations Nelvin and Zorg

User avatar
pgimeno
Party member
Posts: 1629
Joined: Sun Oct 18, 2015 2:58 pm

Re: Scroll Bar Going Too Far

Post by pgimeno » Sat Jan 12, 2019 6:51 pm

zorg wrote:
Fri Jan 11, 2019 7:42 pm
math.floor(x + .5) (and math.ceil(x - .5) for negative numbers)
math.floor(x + .5) is OK for negatives too. You just have to take into account that n.5 will always be rounded up, so e.g. -3.5 will be rounded to -3, and for graphics applications, rounding always in the same direction, without depending on which side of 0 you're on, is desirable.

Incidentally, math.floor(x + .5) gives an incorrect result for the number 0.49999999999999994 only (it returns 1 in that case); for the rest of numbers the result is right. If that's really a concern, which I doubt, you can special case it: return (x == .49999999999999994 and 0 or math.floor(x + 0.5))

math.ceil(x - 0.5) has the same problem with the number -0.49999999999999994.

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 3 guests