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

Timer and other

Started by koslas, 21 August 2015 - 07:30 AM
koslas #1
Posted 21 August 2015 - 09:30 AM
Is there anyway to let there be a timer while I'm using a GUI, or read() but it updates every second, even if os.pullEvent() detects a key, something else? I'm guessing if I want one during the read function I'd have to re-write the read function, but I'm still not sure how I would do one with a GUI
~Sorry about the title as it isn't that informative
Edited on 21 August 2015 - 07:41 AM
LewisTehMinerz #2
Posted 21 August 2015 - 11:42 AM
You can try using parallel.
koslas #3
Posted 21 August 2015 - 11:58 AM
How exactly would I use this?
Astrophylite #4
Posted 21 August 2015 - 12:08 PM
You could also use coroutines to keep checking if the timer event has been pulled.


function checkTimer()
  while true do
    local event = os.pullEvent()
    if event == "timer" then
	  print("Timer Finished!")
    end
  end
end
local oldPull = os.pullEventRaw
local coTime = coroutine.create(checkTimer)
function os.pullEventRaw(sFilter)
  while true do
    local event = { oldPull() }
    if coroutine.status(coTime) == "suspended" then
	  coroutine.resume(coTime, unpack(event))
    end
    if sFilter == event[1] or not sFilter then
	  return unpack(event)
    end
  end
end
koslas #5
Posted 21 August 2015 - 12:29 PM
You could also use coroutines to keep checking if the timer event has been pulled.


function checkTimer()
  while true do
	local event = os.pullEvent()
	if event == "timer" then
	  print("Timer Finished!")
	end
  end
end
local oldPull = os.pullEventRaw
local coTime = coroutine.create(checkTimer)
function os.pullEventRaw(sFilter)
  while true do
	local event = { oldPull() }
	if coroutine.status(coTime) == "suspended" then
	  coroutine.resume(coTime, unpack(event))
	end
	if sFilter == event[1] or not sFilter then
	  return unpack(event)
	end
  end
end

How would I make this to my menu if this were it?

nSelect = 1

function clear()
  term.clear()
  term.setCursorPos(1,1)
end

function menuDisplay()
  clear()
  local nTime = os.time()
  print("The time is: "..textutils.formatTime(nTime, false))
  if nSelect == 1 then
	print("[ Option 1 ]")
  else
	print("  Option 1  ")
  end
  if nSelect == 2 then
	print("[ Option 2 ]")
  else
	print("  Option 2  ")
  end
end

function menu()
  while true do
	menuDisplay()
	event, par1, par2, par3 = os.pullEvent()
	if event == "key" then
	  key = par1
	  if key == 200 and nSelect > 1 then
		nSelect = nSelect-1
	  elseif key == 208 and nSelect < 2 then
		nSelect = nSelect+1
	  elseif key == 28 and nSelect == 1 then
		print("Selected option 1")
		sleep(1)
	  elseif key == 28 and nSelect == 2 then
		print("Selected option 2")
		sleep(1)
	  end
	end
  end
end

menu()

I've never used coroutine, so don't really know how to use it either, so if I wanted to add a timer of 1 second how would I go about that so that if I don't press anything for a second it updates, but also if I do it will still update, so I could add a timer with a menu, so that it ticks up every second, no matter if I'm pressing buttons, or wouldn't that be possible?
Edited on 21 August 2015 - 10:32 AM
LewisTehMinerz #6
Posted 21 August 2015 - 01:25 PM
I think parallel would be simpler.

It's as simple as typing
parallel.waitForAll
then typing the function names. E.G.


parallel.waitForAll( func1, func2, func3, ... )
Astrophylite #7
Posted 21 August 2015 - 01:49 PM
Do you just want it to freeze for a second?
 sleep(1) 
or do you want to make it wait until you press a key ?
 os.pullEvent("key") 
flaghacker #8
Posted 21 August 2015 - 06:46 PM
You could also use coroutines to keep checking if the timer event has been pulled.


function checkTimer()
  while true do
    local event = os.pullEvent()
    if event == "timer" then
	  print("Timer Finished!")
    end
  end
end
local oldPull = os.pullEventRaw
local coTime = coroutine.create(checkTimer)
function os.pullEventRaw(sFilter)
  while true do
    local event = { oldPull() }
    if coroutine.status(coTime) == "suspended" then
	  coroutine.resume(coTime, unpack(event))
    end
    if sFilter == event[1] or not sFilter then
	  return unpack(event)
    end
  end
end

That's a completely wrong implementation, you need to handle event filters and such. Don't try to attempt coroutines if you're not yet familiar worth the computercraft event system.

@OP: the paralell api is the preferred solution if you don't want to rewrite complex functions like read. A basic example would look like this:

function reading()
  while true do
    local text = read()
    print("You wrote " .. text)
  end
end

function waiting()
  while true do
    sleep(3)
    print("3 seconds have passed");
  end
end

paralell.waitForAny(reading, waiting) --NO () after reading &amp; waiting!

You can choose between waitForAny and waitForAll on that last line. Take a look at the wiki.
koslas #9
Posted 21 August 2015 - 09:34 PM
Well I'm thinking about making this into a game, and having it store all the users info on a server, so the simplest thing would be having another computer send a rednet message every second, as that's about all I would know how to do, but I might test out the paralell API and also the coroutine API, and see what one of those 3 are easiest for me. Thanks for your help everyone though :)/>
KingofGamesYami #10
Posted 21 August 2015 - 10:43 PM
I would advise against using coroutines, as they are the hardest thing in CC to use.

If you want to know how to use coroutines, learn how to write the parallel API.

Alternatively, you can use the parallel API which does all the weird stuff to make coroutines work properly.