SHARE
TWEET

Untitled

a guest Feb 28th, 2013 258 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local mapW, mapH=16,32
  2.  
  3. w, h = term.getSize()
  4.  
  5. local map={
  6.   "1111111111111111",
  7.   "1   12         1",
  8.   "1 111111111111 1",
  9.   "1 1      1   1 1",
  10.   "1 1 1111 1 1 1 1",
  11.   "1 1   1  1 1   1",
  12.   "1 111 111111 111",
  13.   "1   1          1",
  14.   "111 11111111 1 1",
  15.   "1 1          1 1",
  16.   "1 111111111111 1",
  17.   "1   1 1    1   1",
  18.   "1 111 1 1111 111",
  19.   "1     1    1   1",
  20.   "1 11111111 111 1",
  21.   "1              1",
  22.   "1111114  4111111",
  23.   "1              1",
  24.   "1              1",
  25.   "1  3  2  2  3  1",
  26.   "1              1",
  27.   "1              1",
  28.   "1  2  5  5  2  1",
  29.   "1              1",
  30.   "1              1",
  31.   "1  2  5  5  2  1",
  32.   "1              1",
  33.   "1              1",
  34.   "1  3  2  2  3  1",
  35.   "1              1",
  36.   "1              1",
  37.   "1111111111111111",
  38. }  
  39.  
  40. local colorSchemes = {
  41.   {0,8}, --white+gray
  42.   {3,11}, --blue
  43.   {6,14}, --red
  44.   {5,13}, --green
  45.   {4,1}, --yellow/orange
  46. }
  47.  
  48.  
  49. local function cast(cx,cy,angle)
  50.   --direction vector
  51.   local vx,vy=math.cos(angle), math.sin(angle)
  52.   local slope=vy/vx
  53.   --next distance, x and y axis points
  54.   local ndx, ndy
  55.   --steps, distance and block
  56.   local dsx, dsy, bsx, bsy
  57.   if vx<0 then
  58.     local x=(cx%1)
  59.     bsx=-1
  60.     ndx=math.sqrt(x*x*(1+slope*slope))
  61.     dsx=math.sqrt((1+slope*slope))
  62.   else
  63.     local x=1-(cx%1)
  64.     bsx=1
  65.     ndx=math.sqrt(x*x*(1+slope*slope))
  66.     dsx=math.sqrt((1+slope*slope))
  67.   end
  68.  
  69.   if vy<0 then
  70.     local y=(cy%1)
  71.     bsy=-1
  72.     ndy=math.sqrt(y*y*(1+1/(slope*slope)))
  73.     dsy=math.sqrt((1+1/(slope*slope)))
  74.   else
  75.     local y=1-(cy%1)
  76.     bsy=1
  77.     ndy=math.sqrt(y*y*(1+1/(slope*slope)))
  78.     dsy=math.sqrt((1+1/(slope*slope)))
  79.   end
  80.  
  81.   local x,y=math.floor(cx),math.floor(cy)
  82.   while x>0 and x<=mapW and y>0 and y<=mapH do
  83.     local hitD
  84.     local isX
  85.     if ndx<ndy then
  86.       --x crossing is next
  87.       x=x+bsx
  88.       isX=true
  89.       hitD=ndx
  90.       ndx=ndx+dsx
  91.     else
  92.       y=y+bsy
  93.       isX=false
  94.       hitD=ndy
  95.       ndy=ndy+dsy
  96.     end
  97.     local wall=map[y]:sub(x,x)
  98.     if wall~=" " then
  99.      
  100.       return colorSchemes[tonumber(wall)][isX and 1 or 2], hitD
  101.     end
  102.   end  
  103. end
  104.  
  105. local px, py=8.5,24.5
  106. local dir=0
  107. local fx,fy
  108. local speed=.1
  109. local turnSpeed=2.5
  110.  
  111. local function turn(amt)
  112.   dir=dir+amt
  113.   fx,fy=math.cos(math.rad(dir)), math.sin(math.rad(dir))
  114. end
  115.  
  116. turn(0)
  117.  
  118. --build table of angles and base distances per scanline
  119. local screenDist=40
  120. local scan={}
  121.  
  122. for x=1,w do
  123.   local t={}
  124.   scan[x]=t
  125.   t.angle=math.atan2(x-(w / 2),screenDist)
  126.   t.dist=((x-(w / 2))^2+screenDist^2)^.5/screenDist
  127. end
  128.  
  129. local function redraw()
  130.   term.setBackgroundColor(colors.gray)
  131.   term.clear()
  132.   --term.setBackgroundColor(colors.gray)
  133.   --for y=10,19 do
  134.   --  term.setCursorPos(1,y)
  135.   --  term.clearLine()
  136.   --end
  137.   for x=1,w do
  138.     local wall,dist=cast(px,py,math.rad(dir)+scan[x].angle)
  139.     if wall then
  140.       term.setBackgroundColor(2^wall)
  141.       --calc wall height based on distance
  142.       local height=scan[x].dist/dist
  143.       height=math.floor(height*9)
  144.       for y=(h/2)-height,(h/2)+height do
  145.         term.setCursorPos(x,y)
  146.         term.write(" ")
  147.       end
  148.     end
  149.   end
  150.  
  151.   term.setBackgroundColor(colors.black)
  152.   term.setTextColor(colors.white)
  153.   term.setCursorPos(w / 2, h / 2)
  154.   term.write("+")
  155. end
  156.  
  157. local function clampCollision(x,y,radius)
  158.   --am I *in* a block?
  159.   local gx,gy=math.floor(x),math.floor(y)
  160.   if map[gy]:sub(gx,gx)~=" " then
  161.     --I am. Complete fail, do nothing.
  162.     return x,y
  163.   end
  164.  
  165.   --ok, check the neighbors.
  166.   local right=math.floor(x+radius)>gx
  167.   local left=math.floor(x-radius)<gx
  168.   local front=math.floor(y-radius)<gy
  169.   local back=math.floor(y+radius)>gy
  170.  
  171.   local pushed=false
  172.  
  173.   if right and map[gy]:sub(gx+1,gx+1)~=" " then
  174.     --push left
  175.     pushed=true
  176.     x=gx+1-radius
  177.   elseif left  and map[gy]:sub(gx-1,gx-1)~=" " then
  178.     --push right
  179.     pushed=true
  180.     x=gx+radius
  181.   end
  182.  
  183.   if front and map[gy-1]:sub(gx,gx)~=" " then
  184.     --push back
  185.     pushed=true
  186.     y=gy+radius
  187.   elseif back and map[gy+1]:sub(gx,gx)~=" " then
  188.     --push forward
  189.     pushed=true
  190.     y=gy+1-radius
  191.   end
  192.  
  193.   --if I wasn't pushed out on any side, I might be hitting a corner
  194.   if not pushed then
  195.     --square rad
  196.     local r2=radius^2
  197.     local pushx,pushy=0,0
  198.     if left then
  199.       if front and map[gy-1]:sub(gx-1,gx-1)~=" " then
  200.         --check front-left
  201.         local dist2=(gx-x)^2+(gy-y)^2
  202.         if dist2<r2 then
  203.           local pushd=(r2-dist2)/2^.5
  204.           pushx,pushy=pushd,pushd
  205.         end
  206.       elseif back and map[gy+1]:sub(gx-1,gx-1)~=" " then
  207.         local dist2=(gx-x)^2+(gy+1-y)^2
  208.         if dist2<r2 then
  209.           local pushd=(r2-dist2)/2^.5
  210.           pushx,pushy=pushd,-pushd
  211.         end
  212.       end
  213.     elseif right then
  214.       if front and map[gy-1]:sub(gx+1,gx+1)~=" " then
  215.         --check front-left
  216.         local dist2=(gx+1-x)^2+(gy-y)^2
  217.         if dist2<r2 then
  218.           local pushd=(r2-dist2)/2^.5
  219.           pushx,pushy=-pushd,pushd
  220.         end
  221.       elseif back and map[gy+1]:sub(gx+1,gx+1)~=" " then
  222.         local dist2=(gx+1-x)^2+(gy+1-y)^2
  223.         if dist2<r2 then
  224.           local pushd=(r2-dist2)/2^.5
  225.           pushx,pushy=-pushd,-pushd
  226.         end
  227.       end
  228.     end
  229.     x=x+pushx
  230.     y=y+pushy
  231.   end
  232.  
  233.   return x,y
  234. end
  235.  
  236.  
  237.  
  238. print([[
  239. Basic wolfenstein 3d-style rendering engine proof-of-concept
  240. controls:
  241. asdw - move
  242. left/right - turn left/right
  243. q - quit
  244.  
  245. Press any key to begin...]])
  246.  
  247. os.pullEvent("key")
  248.  
  249. frametime = 0.01
  250. frametimer = os.startTimer(frametime)
  251.  
  252. local pmousex, pmousey
  253. sensitivity = 2
  254.  
  255. while true do
  256.   px,py=clampCollision(px,py,.25)
  257.   local e={os.pullEvent()}
  258.   if e[1]=="key" then
  259.     if e[2]==keys.left then
  260.       turn(-turnSpeed)
  261.     elseif e[2]==keys.right then
  262.       turn(turnSpeed)
  263.     elseif e[2]==keys.up or e[2]==keys.w then
  264.       px=px+fx*speed
  265.       py=py+fy*speed
  266.     elseif e[2]==keys.down or e[2]==keys.s then
  267.       px=px-fx*speed
  268.       py=py-fy*speed
  269.     elseif e[2]==keys.a then
  270.       px=px+fy*speed
  271.       py=py-fx*speed
  272.     elseif e[2]==keys.d then
  273.       px=px-fy*speed
  274.       py=py+fx*speed
  275.     elseif e[2]==keys.q then
  276.       break
  277.     end
  278.   elseif e[1]=="mouse_drag" then
  279.     if pmousex and math.abs(pmousex - e[3]) < (w / 6) then
  280.       turn((pmousex - e[3]) * sensitivity)
  281.     end
  282.         pmousex = e[3]
  283.         pmousey = e[4]
  284.   elseif e[1]=="timer" then
  285.     if e[2]==frametimer then
  286.       redraw()
  287.       frametimer = os.startTimer(frametime)
  288.     end
  289.   end
  290. end
  291.  
  292.  
  293. term.setBackgroundColor(colors.black)
  294. os.pullEvent()
  295. term.scroll(1)
  296. term.setCursorPos(1,19)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top