Advertisement
nonogamer9

OC-Donut: donut.c ported to OpenComputers

Jul 19th, 2024 (edited)
340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.29 KB | Software | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local term = require("term")
  4. local math = require("math")
  5. local computer = require("computer")
  6. local gpu = component.gpu
  7.  
  8. local w, h = gpu.getResolution()
  9. local buffer = {}
  10. local showFPS, bouncingMode, running = false, false, true
  11. local donuts = {}
  12. local A, B = 0, 0
  13. local z, b = {}, {}
  14.  
  15. local function sin(x) return math.sin(x) end
  16. local function cos(x) return math.cos(x) end
  17.  
  18. local fpsCounter = {
  19.   sampleWindow = 3,
  20.   updateInterval = 0.5,
  21.   frameTimeQueue = {},
  22.   queueSize = 180,
  23.   queueIndex = 1,
  24.   queueSum = 0,
  25.   lastUpdateTime = 0,
  26.   currentFPS = 0,
  27.   update = function(self, dt)
  28.     if #self.frameTimeQueue == self.queueSize then
  29.       self.queueSum = self.queueSum - self.frameTimeQueue[self.queueIndex]
  30.     end
  31.     self.frameTimeQueue[self.queueIndex] = dt
  32.     self.queueSum = self.queueSum + dt
  33.     self.queueIndex = self.queueIndex % self.queueSize + 1
  34.     local numFrames = math.min(#self.frameTimeQueue, self.queueSize)
  35.     local averageFrameTime = self.queueSum / numFrames
  36.     local fps = 1 / averageFrameTime
  37.     local currentTime = computer.uptime()
  38.     if currentTime - self.lastUpdateTime >= self.updateInterval then
  39.       self.currentFPS = math.floor(fps + 0.5)
  40.       self.lastUpdateTime = currentTime
  41.     end
  42.   end,
  43.   draw = function(self)
  44.     if showFPS then
  45.       gpu.set(1, 1, string.format("FPS: %d", self.currentFPS))
  46.     end
  47.   end
  48. }
  49.  
  50. local function cls()
  51.   for i = 1, w * h do buffer[i] = " " end
  52. end
  53.  
  54. local function flush()
  55.   local str = table.concat(buffer)
  56.   gpu.copy(1, 1, w, h, 0, 1)
  57.   gpu.set(1, h, str:sub(1 + (h-1)*w))
  58.   for i = h-1, 1, -1 do
  59.     gpu.set(1, i, str:sub(1 + (i-1)*w, i*w))
  60.   end
  61. end
  62.  
  63. local function createDonut()
  64.   return {
  65.     x = w / 2,
  66.     y = h / 2,
  67.     vx = math.random(1, 2) * (math.random() > 0.5 and 1 or -1),
  68.     vy = math.random(1, 2) * (math.random() > 0.5 and 1 or -1),
  69.     size = math.random(10, 15)
  70.   }
  71. end
  72.  
  73. local function drawMessage()
  74.   local message = "OC-Donut (Press X to quit.) Based on the original donut.c by Andy Sloane <[email protected]> Ported by nonogamer9"
  75.   local oldBg, oldFg = gpu.getBackground(), gpu.getForeground()
  76.   gpu.setBackground(0x0000FF)
  77.   gpu.setForeground(0xFFFFFF)
  78.   gpu.fill(1, h, w, 1, " ")
  79.   gpu.set(1, h, message)
  80.   gpu.setBackground(oldBg)
  81.   gpu.setForeground(oldFg)
  82. end
  83.  
  84. local function drawBouncingMessage(time)
  85.   local message = "Watch The Donuts Bounce!"
  86.   local messageLength = #message
  87.   local yPosition = h - 2
  88.   local xPosition = math.floor(w/2 - messageLength/2 + sin(time) * (w/2 - messageLength/2))
  89.   local oldBg, oldFg = gpu.getBackground(), gpu.getForeground()
  90.   gpu.setBackground(0x000000)
  91.   gpu.setForeground(0xFFFF00)
  92.   gpu.fill(1, yPosition, w, 1, " ")
  93.   gpu.set(xPosition, yPosition, message)
  94.   gpu.setBackground(oldBg)
  95.   gpu.setForeground(oldFg)
  96. end
  97.  
  98. local function updateBouncingDonuts()
  99.   for _, donut in ipairs(donuts) do
  100.     donut.x = donut.x + donut.vx
  101.     donut.y = donut.y + donut.vy
  102.     if donut.x <= donut.size or donut.x >= w - donut.size then
  103.       donut.vx = -donut.vx
  104.     end
  105.     if donut.y <= donut.size or donut.y >= h - donut.size then
  106.       donut.vy = -donut.vy
  107.     end
  108.   end
  109. end
  110.  
  111. event.listen("key_down", function(_, _, _, code)
  112.   if code == 59 then
  113.     showFPS = not showFPS
  114.     if not showFPS then gpu.set(1, 1, string.rep(" ", 10)) end
  115.   elseif code == 60 then
  116.     bouncingMode = not bouncingMode
  117.     if bouncingMode then donuts = {createDonut()} end
  118.   elseif code == 18 and bouncingMode then
  119.     table.insert(donuts, createDonut())
  120.   elseif code == 16 and bouncingMode and #donuts > 1 then
  121.     table.remove(donuts)
  122.   elseif code == 45 then
  123.     running = false
  124.   end
  125. end)
  126.  
  127. while running do
  128.   local frameStartTime = computer.uptime()
  129.   for i = 1, w * h do b[i], z[i] = " ", 0 end
  130.   if bouncingMode then updateBouncingDonuts() end
  131.   local renderDonuts = bouncingMode and donuts or {{x = w/2, y = h/2, size = 30}}
  132.   for _, donut in ipairs(renderDonuts) do
  133.     for j = 0, 6.28, 0.07 do
  134.       for i = 0, 6.28, 0.02 do
  135.         local sini, cosj = sin(i), cos(j)
  136.         local sinA, sinj = sin(A), sin(j)
  137.         local cosA, cosj2 = cos(A), cosj + 2
  138.         local mess = 1 / (sini * cosj2 * sinA + sinj * cosA + 5)
  139.         local cosi, cosB = cos(i), cos(B)
  140.         local sinB = sin(B)
  141.         local t = sini * cosj2 * cosA - sinj * sinA
  142.         local x = math.floor(donut.x + donut.size * mess * (cosi * cosj2 * cosB - t * sinB))
  143.         local y = math.floor(donut.y + donut.size/2 * mess * (cosi * cosj2 * sinB + t * cosB))
  144.         local o = x + w * y
  145.         local N = math.floor(8 * ((sinj * sinA - sini * cosj * cosA) * cosB - sini * cosj * sinA - sinj * cosA - cosi * cosj * sinB))
  146.         if y > 0 and y <= h and x > 0 and x <= w and mess > z[o] then
  147.           z[o] = mess
  148.           b[o] = string.sub(".,-~:;=!*#$@", math.max(N, 1), math.max(N, 1))
  149.         end
  150.       end
  151.     end
  152.   end
  153.   cls()
  154.   for k = 1, w * h do buffer[k] = b[k] end
  155.   flush()
  156.   if bouncingMode then drawBouncingMessage(frameStartTime) else drawMessage() end
  157.   A, B = A + 0.08, B + 0.06
  158.   local frameEndTime = computer.uptime()
  159.   fpsCounter:update(frameEndTime - frameStartTime)
  160.   fpsCounter:draw()
  161.   os.sleep(0.05)
  162. end
  163.  
  164. term.clear()
  165. print("Thank you for using OC-Donut!")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement