Advertisement
Xelostar

ThreeD_API_v0.5.1_Demo2

Jul 22nd, 2018
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.09 KB | None | 0 0
  1.  
  2. -- Made by Xelostar: https://www.youtube.com/channel/UCDE2STpSWJrIUyKtiYGeWxw
  3.  
  4. local path = "/"..shell.dir() -- path to this program
  5.  
  6. os.loadAPI(path.."/ThreeD") -- loading the APIs
  7. os.loadAPI(path.."/bufferAPI")
  8. os.loadAPI(path.."/blittle")
  9.  
  10. local objects = {} -- all objects in the game
  11.  
  12. local size = 3
  13. for x = 1, size do
  14.     for z = 1, size do
  15.         for y = 1, size do
  16.             objects[#objects+1] = {model = "box", x = x, y = y - 0.5, z = z, solid = true}
  17.         end
  18.     end
  19. end
  20.  
  21. local playerX = -3 -- player position
  22. local playerY = 0
  23. local playerZ = 1
  24.  
  25. local playerSpeed = 3 -- player movement speed
  26. local playerTurnSpeed = 180 -- player turn speed
  27.  
  28. local keysDown = {} -- keysDown[key] is true if the key is down (for smooth input)
  29. local blockThickness = 0.9 -- the size of the hitbox for the solid blocks from the middle of the object
  30.  
  31. local FoV = 90 -- field of view
  32.  
  33. local playerDirectionHor = 0 -- camera direction
  34. local playerDirectionVer = 0
  35.  
  36. local screenWidth, screenHeight = term.getSize() -- size of the screen
  37.  
  38. local backgroundColor1 = colors.lime -- ground color
  39. local backgroundColor2 = colors.lightBlue -- sky color
  40.  
  41. local ThreeDFrame = ThreeD.newFrame(1, 1, screenWidth, screenHeight, FoV, playerX, playerY + 0.5, playerZ, playerDirectionVer, playerDirectionHor, path.."/models") -- making a new frame where the camera is 0.5 blocks above the player
  42. local blittleOn = true -- blittle is turned on by default
  43. ThreeDFrame:useBLittle(blittleOn) -- set the frame to use blittle
  44.  
  45. local totalTime = 0 -- time in seconds elapsed since the start of the program
  46.  
  47. local function rendering()
  48.     while true do
  49.         ThreeDFrame:loadGround(backgroundColor1)
  50.         ThreeDFrame:loadSky(backgroundColor2)
  51.         ThreeDFrame:loadObjects(objects)
  52.         ThreeDFrame:drawBuffer()
  53.  
  54.         os.queueEvent("FakeEvent") -- to prevent "too long without yielding" errors without slowing down the program
  55.         os.pullEvent("FakeEvent")
  56.     end
  57. end
  58.  
  59. local function free(x, y, z) -- for collision detection. Tests to see if there's a hitbox (x, y, z) is in
  60.     for _, object in pairs(objects) do
  61.         if (object.solid == true) then
  62.             if (x >= object.x - blockThickness and x <= object.x + blockThickness) then
  63.                 if (y >= object.y - 1 and y <= object.y + 0.5 + 0.2) then -- the height is done differently, since the  player has to have a certain height (different collision from feet and head)
  64.                     if (z >= object.z - blockThickness and z <= object.z + blockThickness) then
  65.                         return false -- collision detected
  66.                     end
  67.                 end
  68.             end
  69.         end
  70.     end
  71.  
  72.     return true -- no collision detected
  73. end
  74.  
  75. local function inputPlayer(time) -- time is the elapsed time in seconds since the last time this function was executed
  76.     local dx = 0
  77.     local dy = 0
  78.     local dz = 0
  79.  
  80.     if (keysDown[keys.left]) then
  81.         playerDirectionHor = playerDirectionHor - playerTurnSpeed * time
  82.         if (playerDirectionHor <= -180) then
  83.             playerDirectionHor = playerDirectionHor + 360
  84.         end
  85.     end
  86.     if (keysDown[keys.right]) then
  87.         playerDirectionHor = playerDirectionHor + playerTurnSpeed * time
  88.         if (playerDirectionHor >= 180) then
  89.             playerDirectionHor = playerDirectionHor - 360
  90.         end
  91.     end
  92.     if (keysDown[keys.down]) then
  93.         playerDirectionVer = playerDirectionVer - playerTurnSpeed * time
  94.         if (playerDirectionVer < -80) then
  95.             playerDirectionVer = -80
  96.         end
  97.     end
  98.     if (keysDown[keys.up]) then
  99.         playerDirectionVer = playerDirectionVer + playerTurnSpeed * time
  100.         if (playerDirectionVer > 80) then
  101.             playerDirectionVer = 80
  102.         end
  103.     end
  104.     if (keysDown[keys.w]) then
  105.         dx = playerSpeed * math.cos(math.rad(playerDirectionHor)) + dx
  106.         dz = playerSpeed * math.sin(math.rad(playerDirectionHor)) + dz
  107.     end
  108.     if (keysDown[keys.s]) then
  109.         dx = -playerSpeed * math.cos(math.rad(playerDirectionHor)) + dx
  110.         dz = -playerSpeed * math.sin(math.rad(playerDirectionHor)) + dz
  111.     end
  112.     if (keysDown[keys.a]) then
  113.         dx = playerSpeed * math.cos(math.rad(playerDirectionHor - 90)) + dx
  114.         dz = playerSpeed * math.sin(math.rad(playerDirectionHor - 90)) + dz
  115.     end
  116.     if (keysDown[keys.d]) then
  117.         dx = playerSpeed * math.cos(math.rad(playerDirectionHor + 90)) + dx
  118.         dz = playerSpeed * math.sin(math.rad(playerDirectionHor + 90)) + dz
  119.     end
  120.    
  121.     if (keysDown[keys.space]) then
  122.         dy = playerSpeed + dy
  123.     end
  124.     if (keysDown[keys.leftShift]) then
  125.         dy = -playerSpeed + dy
  126.     end
  127.    
  128.     -- if where the player will move to is free (no collisions) then move there
  129.     if (free(playerX + dx * time, playerY, playerZ) == true) then
  130.         playerX = playerX + dx * time -- multiply by time so that dx becomes blocks per second
  131.     end
  132.     if (playerY + dy * time >= 0) then
  133.         if (free(playerX, playerY + dy * time, playerZ) == true) then
  134.             playerY = playerY + dy * time
  135.         end
  136.     end
  137.     if (free(playerX, playerY, playerZ + dz * time) == true) then
  138.         playerZ = playerZ + dz * time
  139.     end
  140.  
  141.     ThreeDFrame:setCamera(playerX, playerY + 0.5, playerZ, playerDirectionHor, playerDirectionVer) -- set the new camera position according to the player (again the height is 0.5 blocks above the feet)
  142. end
  143.  
  144. local function keyInput()
  145.     while true do
  146.         local event, key, x, y = os.pullEventRaw()
  147.  
  148.         if (event == "key") then -- detect key presses
  149.             keysDown[key] = true
  150.             if (key == keys.g) then -- if the button is supposed to be pressed once, we'll deal with the processing of the input here
  151.                 if (blittleOn == false) then
  152.                     blittleOn = true
  153.                     ThreeDFrame:useBLittle(true)
  154.                 else
  155.                     blittleOn = false
  156.                     ThreeDFrame:useBLittle(false)
  157.                 end
  158.             end
  159.         elseif (event == "key_up") then -- detect key releases
  160.             keysDown[key] = nil
  161.         elseif (event == "mouse_click") then
  162.             local objectIndex, polyIndex = ThreeDFrame:getObjectIndexTrace(objects, x, y) -- detect on what and object the player clicked
  163.             if (objectIndex ~= nil) then -- if the player clicked on an object (not void)
  164.                 table.remove(objects, objectIndex) -- remove the object the player clicked on
  165.             end
  166.         end
  167.     end
  168. end
  169.  
  170. local function updateGame(time) -- time is the elapsede time in seconds since the last time this function was executed
  171.     totalTime = totalTime + time -- increase the total time that has elapsed
  172.     for objectNr, object in pairs(objects) do
  173.         if (object.model == "pineapple") then -- for all pineapples:
  174.             object.y = math.sin(totalTime*2)/4 -- set their height according to totalTime to make them smoothly bob up and down
  175.             object.rotationY = object.rotationY + 50*time -- increase their rotation according to the time that has elapsed (50 degrees per second of rotation)
  176.         end
  177.     end
  178. end
  179.  
  180. local function gameUpdate() -- this function uses some trickery to estimate the time elapsed more precise than 1 Minecraft tick (0.05 seconds)
  181.     -- a lot of the time, withing each game tick about three frames are rendered which means that the accuracy is more like 0.02 seconds
  182.     local timeFromLastUpdate = os.clock() -- the time frome last update
  183.     local avgUpdateSpeed = 0 -- this indicates the average update speed in seconds per frame
  184.     local updateCount = 0 -- keep track of the frames drawn between each game tick
  185.  
  186.     while true do
  187.         local currentTime = os.clock() -- the current time
  188.         if (currentTime <= timeFromLastUpdate) then
  189.             updateGame(avgUpdateSpeed) -- still the same game tick as the last frame, so just update it with the average delay
  190.             inputPlayer(avgUpdateSpeed) -- same for the player input
  191.  
  192.             updateCount = updateCount + 1 -- increase the update counter
  193.             if (updateCount >= 3) then
  194.                 sleep(0)
  195.             end
  196.         else -- if the next game tick is here:
  197.             local timeOff = -avgUpdateSpeed * (updateCount - 1)
  198.  
  199.             updateGame(currentTime - timeFromLastUpdate + timeOff) -- update the game normally with the difference in time minus the time we estimated wrongly to compensate
  200.             inputPlayer(currentTime - timeFromLastUpdate + timeOff) -- same for the player input
  201.  
  202.             avgUpdateSpeed = 0.05 / (updateCount + 2) -- calculate the new average delay between each frame
  203.  
  204.             updateCount = 1 -- set the update counter to 0 to restart counting
  205.             timeFromLastUpdate = currentTime -- update the time since the last update
  206.         end
  207.  
  208.         coroutine.yield()
  209.     end
  210. end
  211.  
  212. parallel.waitForAll(keyInput, gameUpdate, rendering) -- handle input, the game mechanics and the rendering simultaniously
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement