nonogamer9

Super Mario FX Clone For Craft OS-PC ported to OpenComputers! (it's bad)

Apr 25th, 2025
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.92 KB | None | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local gpu = component.gpu
  4. local internet = require("internet")
  5. local term = require("term")
  6. local computer = require("computer")
  7. local floor, cos, sin, abs = math.floor, math.cos, math.sin, math.abs
  8.  
  9. local loadingURL = "https://files.catbox.moe/l8tnog.bmp"
  10. local bmpURL     = "https://files.catbox.moe/w9tlsn.bmp"
  11. local playerURL  = "https://files.catbox.moe/fzau50.bmp"
  12.  
  13. local function download(url)
  14.     local response = internet.request(url)
  15.     if not response then error("Failed to download: " .. url) end
  16.     local data = ""
  17.     for chunk in response do data = data .. chunk end
  18.     return data
  19. end
  20.  
  21. local function stringUnpack(format, str, pos)
  22.     local function unpackInt(str, pos, size, signed)
  23.         local val = 0
  24.         for i = 0, size - 1 do
  25.             val = val + str:byte(pos + i) * (256 ^ i)
  26.         end
  27.         if signed and val >= 2^(size*8-1) then
  28.             val = val - 2^(size*8)
  29.         end
  30.         return val, pos + size
  31.     end
  32.     if format == "<I4" then
  33.         return unpackInt(str, pos, 4, false)
  34.     elseif format == "<I2" then
  35.         return unpackInt(str, pos, 2, false)
  36.     elseif format == "BBB" then
  37.         return str:byte(pos), str:byte(pos+1), str:byte(pos+2), pos+3
  38.     else
  39.         error("Unsupported format: " .. format)
  40.     end
  41. end
  42.  
  43. local function loadBMP(imageData)
  44.     local width = stringUnpack("<I4", imageData, 19)
  45.     local height = stringUnpack("<I4", imageData, 23)
  46.     local bitsPerPixel = stringUnpack("<I2", imageData, 29)
  47.     local compression = stringUnpack("<I4", imageData, 31)
  48.     local dataOffset = stringUnpack("<I4", imageData, 11)
  49.     if bitsPerPixel ~= 24 or compression ~= 0 then
  50.         error("Unsupported BMP format. Only 24-bit uncompressed BMPs are supported.")
  51.     end
  52.     local texture = {}
  53.     local rowSize = math.floor((bitsPerPixel * width + 31) / 32) * 4
  54.     for y = 1, height do
  55.         texture[y] = {}
  56.         local rowStart = dataOffset + (height - y) * rowSize
  57.         for x = 1, width do
  58.             local pixelStart = rowStart + (x - 1) * 3
  59.             local b, g, r = stringUnpack("BBB", imageData, pixelStart + 1)
  60.             texture[y][x] = (r * 65536) + (g * 256) + b
  61.         end
  62.     end
  63.     return texture, width, height
  64. end
  65.  
  66. local function resizeBMP(bmp, origW, origH, newW, newH)
  67.     local resized = {}
  68.     for y = 1, newH do
  69.         resized[y] = {}
  70.         local srcY = math.floor((y-1) * origH / newH) + 1
  71.         for x = 1, newW do
  72.             local srcX = math.floor((x-1) * origW / newW) + 1
  73.             resized[y][x] = bmp[srcY][srcX]
  74.         end
  75.         if y % 2 == 0 then os.sleep(0) end
  76.     end
  77.     return resized
  78. end
  79.  
  80. local screenWidth, screenHeight = gpu.getResolution()
  81.  
  82. term.clear()
  83. print("Downloading loading screen...")
  84. local loadingImageData = download(loadingURL)
  85. local loadingBMP, loadingW, loadingH = loadBMP(loadingImageData)
  86. local loadingResized = resizeBMP(loadingBMP, loadingW, loadingH, screenWidth, screenHeight)
  87. for y = 1, screenHeight do
  88.     for x = 1, screenWidth do
  89.         gpu.setBackground(loadingResized[y][x])
  90.         gpu.set(x, y, " ")
  91.     end
  92.     if y % 2 == 0 then os.sleep(0) end
  93. end
  94.  
  95. print("Downloading floor texture...")
  96. local floorImageData = download(bmpURL)
  97. os.sleep(0)
  98. print("Downloading player sprite...")
  99. local playerImageData = download(playerURL)
  100. os.sleep(0)
  101.  
  102. local origFloorBMP, origFloorW, origFloorH = loadBMP(floorImageData)
  103. os.sleep(0)
  104. local bgWidth, bgHeight = 20, 20
  105. local background = resizeBMP(origFloorBMP, origFloorW, origFloorH, bgWidth, bgHeight)
  106. os.sleep(0)
  107.  
  108. local origPlayerBMP, origPlayerW, origPlayerH = loadBMP(playerImageData)
  109. os.sleep(0)
  110. local playerW, playerH = 8, 8
  111. local playerSprite = resizeBMP(origPlayerBMP, origPlayerW, origPlayerH, playerW, playerH)
  112. os.sleep(0)
  113.  
  114. local bufferIndex = gpu.allocateBuffer(screenWidth, screenHeight)
  115. if not bufferIndex then error("Failed to allocate GPU buffer (not enough GPU RAM?)") end
  116.  
  117. local foclength, horizon, scale = 100, 15, 60
  118. local camX, camY, camAngle = 10, 10, 0
  119. local playerX, playerY = 10, 10
  120. local jumpTime, jumpMax, isJumping, jumpVel = 0, 0.8, false, 0
  121. local camZ = 0
  122.  
  123. local keyboard = component.isAvailable("keyboard") and require("keyboard") or nil
  124. local keycodes = {w=17, a=30, s=31, d=32, space=57, q=16}
  125.  
  126. local lastTime = computer.uptime()
  127. local frameCount = 0
  128. local fps = 0
  129.  
  130. while true do
  131.     frameCount = frameCount + 1
  132.     local now = computer.uptime()
  133.     if now - lastTime >= 1 then
  134.         fps = frameCount
  135.         frameCount = 0
  136.         lastTime = now
  137.     end
  138.  
  139.     gpu.setActiveBuffer(bufferIndex)
  140.     gpu.setBackground(0x111133)
  141.     gpu.fill(1, 1, screenWidth, screenHeight, " ")
  142.     os.sleep(0)
  143.  
  144.     local halfW = screenWidth / 2
  145.     local cosA, sinA = cos(camAngle), sin(camAngle)
  146.  
  147.     for y = horizon, screenHeight do
  148.         local row = y - horizon
  149.         local invRow = 1 / (row + 1 - camZ)
  150.         for x = 1, screenWidth do
  151.             local dx = x - halfW
  152.             local dy = row
  153.             local wx = camX + (cosA * dx - sinA * dy) * scale * invRow
  154.             local wy = camY + (sinA * dx + cosA * dy) * scale * invRow
  155.             local bx = (floor(wx) % bgWidth) + 1
  156.             local by = (floor(wy) % bgHeight) + 1
  157.             gpu.setBackground(background[by][bx])
  158.             gpu.set(x, y, " ")
  159.         end
  160.         if y % 3 == 0 then os.sleep(0) end
  161.     end
  162.  
  163.     local px0 = floor(screenWidth / 2 - playerW / 2)
  164.     local py0 = floor(screenHeight / 2 - playerH / 2 - camZ)
  165.     for py = 1, playerH do
  166.         for px = 1, playerW do
  167.             local color = playerSprite[py][px]
  168.             gpu.setBackground(color)
  169.             gpu.set(px0 + px, py0 + py, " ")
  170.         end
  171.         if py % 2 == 0 then os.sleep(0) end
  172.     end
  173.  
  174.     gpu.setBackground(0x111133)
  175.     gpu.set(2, 2, ("FPS: %d"):format(fps))
  176.  
  177.     local text1 = "SMFX Clone by nonogamer9"
  178.     local text2 = "Ported to OpenComputers!"
  179.     local centerY = floor(screenHeight / 2 + playerH / 2 + 2)
  180.     local function centerText(y, txt)
  181.         local x = floor((screenWidth - #txt) / 2) + 1
  182.         gpu.set(x, y, txt)
  183.     end
  184.     gpu.setBackground(0x111133)
  185.     centerText(centerY, text1)
  186.     centerText(centerY + 1, text2)
  187.  
  188.     gpu.setActiveBuffer(0)
  189.     gpu.bitblt(0, 1, 1, screenWidth, screenHeight, bufferIndex, 1, 1)
  190.     os.sleep(0)
  191.  
  192.     local ev, _, _, code = event.pull(0.05, "key_down")
  193.     if ev then
  194.         if code == keycodes.q then break end
  195.         if code == keycodes.w then
  196.             playerX = playerX + cos(camAngle)
  197.             playerY = playerY + sin(camAngle)
  198.             camX = camX + cos(camAngle)
  199.             camY = camY + sin(camAngle)
  200.         end
  201.         if code == keycodes.s then
  202.             playerX = playerX - cos(camAngle)
  203.             playerY = playerY - sin(camAngle)
  204.             camX = camX - cos(camAngle)
  205.             camY = camY - sin(camAngle)
  206.         end
  207.         if code == keycodes.a then
  208.             playerX = playerX + sin(camAngle)
  209.             playerY = playerY - cos(camAngle)
  210.             camX = camX + sin(camAngle)
  211.             camY = camY - cos(camAngle)
  212.         end
  213.         if code == keycodes.d then
  214.             playerX = playerX - sin(camAngle)
  215.             playerY = playerY + cos(camAngle)
  216.             camX = camX - sin(camAngle)
  217.             camY = camY + cos(camAngle)
  218.         end
  219.         if code == keycodes.space and not isJumping then
  220.             isJumping = true
  221.             jumpVel = 0.25
  222.             jumpTime = 0
  223.         end
  224.     end
  225.  
  226.     camAngle = camAngle + 0.01
  227.  
  228.     if isJumping then
  229.         camZ = camZ + jumpVel
  230.         jumpVel = jumpVel - 0.025
  231.         if camZ <= 0 then
  232.             camZ = 0
  233.             isJumping = false
  234.             jumpVel = 0
  235.         end
  236.         os.sleep(0)
  237.     end
  238.     os.sleep(0)
  239. end
  240.  
  241. gpu.setActiveBuffer(0)
  242. gpu.freeBuffer(bufferIndex)
  243. gpu.setBackground(0x000000)
  244. gpu.fill(1, 1, screenWidth, screenHeight, " ")
  245.  
Add Comment
Please, Sign In to add comment