Advertisement
jesusthekiller

maze3d_template

Jun 14th, 2013
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.02 KB | None | 0 0
  1. local buffer=term
  2. local loadedAPI=false
  3.  
  4. local function cwrite(msg)
  5.   msg = tostring(msg)
  6.   local x, y = term.getCursorPos()
  7.   term.setCursorPos((51-#msg)/2, y)
  8.   write(msg)
  9. end
  10.  
  11. local function cprint(msg)
  12.   cwrite(msg.."\n")
  13. end
  14.  
  15. local stime = os.clock()
  16.  
  17. if redirect then
  18.   buffer=redirect.createRedirectBuffer()
  19.   print("redirect API found, using buffer")
  20. else
  21.  if not fs.exists("redirect") then  -- Edit
  22.     shell.run("pastebin", "get", "fU9Kj9zr", "redirect")
  23.   end
  24.   local pe=printError
  25.   rawset(_G,"printError",error)  
  26.   local ok, err=pcall(os.loadAPI,"redirect")
  27.   if not ok then
  28.     print("trying "..shell.dir().."/redirect")
  29.     ok,err=pcall(os.loadAPI,shell.dir().."/redirect")
  30.   end
  31.   if ok then    
  32.     print("Loaded redirect API, using buffer")
  33.     buffer=redirect.createRedirectBuffer()
  34.     loadedAPI=true
  35.   else
  36.     print("redirect API not found or could not be loaded, drawing directly; this may cause flickering.")
  37.   end
  38.   rawset(_G,"printError",pe)
  39.  
  40. end
  41.  
  42. local colorSchemes = {
  43.   {0,8}, --white+gray
  44.   {3,11}, --blue
  45.   {6,14}, --red
  46.   {5,13}, --green
  47.   {4,1}, --yellow/orange
  48. }
  49.  
  50.  
  51. local function cast(cx,cy,angle)
  52.   --direction vector
  53.   local vx,vy=math.cos(angle), math.sin(angle)
  54.   local slope=vy/vx
  55.   --next distance, x and y axis points
  56.   local ndx, ndy
  57.   --steps, distance and block
  58.   local dsx, dsy, bsx, bsy
  59.   if vx<0 then
  60.     local x=(cx%1)
  61.     bsx=-1
  62.     ndx=math.sqrt(x*x*(1+slope*slope))
  63.     dsx=math.sqrt((1+slope*slope))
  64.   else
  65.     local x=1-(cx%1)
  66.     bsx=1
  67.     ndx=math.sqrt(x*x*(1+slope*slope))
  68.     dsx=math.sqrt((1+slope*slope))
  69.   end
  70.  
  71.   if vy<0 then
  72.     local y=(cy%1)
  73.     bsy=-1
  74.     ndy=math.sqrt(y*y*(1+1/(slope*slope)))
  75.     dsy=math.sqrt((1+1/(slope*slope)))
  76.   else
  77.     local y=1-(cy%1)
  78.     bsy=1
  79.     ndy=math.sqrt(y*y*(1+1/(slope*slope)))
  80.     dsy=math.sqrt((1+1/(slope*slope)))
  81.   end
  82.  
  83.   local x,y=math.floor(cx),math.floor(cy)
  84.   while x>0 and x<=mapW and y>0 and y<=mapH do
  85.     local hitD
  86.     local isX
  87.     if ndx<ndy then
  88.       --x crossing is next
  89.       x=x+bsx
  90.       isX=true
  91.       hitD=ndx
  92.       ndx=ndx+dsx
  93.     else
  94.       y=y+bsy
  95.       isX=false
  96.       hitD=ndy
  97.       ndy=ndy+dsy
  98.     end
  99.     local wall=map[y]:sub(x,x)
  100.     if wall~=" " then
  101.      
  102.       return colorSchemes[tonumber(wall)][isX and 1 or 2], hitD
  103.     end
  104.   end  
  105. end
  106.  
  107. local w,h=term.getSize()
  108. local centerX, centerY=math.floor((w+1)/2), math.floor((h+1)/2)
  109.  
  110. local px, py=2.5,2.5
  111. local dir=0
  112. local fx,fy
  113. local speed=.1
  114. local turnSpeed=4
  115.  
  116. local function turn(amt)
  117.   dir=dir+amt
  118.   fx,fy=math.cos(math.rad(dir)), math.sin(math.rad(dir))
  119. end
  120.  
  121. turn(0)
  122.  
  123. --build table of angles and base distances per scanline
  124. local screenDist=.55*w
  125. local scan={}
  126.  
  127. for x=1,w do
  128.   local t={}
  129.   scan[x]=t
  130.   t.angle=math.atan2(x-centerX,screenDist)
  131.   t.dist=((x-centerX)^2+screenDist^2)^.5/screenDist
  132. end
  133.  
  134. local function redraw()
  135.   if buffer.isBuffer then
  136.     term.redirect(buffer)
  137.   end
  138.   for x=1,w do
  139.     local wall,dist=cast(px,py,math.rad(dir)+scan[x].angle)
  140.     if wall then
  141.       --calc wall height based on distance
  142.       local height=scan[x].dist/dist
  143.       height=math.floor(math.min(height*centerY,(h+1)/2))
  144.       term.setBackgroundColor(colors.gray)
  145.       for y=1,(h+1)/2-height-1 do
  146.         term.setCursorPos(x,y)
  147.         term.write(" ")
  148.       end
  149.       for y=centerY+height+1,h do
  150.         term.setCursorPos(x,y)
  151.         term.write(" ")
  152.       end
  153.       term.setBackgroundColor(2^wall)
  154.       for y=centerY-height,centerY+height do
  155.         term.setCursorPos(x,y)
  156.         term.write(" ")
  157.       end
  158.     end
  159.   end
  160.   if buffer.isBuffer then
  161.     term.restore()
  162.     buffer.blit()
  163.   end
  164. end
  165.  
  166. local function clampCollision(x,y,radius)
  167.   --am I *in* a block?
  168.   local gx,gy=math.floor(x),math.floor(y)
  169.   if map[gy]:sub(gx,gx)~=" " then
  170.     --I am. Complete fail, do nothing.
  171.     return x,y
  172.   end
  173.  
  174.   --ok, check the neighbors.
  175.   local right=math.floor(x+radius)>gx
  176.   local left=math.floor(x-radius)<gx
  177.   local front=math.floor(y-radius)<gy
  178.   local back=math.floor(y+radius)>gy
  179.  
  180.   local pushed=false
  181.  
  182.   if right and map[gy]:sub(gx+1,gx+1)~=" " then
  183.     --push left
  184.     pushed=true
  185.     x=gx+1-radius
  186.   elseif left  and map[gy]:sub(gx-1,gx-1)~=" " then
  187.     --push right
  188.     pushed=true
  189.     x=gx+radius
  190.   end
  191.  
  192.   if front and map[gy-1]:sub(gx,gx)~=" " then
  193.     --push back
  194.     pushed=true
  195.     y=gy+radius
  196.   elseif back and map[gy+1]:sub(gx,gx)~=" " then
  197.     --push forward
  198.     pushed=true
  199.     y=gy+1-radius
  200.   end
  201.  
  202.   --if I wasn't pushed out on any side, I might be hitting a corner
  203.   if not pushed then
  204.     --square rad
  205.     local r2=radius^2
  206.     local pushx,pushy=0,0
  207.     if left then
  208.       if front and map[gy-1]:sub(gx-1,gx-1)~=" " then
  209.         --check front-left
  210.         local dist2=(gx-x)^2+(gy-y)^2
  211.         if dist2<r2 then
  212.           local pushd=(r2-dist2)/2^.5
  213.           pushx,pushy=pushd,pushd
  214.         end
  215.       elseif back and map[gy+1]:sub(gx-1,gx-1)~=" " then
  216.         local dist2=(gx-x)^2+(gy+1-y)^2
  217.         if dist2<r2 then
  218.           local pushd=(r2-dist2)/2^.5
  219.           pushx,pushy=pushd,-pushd
  220.         end
  221.       end
  222.     elseif right then
  223.       if front and map[gy-1]:sub(gx+1,gx+1)~=" " then
  224.         --check front-left
  225.         local dist2=(gx+1-x)^2+(gy-y)^2
  226.         if dist2<r2 then
  227.           local pushd=(r2-dist2)/2^.5
  228.           pushx,pushy=-pushd,pushd
  229.         end
  230.       elseif back and map[gy+1]:sub(gx+1,gx+1)~=" " then
  231.         local dist2=(gx+1-x)^2+(gy+1-y)^2
  232.         if dist2<r2 then
  233.           local pushd=(r2-dist2)/2^.5
  234.           pushx,pushy=-pushd,-pushd
  235.         end
  236.       end
  237.     end
  238.     x=x+pushx
  239.     y=y+pushy
  240.   end
  241.  
  242.   return x,y
  243. end
  244.  
  245. term.setBackgroundColor(colors.black)
  246. term.setTextColor(colors.white)
  247. term.clear()
  248. term.setCursorPos(1, 1)
  249.  
  250. print([[
  251. Move: WASD
  252. Turn: Arrow Right/Left
  253. Go to start: R
  254. Quit: Q
  255.  
  256. Go to blue block.
  257.  
  258. If you will see white screen, turn around!
  259.  
  260. Press any key to begin...]])
  261.  
  262. os.pullEvent("key")
  263.  
  264. local frameTimer=os.startTimer(0.5)
  265. local prevTick=0
  266. local dirty=true
  267. local win = false
  268. while true do
  269.   px,py=clampCollision(px,py,.25)
  270.   if dirty then
  271.     redraw()
  272.     dirty=false
  273.   end
  274.  
  275.   local e={os.pullEvent()}
  276.   if e[1]=="key" then
  277.     if e[2]==keys.left then
  278.       turn(-turnSpeed)
  279.       dirty=true
  280.     elseif e[2]==keys.right then
  281.       turn(turnSpeed)
  282.       dirty=true
  283.     elseif e[2]==keys.up or e[2]==keys.w then
  284.       px=px+fx*speed
  285.       py=py+fy*speed
  286.       dirty=true
  287.     elseif e[2]==keys.down or e[2]==keys.s then
  288.       px=px-fx*speed
  289.       py=py-fy*speed
  290.       dirty=true
  291.     elseif e[2]==keys.a then
  292.       px=px+fy*speed
  293.       py=py-fx*speed
  294.       dirty=true
  295.     elseif e[2]==keys.d then
  296.       px=px-fy*speed
  297.       py=py+fx*speed
  298.       dirty=true
  299.     elseif e[2]==keys.q then
  300.       break
  301.     elseif e[2]==keys.r then
  302.       px,py = 2.5,2.5
  303.       dirty=true
  304.     end
  305.    
  306.     if px >= mapW-1 and py >= mapH-1 then
  307.       win = true
  308.       break
  309.     end
  310.   end
  311. end
  312.  
  313.  
  314. if loadedAPI then
  315.   os.unloadAPI("redirect")
  316. end
  317.  
  318. -- JESUS PART
  319.  
  320. -- The win/loose message
  321. term.setBackgroundColor(colors.white)
  322. term.setTextColor(colors.black)
  323. term.clear()
  324. term.setCursorPos(1, 1)
  325.  
  326. if win then
  327.   local ntime = os.clock()
  328.   write("\n")
  329.   cprint("Congratulations!")
  330.   cprint("You made it in")
  331.   cprint(tostring(math.floor((ntime-stime)/60)).." minutes and "..tostring(math.ceil((ntime-stime)%60)).." seconds")
  332.   cprint("Size of maze: "..(mapW-1)/2)
  333. else
  334.   write("\n")
  335.   cprint("Oh noes D:")
  336. end
  337.  
  338. sleep(2)
  339.  
  340. parallel.waitForAny(
  341.   function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end,
  342.   function() term.setBackgroundColor(colors.white); term.setTextColor(colors.black) while true do term.setCursorPos(18, 14); term.write("Press any key.."); sleep(0.5); term.clearLine(); sleep(0.5) end end
  343. )
  344.  
  345. term.setBackgroundColor(colors.black)
  346. term.setTextColor(colors.white)
  347. term.clear()
  348. term.setCursorPos(1, 1)
  349. cprint("  Maze by Jesusthekiller. Thanks for playing!")
  350. cprint("3D engine by Gopher, He is A-W-E-S-O-M-E")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement