Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local event = require("event")
- local gpu = component.gpu
- local internet = require("internet")
- local term = require("term")
- local computer = require("computer")
- local floor, cos, sin, abs = math.floor, math.cos, math.sin, math.abs
- local loadingURL = "https://files.catbox.moe/l8tnog.bmp"
- local bmpURL = "https://files.catbox.moe/w9tlsn.bmp"
- local playerURL = "https://files.catbox.moe/fzau50.bmp"
- local function download(url)
- local response = internet.request(url)
- if not response then error("Failed to download: " .. url) end
- local data = ""
- for chunk in response do data = data .. chunk end
- return data
- end
- local function stringUnpack(format, str, pos)
- local function unpackInt(str, pos, size, signed)
- local val = 0
- for i = 0, size - 1 do
- val = val + str:byte(pos + i) * (256 ^ i)
- end
- if signed and val >= 2^(size*8-1) then
- val = val - 2^(size*8)
- end
- return val, pos + size
- end
- if format == "<I4" then
- return unpackInt(str, pos, 4, false)
- elseif format == "<I2" then
- return unpackInt(str, pos, 2, false)
- elseif format == "BBB" then
- return str:byte(pos), str:byte(pos+1), str:byte(pos+2), pos+3
- else
- error("Unsupported format: " .. format)
- end
- end
- local function loadBMP(imageData)
- local width = stringUnpack("<I4", imageData, 19)
- local height = stringUnpack("<I4", imageData, 23)
- local bitsPerPixel = stringUnpack("<I2", imageData, 29)
- local compression = stringUnpack("<I4", imageData, 31)
- local dataOffset = stringUnpack("<I4", imageData, 11)
- if bitsPerPixel ~= 24 or compression ~= 0 then
- error("Unsupported BMP format. Only 24-bit uncompressed BMPs are supported.")
- end
- local texture = {}
- local rowSize = math.floor((bitsPerPixel * width + 31) / 32) * 4
- for y = 1, height do
- texture[y] = {}
- local rowStart = dataOffset + (height - y) * rowSize
- for x = 1, width do
- local pixelStart = rowStart + (x - 1) * 3
- local b, g, r = stringUnpack("BBB", imageData, pixelStart + 1)
- texture[y][x] = (r * 65536) + (g * 256) + b
- end
- end
- return texture, width, height
- end
- local function resizeBMP(bmp, origW, origH, newW, newH)
- local resized = {}
- for y = 1, newH do
- resized[y] = {}
- local srcY = math.floor((y-1) * origH / newH) + 1
- for x = 1, newW do
- local srcX = math.floor((x-1) * origW / newW) + 1
- resized[y][x] = bmp[srcY][srcX]
- end
- if y % 2 == 0 then os.sleep(0) end
- end
- return resized
- end
- local screenWidth, screenHeight = gpu.getResolution()
- term.clear()
- print("Downloading loading screen...")
- local loadingImageData = download(loadingURL)
- local loadingBMP, loadingW, loadingH = loadBMP(loadingImageData)
- local loadingResized = resizeBMP(loadingBMP, loadingW, loadingH, screenWidth, screenHeight)
- for y = 1, screenHeight do
- for x = 1, screenWidth do
- gpu.setBackground(loadingResized[y][x])
- gpu.set(x, y, " ")
- end
- if y % 2 == 0 then os.sleep(0) end
- end
- print("Downloading floor texture...")
- local floorImageData = download(bmpURL)
- os.sleep(0)
- print("Downloading player sprite...")
- local playerImageData = download(playerURL)
- os.sleep(0)
- local origFloorBMP, origFloorW, origFloorH = loadBMP(floorImageData)
- os.sleep(0)
- local bgWidth, bgHeight = 20, 20
- local background = resizeBMP(origFloorBMP, origFloorW, origFloorH, bgWidth, bgHeight)
- os.sleep(0)
- local origPlayerBMP, origPlayerW, origPlayerH = loadBMP(playerImageData)
- os.sleep(0)
- local playerW, playerH = 8, 8
- local playerSprite = resizeBMP(origPlayerBMP, origPlayerW, origPlayerH, playerW, playerH)
- os.sleep(0)
- local bufferIndex = gpu.allocateBuffer(screenWidth, screenHeight)
- if not bufferIndex then error("Failed to allocate GPU buffer (not enough GPU RAM?)") end
- local foclength, horizon, scale = 100, 15, 60
- local camX, camY, camAngle = 10, 10, 0
- local playerX, playerY = 10, 10
- local jumpTime, jumpMax, isJumping, jumpVel = 0, 0.8, false, 0
- local camZ = 0
- local keyboard = component.isAvailable("keyboard") and require("keyboard") or nil
- local keycodes = {w=17, a=30, s=31, d=32, space=57, q=16}
- local lastTime = computer.uptime()
- local frameCount = 0
- local fps = 0
- while true do
- frameCount = frameCount + 1
- local now = computer.uptime()
- if now - lastTime >= 1 then
- fps = frameCount
- frameCount = 0
- lastTime = now
- end
- gpu.setActiveBuffer(bufferIndex)
- gpu.setBackground(0x111133)
- gpu.fill(1, 1, screenWidth, screenHeight, " ")
- os.sleep(0)
- local halfW = screenWidth / 2
- local cosA, sinA = cos(camAngle), sin(camAngle)
- for y = horizon, screenHeight do
- local row = y - horizon
- local invRow = 1 / (row + 1 - camZ)
- for x = 1, screenWidth do
- local dx = x - halfW
- local dy = row
- local wx = camX + (cosA * dx - sinA * dy) * scale * invRow
- local wy = camY + (sinA * dx + cosA * dy) * scale * invRow
- local bx = (floor(wx) % bgWidth) + 1
- local by = (floor(wy) % bgHeight) + 1
- gpu.setBackground(background[by][bx])
- gpu.set(x, y, " ")
- end
- if y % 3 == 0 then os.sleep(0) end
- end
- local px0 = floor(screenWidth / 2 - playerW / 2)
- local py0 = floor(screenHeight / 2 - playerH / 2 - camZ)
- for py = 1, playerH do
- for px = 1, playerW do
- local color = playerSprite[py][px]
- gpu.setBackground(color)
- gpu.set(px0 + px, py0 + py, " ")
- end
- if py % 2 == 0 then os.sleep(0) end
- end
- gpu.setBackground(0x111133)
- gpu.set(2, 2, ("FPS: %d"):format(fps))
- local text1 = "SMFX Clone by nonogamer9"
- local text2 = "Ported to OpenComputers!"
- local centerY = floor(screenHeight / 2 + playerH / 2 + 2)
- local function centerText(y, txt)
- local x = floor((screenWidth - #txt) / 2) + 1
- gpu.set(x, y, txt)
- end
- gpu.setBackground(0x111133)
- centerText(centerY, text1)
- centerText(centerY + 1, text2)
- gpu.setActiveBuffer(0)
- gpu.bitblt(0, 1, 1, screenWidth, screenHeight, bufferIndex, 1, 1)
- os.sleep(0)
- local ev, _, _, code = event.pull(0.05, "key_down")
- if ev then
- if code == keycodes.q then break end
- if code == keycodes.w then
- playerX = playerX + cos(camAngle)
- playerY = playerY + sin(camAngle)
- camX = camX + cos(camAngle)
- camY = camY + sin(camAngle)
- end
- if code == keycodes.s then
- playerX = playerX - cos(camAngle)
- playerY = playerY - sin(camAngle)
- camX = camX - cos(camAngle)
- camY = camY - sin(camAngle)
- end
- if code == keycodes.a then
- playerX = playerX + sin(camAngle)
- playerY = playerY - cos(camAngle)
- camX = camX + sin(camAngle)
- camY = camY - cos(camAngle)
- end
- if code == keycodes.d then
- playerX = playerX - sin(camAngle)
- playerY = playerY + cos(camAngle)
- camX = camX - sin(camAngle)
- camY = camY + cos(camAngle)
- end
- if code == keycodes.space and not isJumping then
- isJumping = true
- jumpVel = 0.25
- jumpTime = 0
- end
- end
- camAngle = camAngle + 0.01
- if isJumping then
- camZ = camZ + jumpVel
- jumpVel = jumpVel - 0.025
- if camZ <= 0 then
- camZ = 0
- isJumping = false
- jumpVel = 0
- end
- os.sleep(0)
- end
- os.sleep(0)
- end
- gpu.setActiveBuffer(0)
- gpu.freeBuffer(bufferIndex)
- gpu.setBackground(0x000000)
- gpu.fill(1, 1, screenWidth, screenHeight, " ")
Add Comment
Please, Sign In to add comment