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

animations and buffers

Started by cdel, 11 July 2014 - 06:27 AM
cdel #1
Posted 11 July 2014 - 08:27 AM
hello all, I was just wondering how to create animations such as the shutdown animation in OneOS and buffers for gui's.
oeed #2
Posted 11 July 2014 - 09:16 AM
I use my Drawing API to draw both the animation and buffer everything, so if you want the least work you could use that, it's pretty easy to use.

In terms of the animation it's just a pretty simple loop. It could probably do with a tidy up really, but basically all it does is draw a white rectangle that slowly gets smaller and then 'fades' to black. You basically just chuck a bunch of small sleeps between each different step of the animation.
Spoiler

function AnimateShutdown(restart)
if not Settings:GetValues()['UseAnimations'] then
  return
end
Drawing.Clear(colours.white)
Drawing.DrawBuffer()
sleep(0)
local x = 0
local y = 0
local w = 0
local h = 0
for i = 1, 8 do
  local percent = (i * 0.05)
  Drawing.Clear(colours.black)
  x = Drawing.Screen.Width * (i * 0.01)
  y = math.floor(Drawing.Screen.Height * (i * 0.05)) + 3
  w = Drawing.Screen.Width - (2 * x) + 1
  h = Drawing.Screen.Height - (2 * y) + 1
  if h < 1 then
   h = 1
  end
  Drawing.DrawBlankArea(x + 1, y, w, h, colours.white)
  Drawing.DrawBuffer()
  sleep(0)
end
Drawing.DrawBlankArea(x + 1, y, w, h, colours.lightGrey)
Drawing.DrawBuffer()
sleep(0)
Drawing.DrawBlankArea(x + 1, y, w, h, colours.grey)
Drawing.DrawBuffer()
sleep(0)
term.setBackgroundColour(colours.black)
term.clear()
if restart then
  sleep(0.2)
  os.reboot()
else
  os.shutdown()
end
end

In terms of buffering, the best way to do it in my opinion is to either make or use a drawing API similar to the one linked. Rather than using term.writes or other hacky things it allows you to minimise the length of your code, make it more obvious what it does and allow for future additions (for example, in OneOS I've just made away, using my Drawing API, that things like buttons or windows can't draw outside of their frame).

In my drawing API you "draw" each aspect (for example, a box or some text) to a table (not to the screen yet) and once everything (buttons, etc) has "drawn" you then write the buffer to the screen. To do this you have another table of what was previously written to the screen and if there are any differences you change that pixel. My method (below) probably isn't the most efficient way of doing it, and sometimes that's quite noticeable when OneOS is lagging. You could also take a look at LyqydOS' way of doing it or GopherAlt's redirect API.

Spoiler

DrawBuffer = function()
	for y,row in pairs(Drawing.Buffer) do
		for x,pixel in pairs(row) do
			local shouldDraw = true
			local hasBackBuffer = true
			if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
				hasBackBuffer = false
			end
			if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
				shouldDraw = false
			end
			if shouldDraw then
				term.setBackgroundColour(pixel[3])
				term.setTextColour(pixel[2])
				term.setCursorPos(x, y)
				term.write(pixel[1])
			end
		end
	end
	Drawing.BackBuffer = Drawing.Buffer
	Drawing.Buffer = {}
end
Edited on 11 July 2014 - 07:19 AM
cdel #3
Posted 11 July 2014 - 10:21 AM
okay, thanks :)/>