## Scroll Bar Going Too Far

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

### Scroll Bar Going Too Far

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()
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

You missed to subtract the visible words in your calculation

Code: Select all

function love.load()
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


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

### Re: Scroll Bar Going Too Far

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?

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

### Re: Scroll Bar Going Too Far

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 True 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

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.

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

### Re: Scroll Bar Going Too Far

Thank you for the explanations Nelvin and Zorg

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

### Re: Scroll Bar Going Too Far

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.

### Who is online

Users browsing this forum: No registered users and 8 guests