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

[Lua][Question] os.pullEvent / continue running if no input

Started by Fizzgig, 22 December 2012 - 11:17 AM
Fizzgig #1
Posted 22 December 2012 - 12:17 PM
Im trying to write a sleep function that displays for the user how much time it has left. I got that part working so then I decided that it would be nice to let the user cancel sleeping if they wish. But the os.pullEvent seems to perminently freeze the program until input is detected. Is there some other way to make this work?

below is the code:

function sleepmode(duration)
  repeat
   term.clear()
   term.setCursorPos(1,1)
   print("Status - Sleeping... "..duration.."sec")
   print("Press 'x' to cancel.")
  
   local id, key = os.pullEvent("key")
   if key == 45 then break end
  
   sleep(1)
   duration = duration-1
  until duration < 0
end

Thanks alot for your help
Goof #2
Posted 22 December 2012 - 12:35 PM
When calling os.pullEvent, it listen, until it is triggered. So it actually waits for the input, before it can countinue. So you
should use the parallel api, so it is counting, and waiting for input, at the same time:D i cant post any code, since im posting this on my phone :(/>

i Hope i could help :D/>
Sammich Lord #3
Posted 22 December 2012 - 12:39 PM
Look on the wiki for the usage of the parallel API that will "run two functions at once".(Not really. Just switches between them very fast.)
ChunLing #4
Posted 22 December 2012 - 12:41 PM
Set a timer event using os.startTimer(), and don't specify the event to pull.
Fizzgig #5
Posted 22 December 2012 - 01:05 PM
ok looking up info for both parallel api and os.startTimer. Seems either way i need to write another function to make this work xD I got function on functions goin now =P let the experiments continue… =)

good thing turtles never get bored!
remiX #6
Posted 22 December 2012 - 01:30 PM
Using os.startTimer() should work, I haven't really used it but I think this would work :P/>


function sleepmode(duration)
    timer = os.startTimer(1)
  repeat
   term.clear()
   term.setCursorPos(1,1)
   print("Status - Sleeping... "..duration.."sec")
   print("Press 'x' to cancel.")
 
   local id, p1 = os.pullEvent()
   if id == "key" and p1 == 45 then break
   elseif id == "timer" and p1 == timer then
   duration = duration-1
   timer = os.startTimer(1)
   end
   
  until duration < 0
end
theoriginalbit #7
Posted 22 December 2012 - 01:38 PM
When calling os.pullEvent, it listen, until it is triggered. So it actually waits for the input, before it can countinue. So you
should use the parallel api

The only reason it waits for input is because in OP it has os.pullEvent("key") so using parallel is not needed here, just a removal of "key"


In terms of getting it to work, remiX's solution WILL work. I use this method all the time over using the parallel api (no point using coroutines when they aren't needed for the solution).

EDIT: Also when timing is important between 2 functions (lets say updating a clock and accepting user input), its most of the time easier to use timers over the parallel api as parallel doesn't always get things timed perfectly. (and before anyone tries to debate this, I have tested it extensively and its small amounts each time, but that can eventually build up to a big difference in a program that needs perfect timing. when testing i found a large fluctuation in the amount of time the coroutine runs for, vs doing the timers with pull events, while still having a fluctuation, was much smaller. :)/> )

EDIT: Side note too, the sleep( ) function never perfectly sleeps for the time supplied, now i could go down to the assembly level programming and tell you why it doesn't but that would most likely bore you all, I'll just tell you that a 1 second timer loop in assembly is actually 0.999 (or if you prefer it in milliseconds 1000ms is actually 999ms)
Edited on 22 December 2012 - 12:53 PM
Fizzgig #8
Posted 22 December 2012 - 01:44 PM
Yey thats exactly what I was hoping! The function is sound and I dont think it needs to be compounded to make it work. So I cant call the event on an object! Thanks very much remiX and TOB
theoriginalbit #9
Posted 22 December 2012 - 01:46 PM
So I cant call the event on an object!
What object?
Fizzgig #10
Posted 22 December 2012 - 01:49 PM
I meant I was setting it to something.. the value "key" which was my error.
theoriginalbit #11
Posted 22 December 2012 - 01:51 PM
oh yeh, well it wasn't an error per-say, since pull event is designed to only pull a specified event, you were just doing something that caused the program not to run as expected.
Fizzgig #12
Posted 22 December 2012 - 02:02 PM
I pluged in remiX's solution and its works perfectly. It seemed that the timer function is set 2x so I thought I would have to change the code. but it counts down 1sec at a time even with the 2 calls. Not sure why thats working… lol but it is

edit: no never mind..it calls once before and then again for the next..its right

Im gonna be using this a whole lot xD thanks everyone
theoriginalbit #13
Posted 22 December 2012 - 02:10 PM
yeh the timer needs to be started first outside the loop so an event is pulled then its just started again each time its pulled.
Lyqyd #14
Posted 22 December 2012 - 10:34 PM
EDIT: Side note too, the sleep( ) function never perfectly sleeps for the time supplied, now i could go down to the assembly level programming and tell you why it doesn't but that would most likely bore you all, I'll just tell you that a 1 second timer loop in assembly is actually 0.999 (or if you prefer it in milliseconds 1000ms is actually 999ms)

That's probably far less relevant than the fact that only one computer is ever running at a time, so all sleep does is give you an approximate minimum wait time. If you were to sleep(1) and, while that computer was yielded, another computer refused to yield until it was forced to, that sleep wouldn't end for at least ten seconds. :)/>
theoriginalbit #15
Posted 22 December 2012 - 11:16 PM
Yeh that too :P/>