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

Making constant refresh rate

Started by mhiekuru, 07 July 2015 - 01:57 AM
mhiekuru #1
Posted 07 July 2015 - 03:57 AM
I'm trying to get this to work but just couldn't. I have buttons and data to show, and it's suppose to render the data in a constant rate.
so i tried using a timer event, but then it will stop rendering if a click event is applied because the function on the mouse_click has an os.sleep so I added a timer after the function, and now its making like another instance of timer that increases the refresh rate of the data being displayed. and i couldnt use os.sleep because it makes the button unclickable for a fraction of a second. Anybody has idea what's a better way of making this?

EDITED


os.startTimer(0)
while true do
local event ,a,b,c = os.pullEvent()
if event == 'mouse_click' then --buttons
  --run a functions 1st function has os.sleep, 2nd function dont have os.sleep (alternate between functions)
  --os.startTimer(0.5)
end
if event == 'timer' then
  --render stuff on screen
  os.startTimer(0.5)
end
end
Edited on 07 July 2015 - 04:18 AM
Dog #2
Posted 07 July 2015 - 05:39 AM
You're capturing the event in 'a' then comparing to 'event'. Change your two if statements from this…

if event ==

to this…

if a ==
mhiekuru #3
Posted 07 July 2015 - 06:18 AM
oh sorry its just a pseudo code, the real code is correct but a clutter mess to post
Cranium #4
Posted 07 July 2015 - 06:23 AM
It's much easier to debug if you post the actual code though.
mhiekuru #5
Posted 07 July 2015 - 07:34 AM
im sorry, here it is xKdM0CPA
the part i posted is in the render function
Edited on 07 July 2015 - 05:35 AM
mhiekuru #6
Posted 07 July 2015 - 02:49 PM
bump
Dog #7
Posted 07 July 2015 - 05:49 PM
No need to bump your question - someone will jump in when they have the time.

First, you don't need the sleeps, so you can eliminate those. Second you need to track your timers (by naming them) so that you aren't running multiples and causing the problem you're having. Take a look at this page (specifically the code example) and see if that gives you what you need to better manage your timers and solve the problem.
Grim Reaper #8
Posted 07 July 2015 - 10:20 PM
Just from taking a look at your pseudo code, I think I have an idea of what you're doing and what you're not doing.

The problems you're seeing are due to the fact that functions you're calling from the main loop and up the stack are making os.pullEvent (coroutine.yield) calls which delay the return back to your loop. If you wanted to have this "main loop" structure, a possible solution would be to call the functions in your main loop inside a coroutine, so they yield back to the main loop.

Something like this, for example:
SpoilerHere, the main loop runs, waiting for a mouse click in the upper left-hand corner of the screen. Once this event occurs, then the function "stuff" is called which uses the native "read" function, making lots of calls to os.pullEvent which ultimately yield back to our main loop. The main loop's "os.pullEvent" call supplies the active threads with their events through "coroutine.resume."

local function stuff()
    term.setCursorPos(1, 1)

    -- Grab some input.
    local input = read() -- This will call os.pullEvent, yielding back to the resuming caller.
    local fileHandle = fs.open("/input.log", 'a')

    if fileHandle then
        fileHandle.writeLine(input)
        fileHandle.close()
    else
        return false
    end

    return true
end



-- Removes any dead threads from the table.
local function purge(threads)
    local deadKeys = {}

    for key, thread in pairs(threads) do
        if coroutine.status(thread) == "dead" then
            table.insert(deadKeys, key)
        end
    end

    for _, deadKey in ipairs(deadKeys) do
        table.remove(threads, deadKey)
    end
end



local threads = {}

while true do
    local eventData = { os.pullEvent() }

    -- Update coroutines if there are any currently alive.
    for _, thread in pairs(threads) do
        coroutine.resume(thread, unpack(eventData))
    end
    -- Remove any dead threads.
    purge()

    -- Mouse click in the origin of the screen -> Get some input there.
    if eventData[1] == "mouse_click" and eventData[3] == 1 and eventData[4] == 1 then
        table.insert(coroutine.create(stuff))
    end
end
Dog #9
Posted 08 July 2015 - 01:05 AM
fwiw, you could just use the parallel api (in your case, parallel.waitForAny) - it would be much simpler than managing the coroutines yourself.

local timerID --# define our timer ID using a forward declaration (scripts read from top to bottom; we want this variable available to the entire script so we define it at the beginning)

local function input() --# this will handle mouse click events
  while true do
    local _, button, x, y = os.pullEvent("mouse_click")
    --# do mouse stuff here
  end
end

local function timer() --# this will handle timer events
  while true do
    local _, id = os.pullEvent("timer")
    if id == timerID then
      --# render stuff on screen
      timerID = os.startTimer(0.5)
    end
  end
end

timerID = os.startTimer(0.5) --# start the timer
parallel.waitForAny(input, timer) --# start the program