Posted 28 July 2012 - 07:30 PM
Scrolling Marquee(s) with Multiple Monitors
——————————————————————–
I've had this program for awhile and decided to post it.
This can take an unlimited number of monitors (one monitor per computer), and automatically scrolls as many lines of text as you'd like from one monitor to the next. At the end of the last monitor, that line will go back to the first monitor, making an infinite loop. The speed of each line can also be customized. Everything can be configured in a couple text files.
PICTURES:
CODE:
You will need to tweak these files with the appropriate computer id's and what text you want to scroll. Use the code I gave as an example… it should be pretty self-explanatory. Instructions are also put in the comments at the top of the 'scrollMaster' and 'scrollSlave' programs.
The first three files go on the 'Master' computer, which will be attached the the starting monitor. The scrollMaster code does not need to be touched. You define all the other monitors/computers in 'scrollNodes'. Each number corresponds to a computer id, and the order these are put in the file determines the order the monitors will go in. 'scrollFile' is where you define the text that scrolls. For each line you define a speed (the smaller the number, the faster) with an INTEGER (no decimals), and then type the text that displays on the next line. All the other computers are called 'Slave' computers. They only have one file, 'scrollSlave'. SImply define the computer id of the master computer in that file, and you're good to go. The master and all the slave computers should have a modem, and one monitor (any size) attached to them.
To run, run all of the slave computers FIRST, and then run the master program. If the master program is started first, you will need to restart it once all the slaves are running.
Scroll Master:
Scroll File (Scroll Master Computer):
Scroll Nodes (Scroll Master Computer):
Scroll Slave:
——————————————————————–
I've had this program for awhile and decided to post it.
This can take an unlimited number of monitors (one monitor per computer), and automatically scrolls as many lines of text as you'd like from one monitor to the next. At the end of the last monitor, that line will go back to the first monitor, making an infinite loop. The speed of each line can also be customized. Everything can be configured in a couple text files.
PICTURES:
Spoiler
CODE:
You will need to tweak these files with the appropriate computer id's and what text you want to scroll. Use the code I gave as an example… it should be pretty self-explanatory. Instructions are also put in the comments at the top of the 'scrollMaster' and 'scrollSlave' programs.
The first three files go on the 'Master' computer, which will be attached the the starting monitor. The scrollMaster code does not need to be touched. You define all the other monitors/computers in 'scrollNodes'. Each number corresponds to a computer id, and the order these are put in the file determines the order the monitors will go in. 'scrollFile' is where you define the text that scrolls. For each line you define a speed (the smaller the number, the faster) with an INTEGER (no decimals), and then type the text that displays on the next line. All the other computers are called 'Slave' computers. They only have one file, 'scrollSlave'. SImply define the computer id of the master computer in that file, and you're good to go. The master and all the slave computers should have a modem, and one monitor (any size) attached to them.
To run, run all of the slave computers FIRST, and then run the master program. If the master program is started first, you will need to restart it once all the slaves are running.
Scroll Master:
Spoiler
--[[
Scroll Program: Master
By: Negeator
Instructions:
Don't touch this file! (unless you know what you are doing)
Define all of the slave computer ids in the 'scrollNodes' file.
Put an id on each line, this will be the order they go in.
Define all of the lines of text in the 'scrollFile' file.
Put the speed (higher the number, slower it scrolls, NO DECIMAL VALUES) on one line, and the text on the other.
In case you can't count, there should be two lines in the text file for every line it displays.
To Run, run all of the slaves first, then run the master program. If you run the master before one of the slaves, you'll have to stop the master and re-run it.
]]--
sleep(1) --Make sure slave computers boot first (for logging into a server with computers set to automatically run the program)
local mon
local timeMax
--Arrays Initialized
local nodes = { } --Slave Computer ID's
local text = { } --Current Text for each line of each monitor
local heights = { } --Heights of each monitor
local serverText = { } --Current server text (Feeds one character of this at a time into the Master monitor, and then removes that character. When the string is empty, it is replenished by being reset using storeServerText)
local storeServerText = { } --Stored Server Text (this does not change)
local scrollSpeeds = { } --Time it takes to scroll (1 = fastest, only whole numbers for now)
--[[ Functions ]]--
function main()
--Initialization
getNodeData() --Load Nodes (slave computer id's) from a file
getMessageData() --Load Message (text and speeds for each line) from a file
startModem() --Start Modem
startMon() --Start Monitor
textInit() --Initialize the Text arrays
getServerText() --Initialize serverText values
timeMax = getLongestTime() --Get longest scroll time
local currTime = 0 --Initialize the current time variable
os.startTimer(.01) --Start the timer (currTime will increment ever .01 seconds)
print("Working!")
while true do
drawText()
event = os.pullEvent()
if event == "timer" then
for i = 1, #scrollSpeeds do
if (currTime % scrollSpeeds[i]) == 0 then
updateCharLine(i)
updateText()
end
end
currTime = currTime + 1
if currTime > timeMax then
currTime = 0
end
os.startTimer(.01)
end
end
end
function getServerText()
for i = 1, #storeServerText do
serverText[i] = storeServerText[i]
end
end
--Update all of the slaves' text
function updateText()
for i = 1, #nodes do
sendText(i)
end
end
--Update text (rows) for a slave
function sendText(index)
local sendID = nodes[index]
rednet.send(sendID,"update")
for i = 1, heights[index + 1] do
if i > #storeServerText then
rednet.send(sendID," ")
else
rednet.send(sendID,text[index + 1][i])
end
end
end
--Initialize 'text' (make all of the rows the appropriate length, etc)
function textInit()
--Add to heights and text for the first monitor (Master)
local length, height = mon.getSize()
table.insert(heights,height)
table.insert(text, { })
for a = 1, #storeServerText do
table.insert(text[1],textCreate(length))
end
print("a")
--Add to heights and text for the rest of the monitors (Slaves)
for i = 1, #nodes do
length = getLength(nodes[i])
height = getHeight(nodes[i])
--Create Slave Height
table.insert(heights,height)
--Initialize text (rows) for Slaves
table.insert(text, { })
for a = 1, #storeServerText do
table.insert(text[#text],textCreate(length))
end
end
end
--Create a blank string based on a specific length
function textCreate(len)
local ret = ""
for i = 1, len do
ret = ret .. " "
end
return ret
end
function updateCharLine(index)
text[1][index] = text[1][index] .. string.sub(serverText[index],1,1)
for i = 2, #text do
text[i][index] = text[i][index] .. string.sub(text[i - 1][index],1,1)
end
for i = 1, #text do
text[i][index] = string.sub(text[i][index],2,string.len(text[i][index]))
end
serverText[index] = string.sub(serverText[index], 2, string.len(serverText[index]))
if serverText[index] == "" then
serverText[index] = storeServerText[index]
end
end
--Draw text on the Master's monitor
function drawText()
for i = 1, #text[1] do
if i > heights[1] then
return
end
mon.setCursorPos(1,i)
mon.write(text[1][i])
end
end
--Get the length of a slave's monitor
function getLength(index)
-- term.write(1,1,"Waiting on ".. index .." to send")
print("Waiting on ".. index)
rednet.send(index,"length")
while true do
id, message = rednet.receive()
if id == index then
return tonumber(message)
end
end
end
--Get the height of a slave's monitor
function getHeight(index)
rednet.send(index,"height")
while true do
id, message = rednet.receive()
if id == index then
return tonumber(message)
end
end
end
--Start the monitor (detect side, etc)
function startMon()
local monSide
for i=1,#rs.getSides() do
if peripheral.isPresent(rs.getSides()[i]) and peripheral.getType(rs.getSides()[i]) == "monitor" then
monSide = rs.getSides()[i]
mon = peripheral.wrap( monSide )
return
end
end
error()
end
--Start the monitor (detect side, etc)
function startModem()
local modemSide
for i=1,#rs.getSides() do
if peripheral.isPresent(rs.getSides()[i]) and peripheral.getType(rs.getSides()[i]) == "modem" then
modemSide = rs.getSides()[i]
rednet.open(modemSide)
return
end
end
-- error()
end
--Gets the scroll time that is the longest
function getLongestTime()
local max = scrollSpeeds[1]
for i = 2, #scrollSpeeds do
if scrollSpeeds[i] > max then
max = scrollSpeeds[i]
end
end
return max
end
--Load messages and speeds from a file
function getMessageData()
local file, error = io.open("scrollFile", "r")
if error then
return error
end
local readText
local boolean = true
local num = 0
while boolean do
readText = file:read()
if readText ~= nil then
if num == 0 then
table.insert(scrollSpeeds,tonumber(readText))
num = 1
else
table.insert(serverText,"")
table.insert(storeServerText,readText)
print(" Inserting "..readText)
num = 0
end
else
boolean = false
end
end
file:close()
end
function getNodeData()
local file, error = io.open("scrollNodes", "r")
if error then
return error
end
local readText
local boolean = true
local num = 0
while boolean do
readText = file:read()
if readText ~= nil then
table.insert(nodes,tonumber(readText))
else
boolean = false
end
end
file:close()
end
--[[ Run Program ]]--
main()
Scroll File (Scroll Master Computer):
Spoiler
2
Hello World! This is some text ...
4
Here is another line, scrolling at another speed. The larger the number is set for this line in 'scrollFile', the slower this line will scroll...
2
Be sure to put a space or two at the end of every line. If you don't there won't be any spaces in between the first word and the last word when this text repeats.
10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
Scroll Nodes (Scroll Master Computer):
Spoiler
2
3
4
Scroll Slave:
Spoiler
--[[
Scroll Program: Slave
By: Negeator
Instructions:
Set the 'serverID' variable to the id of the master computer.
]]--
local serverID = 1 -- CHANGE THIS TO THE COMPUTER ID OF THE MASTER
local mon
local text = { }
local length, height
--[[ Functions ]]--
function main()
--Initialization
startModem()
startMon()
length, height = mon.getSize()
for i = 1, height do
table.insert(text,"")
end
print("Ready!")
while true do
drawText()
event, id, message = os.pullEvent()
if event == "rednet_message" then
if id == serverID then
if message == "length" then
rednet.send(serverID,tostring(length))
elseif message == "height" then
rednet.send(serverID, tostring(height))
elseif message == "update" then
for i = 1, height do
repeat
id2, message2 = rednet.receive()
until id2 == id
text[i] = message2
end
end
end
end
end
end
--Draw Text
function drawText()
for i = 1, height do
mon.setCursorPos(1,i)
mon.write(text[i])
end
end
--Start the monitor (detect side, etc)
function startMon()
local monSide
for i=1,#rs.getSides() do
if peripheral.isPresent(rs.getSides()[i]) and peripheral.getType(rs.getSides()[i]) == "monitor" then
monSide = rs.getSides()[i]
mon = peripheral.wrap( monSide )
return
end
end
error()
end
function startModem()
local modemSide
for i=1,#rs.getSides() do
if peripheral.isPresent(rs.getSides()[i]) and peripheral.getType(rs.getSides()[i]) == "modem" then
modemSide = rs.getSides()[i]
rednet.open(modemSide)
return
end
end
error()
end
--[[ Run Program ]]--
main()