gobal = _G
gobal.runningTerminal = true
function TermWrite(word,tm)
while true do
local x,y = term.getCursorPos()
local g = 0
local ostimer = os.startTimer(tm)
local typing = true
local count = 1
while true do
e = { os.pullEvent(true) }
if e[1] == "timer" and e[2] == ostimer then
term.setCursorPos(3,4)
write(word)
term.setCursorPos(x+g,y)
write( string.sub(word,count,count) )
ostimer = os.startTimer(tm)
g = g + 1
count = count + 1
if count == #word then
break
end
end
end
word = os.pullEvent(false)
end
end
TerminalWrite = coroutine.create(TermWrite)
TW = coroutine.create(TermWrite)
e = {}
term.clear()
term.setCursorPos(1,1)
coroutine.resume(TerminalWrite,"Hello There!",1)
term.setCursorPos(1,2)
coroutine.resume(TW,"This is pretty Cool!",.01)
while true do
g,b = coroutine.resume(TerminalWrite,unpack(e))
f,j = coroutine.resume(TW,unpack(e))
if not b then
break
end
e = { os.pullEvent() }
end
This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
Help with coroutines
Started by Micheal Pearce, 13 January 2016 - 07:57 PMPosted 13 January 2016 - 08:57 PM
I'm stumped with this one, I have no idea why but when I run this it keeps setting the var 'word' to 'time' and writing it abunch of times
Posted 13 January 2016 - 09:27 PM
an event loop inside of an event loop, that just sounds like a disaster
worse: event loop in event loop in coroutine in eventloop
change those to coroutine.yield for readability
also os.pullEvent takes a sting parameter for the event to pull (discarding other event types), I have no idea what you think it is doing by passing it a boolean
http://www.computerc...ics-coroutines/
worse: event loop in event loop in coroutine in eventloop
change those to coroutine.yield for readability
http://www.computerc...ics-coroutines/
BB's first law of coroutines is "you probably don't need to be using coroutines"
Edited on 13 January 2016 - 09:15 PM
Posted 13 January 2016 - 09:33 PM
os.pullEvent is basically just coroutine.yeild so when a pass the boolean though it, it comes out as var b in the main loop at the bottom and if its false it means it's stopped typing and if b is false then it breaks the loop ending the program
Posted 13 January 2016 - 10:11 PM
gobal = _G
gobal.runningTerminal = true
function TermWrite(word,tm)
while true do
local x,y = term.getCursorPos()
local g = 0
local ostimer = os.startTimer(tm)
local typing = true
local count = 1
while true do
e = { os.pullEvent(true) }
if e[1] == "timer" and e[2] == ostimer then
term.setCursorPos(3,4)
write(word)
term.setCursorPos(x+g,y)
write( string.sub(word,count,count) )
ostimer = os.startTimer(tm) --# Timer started here
g = g + 1
count = count + 1
if count == #word then
break --# the loop breaks, but the timer is still running
end
end
end
word = os.pullEvent(false) --# timer is what the event that gets pulled is, hence word getting set to "timer" (not time)
end
end
TerminalWrite = coroutine.create(TermWrite)
TW = coroutine.create(TermWrite)
e = {}
term.clear()
term.setCursorPos(1,1)
coroutine.resume(TerminalWrite,"Hello There!",1)
term.setCursorPos(1,2)
coroutine.resume(TW,"This is pretty Cool!",.01)
while true do
g,b = coroutine.resume(TerminalWrite,unpack(e))
f,j = coroutine.resume(TW,unpack(e))
if not b then
break
end
e = { os.pullEvent() }
end
edit:
Notice the comments I did not actually change any of the actual code.
Edited on 13 January 2016 - 09:12 PM
Posted 13 January 2016 - 10:16 PM
I think you may have replied while I was editing my post (sorry about that)
Wouldn't a slow write function in a coroutine be better?
Wouldn't a slow write function in a coroutine be better?
Edited on 13 January 2016 - 09:19 PM
Posted 13 January 2016 - 10:22 PM
I think you may have replied while I was editing my post (sorry about that)
Wouldn't a slow write function in a coroutine be better?
Most likely yes. Textutils.slowWrite just uses timers anyway, so it should work perfectly fine, however he would still have the same problem. He is grabbing his timer event and treating it as if it were the thing he passed it. All he needs to get this to work is to just do a few checks when he pulls the event.
Posted 13 January 2016 - 10:27 PM
Thank you for your help! I've added a check in the main loop so if b or j is false they stop running
and could I use textutils.slowWrite instead of this? remember I'm trying to write two lines at the same time
and could I use textutils.slowWrite instead of this? remember I'm trying to write two lines at the same time
Posted 13 January 2016 - 10:30 PM
you should use coroutine.status to see if your coroutine has ended - http://lua-users.org...outinesTutorial scroll down to simple usage
testutils.slowWrite would break if you run two at the same time, look at the print loop
testutils.slowWrite would break if you run two at the same time, look at the print loop
--#textutils file
function slowWrite( sText, nRate )
nRate = nRate or 20
if nRate < 0 then
error( "Rate must be positive", 2 )
end
local nSleep = 1 / nRate
sText = tostring( sText )
local x,y = term.getCursorPos(x,y)
local len = string.len( sText )
for n=1,len do
term.setCursorPos( x, y ) --#move this line
sleep( nSleep ) --#below this one to fix
local nLines = write( string.sub( sText, 1, n ) )
local newX, newY = term.getCursorPos()
y = newY - nLines
end
end
Edited on 13 January 2016 - 09:30 PM
Posted 13 January 2016 - 10:48 PM
I couldn't use coroutine.status because of how I set it up so I could use it more than once, it would just return suspended and I wouldn't be able to tell where it suspended from
Posted 14 January 2016 - 12:55 AM
Which is a good reason to change how you set it up, really.
As in most cases where you could use coroutines, it's easier to have the parallel API implement them for you:
As in most cases where you could use coroutines, it's easier to have the parallel API implement them for you:
local function TermWrite(word,tm)
local x, y = term.getCursorPos()
for i = 1, #word do
term.setCursorPos(x + i - 1, y)
term.write(word:sub(i, i))
sleep(tm)
end
end
parallel.waitForAll(
function()
term.setCursorPos(1,1)
TermWrite("Hello There!",1)
end,
function()
term.setCursorPos(1,2)
TermWrite("This is pretty Cool!",.01)
end)
Posted 14 January 2016 - 01:11 AM
But I feel like it'd be better in the long run to use coroutines in my program because I'm gonna need to get input from other running programs while this is running
Posted 14 January 2016 - 01:18 AM
The example provided IS using coroutines. It's simply handling the resuming via the parallel API.
If you really, really want to handle them directly within your own code, read through the example here. You can't simply resume your coroutines any time an event occurs - your coroutines are tolerant of that, but "regular scripts" you try to run within your manager will fail hard if you don't respect their filters.
I've also decided to finish writing my coroutine tutorial, as I've got a bit of spare time today. With any luck I'll have it done within a few hours.
If you really, really want to handle them directly within your own code, read through the example here. You can't simply resume your coroutines any time an event occurs - your coroutines are tolerant of that, but "regular scripts" you try to run within your manager will fail hard if you don't respect their filters.
I've also decided to finish writing my coroutine tutorial, as I've got a bit of spare time today. With any luck I'll have it done within a few hours.