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

Flickering

Started by KaBooMa, 04 January 2013 - 02:59 AM
KaBooMa #1
Posted 04 January 2013 - 03:59 AM
I have a similar program to the one I am gonna post below. Basically, when doing A LOT of clearing of the terminal and writing, you can manage a flicker effect on stuff. I am not sure how to explain this but basically, what the program does it it is doing a lot of drawing and it causes a flicker. I was wondering, how do you go about stopping this flickering?

Spoiler


mw, mh = term.getSize()

function pixel(x,y,color)
  term.setCursorPos(x,y)
  term.setBackgroundColor(color)
  term.write(" ")
end

function drawRect(minx,miny,maxx,maxy,color)
  for x = minx, maxx do
    for y = miny, maxy do
      pixel(x,y,color)
    end
  end
end

function clear()
  term.setBackgroundColor(colors.black)
  term.clear()
end

while true do
  clear()
  for y=1,9 do
    --clear()
    drawRect(1,1,mw,mh,colors.red)
    drawRect(1,1,mw,y,colors.blue)
    sleep(0.005)
  end
end

I am coding a OS atm and the os has a topbar you click and it slides down nice and smooth. Now, when it slides down it has to reprint everything because if you don't, it starts to have a sorta, drag effect. As it slides down, it has to clear the terminal, print the background, print the topbar, and then print icons and basically, it starts flickering. Just wondering how someone would achieve a non-flicker on something like this.

EDIT: Edited code to show a bit better what I am having a problem with.
Kingdaro #2
Posted 04 January 2013 - 04:38 AM
The best way to reduce "flickering" is to only redraw elements when necessary, and not all of the time. In an event pulling loop, you could only draw during a queued "redraw" event, and only redraw the elements when, for example, the user clicks.


local function draw()
  clear()
  for y=1,9 do
    --clear()
    drawRect(1,1,mw,mh,colors.red)
    drawRect(1,1,mw,y,colors.blue)
  end
end

os.queueEvent('redraw')
while true do
  local ev = os.pullEvent()
  if ev == 'redraw' then
    draw()
  elseif ev == 'mouse_click' then
    os.queueEvent('redraw')
  end
end
KaBooMa #3
Posted 04 January 2013 - 04:43 AM
Ya I have what your are saying basically in the os, but not in this because it is just a example to reproduce the flickering I am talking about. Now, using the same stuff, it still creates that flicker due to what I am gonna saying having to clear the screen and then go and print out each pixel. Is there no way to really fix that?

EDIT: I coded a sorta precache function for this and it seems to smooth it out…I am not sure if this is going to work for the OS. I really hope so. Here is what I got so far

Spoiler


mw, mh = term.getSize()

frame = {}

function pixel(x,y,color)
  -- term.setCursorPos(x,y)
  -- term.setBackgroundColor(color)
  -- term.write(" ")
  if (not frame[x]) then table.insert(frame,x,{}) end
  table.insert(frame[x],y,{})
  frame[x][y] = {color = color, text = " ",x = x, y = y}
end

function drawRect(minx,miny,maxx,maxy,color)
  for x = minx, maxx do
	for y = miny, maxy do
	  pixel(x,y,color)
	end
  end
end

function clear()
  term.setBackgroundColor(colors.black)
  term.clear()
end

function updateScreen()
--clear()
for x, _ in pairs(frame) do
for y, p in pairs(frame[x]) do
term.setCursorPos(x,y)
term.setBackgroundColor(p.color)
term.write(p.text)
end
end
frame = {}
end

os.queueEvent("draw")

while true do
  -- clear()
  local event = os.pullEvent()

  if (event == "draw") then
for y=9,1,-1 do
-- clear()
drawRect(1,1,mw,mh,colors.red)
drawRect(1,1,mw,y,colors.blue)
updateScreen()
sleep(0.005)
end
  elseif (event == "mouse_click") then
os.queueEvent("draw")
  end
end

I know this works, but for some reason, I really really feel that this is going to bug out when used certain ways….Hmm
Lyqyd #4
Posted 04 January 2013 - 04:47 AM
You could redirect the screen to a buffer, then use the buffer to draw only what has changed to the screen after your draws are complete. You'd probably want to have it draw to screen each time just before yielding, so that complex draw operations are dealt with in their totality, rather than dealing with individual changes to the screen.
KaBooMa #5
Posted 04 January 2013 - 04:51 AM
I am sorta gonna guess what you just said, I did while you was typing it haha I believe what I got up there is what you mean…I think it will do but I really need to place it inside my os to test it before I can be certain. I think I can have a frame variable in the draw api, then simply have all new textboxes,rects., and other stuff just add to the frame variable. Then I can add a draw.flush() to simply flush out the frame and clear it for next usage. I am gonna go code in the os rather than ramble here about how I wanna do it ^.^ I shall return! :)/>
Exerro #6
Posted 04 January 2013 - 05:02 AM
would 20fps stop flickering? if you have it limit the code to only run at a maximum of 20fps would it still flicker?
Lyqyd #7
Posted 04 January 2013 - 05:59 AM
I am sorta gonna guess what you just said, I did while you was typing it haha I believe what I got up there is what you mean…I think it will do but I really need to place it inside my os to test it before I can be certain. I think I can have a frame variable in the draw api, then simply have all new textboxes,rects., and other stuff just add to the frame variable. Then I can add a draw.flush() to simply flush out the frame and clear it for next usage. I am gonna go code in the os rather than ramble here about how I wanna do it ^.^ I shall return! :)/>/>

Well, that's not precisely what I meant, but I suppose it would do for simple cases. If it works, excellent!
KaBooMa #8
Posted 04 January 2013 - 06:17 AM
So I decided to run that basic idea through the OS. Let me tell you buddy, after doing some changes to the draw api to get it to draw it all and flush properly, this is the bomb. Lyqyd, King, everybody, thanks for the help ^.^ Finally I can navigate my OS, with no flick! This is very eye pleasing now…All the flickering was making my eyes hurt haha. Thank you everyone that helped me figure this out :)/>