Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local buffer=term
- local loadedAPI=false
- local function cwrite(msg)
- msg = tostring(msg)
- local x, y = term.getCursorPos()
- term.setCursorPos((51-#msg)/2, y)
- write(msg)
- end
- local function cprint(msg)
- cwrite(msg.."\n")
- end
- local stime = os.clock()
- if redirect then
- buffer=redirect.createRedirectBuffer()
- print("redirect API found, using buffer")
- else
- if not fs.exists("redirect") then -- Edit
- shell.run("pastebin", "get", "fU9Kj9zr", "redirect")
- end
- local pe=printError
- rawset(_G,"printError",error)
- local ok, err=pcall(os.loadAPI,"redirect")
- if not ok then
- print("trying "..shell.dir().."/redirect")
- ok,err=pcall(os.loadAPI,shell.dir().."/redirect")
- end
- if ok then
- print("Loaded redirect API, using buffer")
- buffer=redirect.createRedirectBuffer()
- loadedAPI=true
- else
- print("redirect API not found or could not be loaded, drawing directly; this may cause flickering.")
- end
- rawset(_G,"printError",pe)
- end
- local colorSchemes = {
- {0,8}, --white+gray
- {3,11}, --blue
- {6,14}, --red
- {5,13}, --green
- {4,1}, --yellow/orange
- }
- local function cast(cx,cy,angle)
- --direction vector
- local vx,vy=math.cos(angle), math.sin(angle)
- local slope=vy/vx
- --next distance, x and y axis points
- local ndx, ndy
- --steps, distance and block
- local dsx, dsy, bsx, bsy
- if vx<0 then
- local x=(cx%1)
- bsx=-1
- ndx=math.sqrt(x*x*(1+slope*slope))
- dsx=math.sqrt((1+slope*slope))
- else
- local x=1-(cx%1)
- bsx=1
- ndx=math.sqrt(x*x*(1+slope*slope))
- dsx=math.sqrt((1+slope*slope))
- end
- if vy<0 then
- local y=(cy%1)
- bsy=-1
- ndy=math.sqrt(y*y*(1+1/(slope*slope)))
- dsy=math.sqrt((1+1/(slope*slope)))
- else
- local y=1-(cy%1)
- bsy=1
- ndy=math.sqrt(y*y*(1+1/(slope*slope)))
- dsy=math.sqrt((1+1/(slope*slope)))
- end
- local x,y=math.floor(cx),math.floor(cy)
- while x>0 and x<=mapW and y>0 and y<=mapH do
- local hitD
- local isX
- if ndx<ndy then
- --x crossing is next
- x=x+bsx
- isX=true
- hitD=ndx
- ndx=ndx+dsx
- else
- y=y+bsy
- isX=false
- hitD=ndy
- ndy=ndy+dsy
- end
- local wall=map[y]:sub(x,x)
- if wall~=" " then
- return colorSchemes[tonumber(wall)][isX and 1 or 2], hitD
- end
- end
- end
- local w,h=term.getSize()
- local centerX, centerY=math.floor((w+1)/2), math.floor((h+1)/2)
- local px, py=2.5,2.5
- local dir=0
- local fx,fy
- local speed=.1
- local turnSpeed=4
- local function turn(amt)
- dir=dir+amt
- fx,fy=math.cos(math.rad(dir)), math.sin(math.rad(dir))
- end
- turn(0)
- --build table of angles and base distances per scanline
- local screenDist=.55*w
- local scan={}
- for x=1,w do
- local t={}
- scan[x]=t
- t.angle=math.atan2(x-centerX,screenDist)
- t.dist=((x-centerX)^2+screenDist^2)^.5/screenDist
- end
- local function redraw()
- if buffer.isBuffer then
- term.redirect(buffer)
- end
- for x=1,w do
- local wall,dist=cast(px,py,math.rad(dir)+scan[x].angle)
- if wall then
- --calc wall height based on distance
- local height=scan[x].dist/dist
- height=math.floor(math.min(height*centerY,(h+1)/2))
- term.setBackgroundColor(colors.gray)
- for y=1,(h+1)/2-height-1 do
- term.setCursorPos(x,y)
- term.write(" ")
- end
- for y=centerY+height+1,h do
- term.setCursorPos(x,y)
- term.write(" ")
- end
- term.setBackgroundColor(2^wall)
- for y=centerY-height,centerY+height do
- term.setCursorPos(x,y)
- term.write(" ")
- end
- end
- end
- if buffer.isBuffer then
- term.restore()
- buffer.blit()
- end
- end
- local function clampCollision(x,y,radius)
- --am I *in* a block?
- local gx,gy=math.floor(x),math.floor(y)
- if map[gy]:sub(gx,gx)~=" " then
- --I am. Complete fail, do nothing.
- return x,y
- end
- --ok, check the neighbors.
- local right=math.floor(x+radius)>gx
- local left=math.floor(x-radius)<gx
- local front=math.floor(y-radius)<gy
- local back=math.floor(y+radius)>gy
- local pushed=false
- if right and map[gy]:sub(gx+1,gx+1)~=" " then
- --push left
- pushed=true
- x=gx+1-radius
- elseif left and map[gy]:sub(gx-1,gx-1)~=" " then
- --push right
- pushed=true
- x=gx+radius
- end
- if front and map[gy-1]:sub(gx,gx)~=" " then
- --push back
- pushed=true
- y=gy+radius
- elseif back and map[gy+1]:sub(gx,gx)~=" " then
- --push forward
- pushed=true
- y=gy+1-radius
- end
- --if I wasn't pushed out on any side, I might be hitting a corner
- if not pushed then
- --square rad
- local r2=radius^2
- local pushx,pushy=0,0
- if left then
- if front and map[gy-1]:sub(gx-1,gx-1)~=" " then
- --check front-left
- local dist2=(gx-x)^2+(gy-y)^2
- if dist2<r2 then
- local pushd=(r2-dist2)/2^.5
- pushx,pushy=pushd,pushd
- end
- elseif back and map[gy+1]:sub(gx-1,gx-1)~=" " then
- local dist2=(gx-x)^2+(gy+1-y)^2
- if dist2<r2 then
- local pushd=(r2-dist2)/2^.5
- pushx,pushy=pushd,-pushd
- end
- end
- elseif right then
- if front and map[gy-1]:sub(gx+1,gx+1)~=" " then
- --check front-left
- local dist2=(gx+1-x)^2+(gy-y)^2
- if dist2<r2 then
- local pushd=(r2-dist2)/2^.5
- pushx,pushy=-pushd,pushd
- end
- elseif back and map[gy+1]:sub(gx+1,gx+1)~=" " then
- local dist2=(gx+1-x)^2+(gy+1-y)^2
- if dist2<r2 then
- local pushd=(r2-dist2)/2^.5
- pushx,pushy=-pushd,-pushd
- end
- end
- end
- x=x+pushx
- y=y+pushy
- end
- return x,y
- end
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- print([[
- Move: WASD
- Turn: Arrow Right/Left
- Go to start: R
- Quit: Q
- Go to blue block.
- If you will see white screen, turn around!
- Press any key to begin...]])
- os.pullEvent("key")
- local frameTimer=os.startTimer(0.5)
- local prevTick=0
- local dirty=true
- local win = false
- while true do
- px,py=clampCollision(px,py,.25)
- if dirty then
- redraw()
- dirty=false
- end
- local e={os.pullEvent()}
- if e[1]=="key" then
- if e[2]==keys.left then
- turn(-turnSpeed)
- dirty=true
- elseif e[2]==keys.right then
- turn(turnSpeed)
- dirty=true
- elseif e[2]==keys.up or e[2]==keys.w then
- px=px+fx*speed
- py=py+fy*speed
- dirty=true
- elseif e[2]==keys.down or e[2]==keys.s then
- px=px-fx*speed
- py=py-fy*speed
- dirty=true
- elseif e[2]==keys.a then
- px=px+fy*speed
- py=py-fx*speed
- dirty=true
- elseif e[2]==keys.d then
- px=px-fy*speed
- py=py+fx*speed
- dirty=true
- elseif e[2]==keys.q then
- break
- elseif e[2]==keys.r then
- px,py = 2.5,2.5
- dirty=true
- end
- if px >= mapW-1 and py >= mapH-1 then
- win = true
- break
- end
- end
- end
- if loadedAPI then
- os.unloadAPI("redirect")
- end
- -- JESUS PART
- -- The win/loose message
- term.setBackgroundColor(colors.white)
- term.setTextColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
- if win then
- local ntime = os.clock()
- write("\n")
- cprint("Congratulations!")
- cprint("You made it in")
- cprint(tostring(math.floor((ntime-stime)/60)).." minutes and "..tostring(math.ceil((ntime-stime)%60)).." seconds")
- cprint("Size of maze: "..(mapW-1)/2)
- else
- write("\n")
- cprint("Oh noes D:")
- end
- sleep(2)
- parallel.waitForAny(
- function() coroutine.yield(); os.pullEvent("key"); coroutine.yield() end,
- 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
- )
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- cprint(" Maze by Jesusthekiller. Thanks for playing!")
- cprint("3D engine by Gopher, He is A-W-E-S-O-M-E")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement