Advertisement
Guest User

Untitled

a guest
Feb 28th, 2013
483
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.55 KB | None | 0 0
  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)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement