This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Theadictablock's profile picture

Message board help

Started by Theadictablock, 08 July 2013 - 09:35 AM
Theadictablock #1
Posted 08 July 2013 - 11:35 AM
Im new to this and am wanting to make a message board that shows todo list news ect i can figure out how to do that but how would i make that into different slides that change every so often

i was thinking somthing like after slide comes up use timer for 15 secs ish and then clear. then it would start printing again.
would that work and if so does anyone know the coding for that part.
:huh:/>
Theadictablock #2
Posted 08 July 2013 - 11:38 AM
Oh and how do you loop it and put it on monitor
Bubba #3
Posted 08 July 2013 - 12:11 PM
So you want something almost like a powerpoint?

Well I would do it like this:

1) Wrap the monitor using peripheral.wrap([side]). This returns an object which you can use to perform monitor actions. For example:

local monitor = peripheral.wrap("left")
monitor.clear()
monitor.setCursorPos(1,1)
monitor.write("Hello!")

The next thing you'll want to do is get an table of all the messages you'd like to display. If you're not familiar with tables, here's an example:

local myDisplayStuff = {
  [1] = "Welcome to [x]! We hope you enjoy your stay, and please - abide by the rules.";
  [2] = "TODO - Finish the outer wall.";
  [3] = "TODO - Rebuilld the giant stadium.";
}

Finally, you'll want to get some code that displays that text in a way that looks good. You could go about this in several ways. The easiest one would be to simply center it on the screen. However, the issue with that is that on occasion you will have text that is too long to center and it will bleed off the screen. If you encounter such a case, you'll have to check each item and wrap it to the next line.

If you want to center text on the screen, click the spoiler below.
SpoilerHere's an example of centering:

local monX, monY = monitor.getSize() --#Of course, we need to get the monitor's size to be able to center it
local function printCentered(text, yPos)
  monitor.setCursorPos(monX/2-#text/2, yPos)
  monitor.write(text)
end

That's pretty simple. But what if we encounter the case with lengthy text? We'll use a for loop to display it properly. WARNING: This function does not automatically wrap text at a space. That would be slightly more complicated. If you want to know how you can do that, take a look into the "bios.lua" file that is located in the ComputerCraft[version].zip file. Or just adjust your text by adding spaces where appropriate :)/>/>/>/>

local function centerPrintWithWrap(text, yPos)
  if #text > monX then
    local space = 4 --#This is the space on the side
    local last = 1 --#This will be used to keep track of the beginning substring
    local y = yPos
    for i=monX-space, #text, monX-space do
      centerPrint(text:sub(last, i), y)
      last=i+1
      y=y+1
    end
  else
    centerPrint(text, yPos)
  end
end

If you want a full breakdown of that code, see the spoiler below.
Spoiler

if #text>monX then
The # operator gets the length of items, including tables and strings (like in this case). So, if the length of the text is longer than the monitor is wide, we'll have to use wrapping. Otherwise, continue on!


for i=monX-space, #text, monX-space do
Not sure if you're familiar with for loops, but if not go ahead and check out the Lua PIL (Google it!). It's a great resource and should be the goto place if you have a basic Lua Question.
What this code does is loop, starting at the size of the monitor minus the amount of space you'd like to have for looks on either side, and goes to the length of the text, incrementing by monitor size minus space.

So for example, If I had a monitor that is 51 wide, and a text that is 80 characters long, this will start with i=51-4, run until it reaches 80, and increment each time by 51-4.


centerPrint(text:sub(last, i), y)
This code gets a substring of the text and prints it in the center. Here is the result of some basic string.sub operations so you can better understand what's going on here.

local myString = "Hello, friend!"
print(myString:sub(1, 3))
--#Output: Hel
print(myString:sub(6, 10))
--#Output: , fri

So now all you need to do is put this all together. You can iterate of a table using a for loop like this:

for index=1, #yourTableWithStrings do
  local item = yourTableWithStrings[index]
  centerPrintWithWrap(item, monY/2) --#Print it centered on the y-axis too.
end

Hopefully this helps you out!

Edit: Oops! Forgot the timer. Fortunately that's quite simple.

In your loop that goes over the table of strings, go ahead and add in something like this:

sleep(15) --#Sleeps 15 seconds and then continues to the next one

And don't forget to clear the monitor with monitor.clear() at the beginning of the for statement, otherwise the next text will write over old text and look ugly if it's shorter.


If you want to print actual lists that begin on the left side of the screen, click below:
Spoiler

This one is much more simple. We'll have some code that iterates over the table of strings and writes it to the screen until no more can fit, at which point we'll pause for 15 seconds and then move onto the next set.

[code]
local monX, monY = monitor.getSize()
local monitor = peripheral.wrap([side])
local function runUntilLimit(textTable, currentPosition)
  monitor.setCursorPos(1,1) monitor.clear()
  if #textTable-currentPosition > monY then --#If we have more text objects than screen space then...
    for i=currentPosition, currentPosition+monY do
      monitor.write("-> "..textTable[i])
      local currentX, currentY = monitor.getCursorPos()
      monitor.setCursorPos(1, currentY)

      return runUntilLimit(textTable, currentPosition+monY)
      --#Note: The above line where I recursively call the function is a /bad/ coding practice unless you 
      --#know what you're doing. If you do not use the return statement, you will get an index array 
      --#out of bounds exception. Best to just use a for loop instead, but for the sake of time this 
      --#is what I used.
    end
  else
    for i=currentPosition, #textTable do
      monitor.write("-> "..textTable[i])
      local currentX, currentY = monitor.getCursorPos()
      monitor.setCursorPos(1, currentY+1)
    end

    return false
  end
end

So then to call this, all you have to do is this:

while runUntilLimit(textTable, 1) do sleep(15) end
Theadictablock #4
Posted 08 July 2013 - 12:17 PM
thanks so much ill try to finnish it when i get home from holiday. It makes it simpler
. :)/>
Theadictablock #5
Posted 08 July 2013 - 12:21 PM
if i put that code together would it work or is there a order.
Bubba #6
Posted 08 July 2013 - 12:34 PM
if i put that code together would it work or is there a order.

Well I didn't specifically write it in order but for the most part yeah you could. However I would suggest actually reading to understand because otherwise you won't be able to replicate this in another project without help ;)/>