I dusted off a few of my older routines and put together what you are looking for. I plan on turning it into an API. Try this:
Vertical Scroll Program
--[[
Vertical Scrolling Text
by Surferpup
]]
--[[
TO DO
Finish Color Aspects
More Error Checking
Convert to API
]]
function setOutput(_device)
local result,width,height = pcall(function () return _device.getSize() end)
if not result then
print "setOutput: The output device specified is not a monitor or terminal"
error()
end
return _device,width,height
end
function setMaxWidth(_textArray)
local maxWidth = 0
for i = 1,#_textArray do
if (maxWidth < #(_textArray[i])) then
maxWidth = #(_textArray[i])
end
end
return maxWidth
end
function setScale(_maxWidth,_device)
if not (pcall(function () _device.setTextScale(5) end)) then
return false
else
local scale = 5
local function checkScale()
local thisWidth,temp
thisWidth,temp = _device.getSize()
return (_maxWidth > thisWidth)
end
while checkScale() and scale >= 1 do
scale = scale - 0.5
_device.setTextScale(scale)
end
return true,_device.getSize()
end
end
function refreshDisplay(_startY,_startIndex,_text,_device,_length,_width)
if not _length then
_length,_width = _device.getSize()
end
for y = _startY,1,-1 do
centerPrint(_text[_startIndex],_width,y,_device)
_startIndex = _startIndex-1
if _startIndex < 1 then break end
end
end
function centerPrint(_text,_width,_yPosition,_output,_highlight,_highlightBackGroundColor,_highlightTextColor,_defaultBackgroundColor,_defaultTextColor)
_text = _text or ""
_output = _output or term
if not _width then
_width,_ = _output.getSize()
end
_yPosition = _yPosition or 1
_highlight = _highlight or 0
if not _output.isColor() then
_highlightBackgroundColor = colors.white
_highlightTextColor = colors.black
_defaultBackgroundColor = colors.black
_defaultTextColor= colors.white
else
_highlightBackgroundColor = _highlightBackgroundColor or colors.white
_highlightTextColor = _highlightTextColor or colors.black
_defaultBackgroundColor = _defaultBackgroundColor or colors.black
_defaultTextColor= _defaultTextColor or colors.white
end
local xPosition = math.floor(_width/2) - (#_text/2)
if xPosition < 1 then
xPosition=1
end
_output.setCursorPos(xPosition,_yPosition)
if _highlight == true then
_output.setBackgroundColor(_highlightBackgroundColor)
_output.setTextColor(_highlightTextColor)
else
_output.setBackgroundColor(_defaultBackgroundColor)
_output.setTextColor(_defaultTextColor)
end
_output.write(_text)
_output.setBackgroundColor(_defaultBackgroundColor)
_output.setTextColor(_defaultTextColor)
end
function scrollPrint(_textArray, -- the text table of strings to print
_startingVerticalPosition, -- the y-position to begin on the monitor
_maximumVerticalPosition, -- the maximum y-position to go to
_sleepInterval, -- delay between printed lines
_outputDevice) -- the output device (term or monitor peripheral)
_textArray = _textArray or {" ";}
_outputDevice = _outputDevice or term
_outputDevice,_,_ = setOutput(_outputDevice)
_sleepInterval = _sleepInterval or 1
local maxWidth = setMaxWidth(_textArray)
local result,width,height = setScale(maxWidth,_outputDevice)
if not result then
width,height = _outputDevice.getSize()
end
_startingVerticalPostition = _startingVerticalPostition or 1
_maximumVerticalPosition = _maximumVerticalPosition or height
if _startingVerticalPosition > height then
_startingVerticalPosition = math.floor(height/2)
end
if _maximumVerticalPosition > height then
_maximumVerticalPosition = height
end
for i = 1,#_textArray do
if _startingVerticalPosition>=_maximumVerticalPosition then
_startingVerticalPosition = _maximumVerticalPosition
else
_startingVerticalPosition=_startingVerticalPosition+1
end
for j = 1,_startingVerticalPosition do
_outputDevice.setCursorPos(1,j)
_outputDevice.write(string.rep(" ",width))
end
refreshDisplay(_startingVerticalPosition,i,_textArray,_outputDevice,2)
sleep(_sleepInterval)
end
end
--Main Program Code Block begins here
-- HERE IS THAT LONG TABLE OF STRINGS:
Text = {
"The year was 2025. Aerial drones had revealed a large weapons cache in Siberia.",
" ",
"United Nations investigators were sent to investigate.",
" ",
"Once they got there they were met by Russian military. ",
" ",
"The Russians captured and executed the agents.",
" ",
"What were once thought to be nuclear weapons were soon revealed as anti-matter.",
" ",
"A weapon like no one had ever seen. A global scare prompted a new kind of space race.",
" ",
"A secret task force assembled to begin work on what only science fiction had thought possible before.",
" ",
"They started to build deep space vessels capable of supporting life.",
" ",
"They believed there was a possibility of life on other planets.",
" ",
"As work neared completion of the Icarus; the Russians found out.",
" ",
"Only a portion of the life support was completed when the war began.",
" ",
"Knowing that this would be the end of earth a rash decision was made,",
" ",
"they were going to launch the Icarus and head for the moon.",
" ",
"Only one section of the ship had breathable air,",
" ",
"this is where they setup a station to refill breathable tanks so that people could survive in space.",
" ",
"In the first year of the war Russia had expanded its territory to berlin.",
" ",
"As there was no slowing them down the Icarus was launched.",
" ",
"Upon reaching the moon it had been revealed that in our 55 year absence a new species had inhabited the moon.",
" ",
"The powers of the tesseract were revealed and teleportation finally became a reality.",
" ",
"Several years had passed and thousands of drones later they had found a suitable planet.",
" ",
"With little life support leaders believed the best way of reaching this planet would be",
" ",
"to send small settler groups to the planet and begin colonizing it.",
" ",
"The settlers began to plant trees, grow crops and create breathable oxygen levels.",
" ",
"However, soon it was discovered that this planet had resources like no one had seen",
" ",
"People knew they could profit from this world and began to mine its resources.",
" ",
" Soon factions were forming, and small warfare was beginning to break out across this new planet….",
" ",
" ",
" ",
" ",
"Here we are today; this is the first bunker created by the Terra Nova Army",
" ",
"and serves as the hub for new survivors to get a new start on the world",
" ",
"we know today as INSERT WORLD NAME HERE.",
" ",
"You can buy supplies and view the ranks in the terra nova army.",
" ",
"New world rules will be in the main atrium along with ranks",
" ",
"and items that have been banished from the new world so that it does not have the same fate as earth.",
" ",
"Please view the rules or your fate could very well be decided by the military leaders.",
" ",
"Earth is still habitable however riddled with radiation it is very dangerous.",
" ",
"War still rages there and bombs fall frequently.",
" ",
"Resources are still there however death is almost emanate.",
" ",
"Travel there at your own risk.",
" ",
}
scrollPrint(Text,1,15,1,peripheral.wrap("top"))
print ("Done")
The code is only around 130 lines long, and then there is your Text Array which takes up another 80+ lines. The main function that does the work is the scrollPrint() function. It takes the following arguments:
- _textArray, – the text table of strings to print
- _startingVerticalPosition – the y-position to begin on the monitor
- _maximumVerticalPosition, – the maximum y-position to go to
- _sleepInterval, – delay between printed lines
- _outputDevice) – the output device (term or monitor peripheral)
I have some built in error checking, although I would like to do more. Also, I started on color support and highlighted text, however, that is not complete in this version. Filally, I think this would make a good API, so I will try and finish this up as well. I tried to make all of the variable names and function names make sense. If a variable is an argument to a function, it begins with an underscore (ie. _argument). If a variable does not begin with an underscore, it is defined as a local variable.
To use it, create your text table as you have done already and fill in the main function call. In the example, that call is:
scrollPrint(Text,1,15,1,peripheral.wrap("top"))
In the example, your Text Table is scrolled through. The first lines starts centered on line 1 of the monitor. It then continues adding lines until it hits line 15 of the monitor. From then on, it prints each new line on line 15 and scrolls the older lines up and out of view (much like a normal terminal display would do). If you want it to start on line 15 and scroll up, change the _startingVerticalPosition to 15. If you want it to use the whole screen, set the _startingVerticalPosition argument to 1 and _maximumVerticalPosition argument to _ (underscore). Ex.
scrollPrint(Text,1,_,1,peripheral.wrap("top"))
I also don't clear the monitor. Instead, I only write over used lines with spaces. I think this allows for a smother display. It also allows for you to have other text (or graphics) on say the bottom half of the monitor while the text scrolls in the top half.
I auto-scale to the largest scale that will fit the width of all of the text strings. If you are using a terminal, autoscale is ignored. If it can't fit text on a line, it left justifies and fits as much as it can.
Let me know if you need help sorting out any of the functions.