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

Monitor Flickering

Started by TheUltimateKrtekCZ, 16 February 2017 - 06:38 PM
TheUltimateKrtekCZ #1
Posted 16 February 2017 - 07:38 PM
When I run the program, it runs fine, but after about 10 seconds, the monitor starts going crazy. The colors in the rectangle change color. After that, in the next 20 seconds, the game crashes.

Since my english it very good :D/>, I will post a video instead. That will hopefully explain, what is going on. In the video, the flickering is small compared to the flickering I usually get.
VideoURL: https://youtu.be/XVlwCspR2tk
CODE:
SpoilershowRF <FramesPerSecond>

args = {...}
monitor = peripheral.wrap("top")
monitor.setTextScale(0.5)
monitor.setBackgroundColor(colors.black)
monitor.clear()
wirelessModem = peripheral.wrap("bottom")
wirelessModem.open(0)
rednet.open("bottom")
energyCell = peripheral.wrap("front")
running = true
fps = args[1]
screenSizeX, screenSizeY = monitor.getSize()
function drawPoint(x, y, color)
  -- returnState = monitor.getBackgroundColor()
  monitor.setCursorPos(x, y)
  monitor.setBackgroundColor(color)
  monitor.write(" ")
  -- monitor.setBackgroundColor(returnState)
end
function drawRect(minX, maxX, minY, maxY, backgroundColor, borderColor)
  returnState = monitor.getBackgroundColor()
  for i = minX, maxX do
	for j = minY, maxY do
	  if i == minX or i == maxX or j == minY or j == maxY then
		drawPoint(i, j, borderColor)
	  else
		drawPoint(i, j, backgroundColor)
	  end
	end
  end
  monitor.setBackgroundColor(returnState)
end

function draw()
  monitor.setBackgroundColor(colors.black)
  monitor.clear()
  drawRect(3, screenSizeX - 3, 3, screenSizeY - 3, colors.green, colors.blue)
  drawRect(4, screenSizeX - 4, 4, screenSizeY - 4, colors.purple, colors.purple)
  drawRect(4, 3 + math.floor((screenSizeX - 9) * energyCell.getEnergyStored() / energyCell.getMaxEnergyStored()), 4, screenSizeY - 4, colors.red, colors.red)
  monitor.setCursorPos(1, 1)
  monitor.setBackgroundColor(colors.black)
  monitor.write("Enegry Stored:   " .. energyCell.getEnergyStored())
  monitor.setCursorPos(1, 2)
  monitor.write("Energy Capacity: " .. energyCell.getMaxEnergyStored())
end
while true do
  if peripheral.isPresent("front") then
	draw()
	rednet.broadcast(textutils.serialize({energyCell.getEnergyStored(), energyCell.getMaxEnergyStored(), true}), "EnergyCellEnergy")
	os.startTimer(1 / fps)
	os.pullEvent("timer")
  else
	rednet.broadcast(textutils.serialize({0, 0, false}), "EnergyCellEnergy")
  end
end
Bomb Bloke #2
Posted 17 February 2017 - 08:57 AM
Code doesn't run instantly. Your drawing code in particular uses a lot more function calls than it needs to, because with each frame you're drawing to many individual points multiple times. The delay this generates, when compounded by the fact that peripheral calls are particularly slow, leads to a noticeable flicker effect while the display is in the process of being redrawn.

If we do our peripheral calls just before clearing the screen (saving the results to variables), and take care not to redraw more than we have to, we can speed things up somewhat. Eg something along the lines of this (untested) code:

Spoiler
local maxEnergy = energyCell.getMaxEnergyStored()  -- No need to call this more than once.

term.redirect(monitor)  -- Redirect all terminal output to the monitor.
term.setBackgroundColour(colours.black)
term.clear()  -- We only really need to clear the whole display once.
term.setCursorPos(1, 2)
term.write("Energy Capacity: " .. maxEnergy)  -- This line isn't going to change.
paintutils.drawBox(3, 3, screenSizeX - 3, screenSizeY - 3, colours.blue)  -- Neither will this border.

local function draw()
	local stored = energyCell.getEnergyStored()
	
	term.setCursorPos(1, 1)
	term.setBackgroundColour(colours.black)
	term.clearline()
	term.write("Enegry Stored:   " .. stored)
	
	local barLength = math.floor((screenSizeX - 9) * stored / maxEnergy)
	
	if barLength > 0 then paintutils.drawFilledBox(4, 4, 3 + barLength, screenSizeY - 4, colours.red) end
	if barLength < screenSizeX - 9 then paintutils.drawFilledBox(4 + barLength, 4, screenSizeX - 4, screenSizeY - 4, colours.purple) end
end

That should just about eliminate any flicker.

In regards to your game crashes, difficult to comment on those without seeing the resulting logs, but off the top of my head I'm going to guess you're running OptiFine or similar.