local playerx = 10 local playery = 10 local angle = 1 local playerspeed = 0 local playerswspeed = 0 local playermaxspeed = 100 local sin = {0, 0.707, 1, 0.707, 0, -0.707, -1, -0.707} local cos = {1, 0.707, 0, -0.707, -1, -0.707, 0, 0.707} function love.update(dt) playerx = playerx + sin[angle] * playerspeed * dt playerx = playerx + cos[angle] * playerswspeed * dt playery = playery + cos[angle] * playerspeed * dt playery = playery - sin[angle] * playerswspeed * dt end function love.keypressed(key) if key == 'w' then playerspeed = playerspeed + playermaxspeed elseif key == 's' then playerspeed = playerspeed - playermaxspeed elseif key == 'a' then playerswspeed = playerswspeed + playermaxspeed elseif key == 'd' then playerswspeed = playerswspeed - playermaxspeed elseif key == 'q' then angle = angle + 1 if angle > 8 then angle = 1 end elseif key == 'e' then angle = angle - 1 if angle < 1 then angle = 8 end elseif key == 'escape' then love.event.quit() end end function love.keyreleased(key) if key == 'w' then playerspeed = playerspeed - playermaxspeed elseif key == 's' then playerspeed = playerspeed + playermaxspeed elseif key == 'a' then playerswspeed = playerswspeed - playermaxspeed elseif key == 'd' then playerswspeed = playerswspeed + playermaxspeed end end function transform(wx, wy) -- Player-relative space (translation) local tx = wx - playerx local ty = wy - playery -- Player-relative space (rotation) local rx = cos[angle] * tx - sin[angle] * ty local ry = cos[angle] * ty + sin[angle] * tx -- -1.0 to +1.0 abstract screen space (perspective) -- Player-relative x maps to *-x* -- Player-relative y maps to *z* local px = -rx / ry -- Screen space (scaling and translation) local hwidth = love.graphics.getWidth() / 2 local x = px * hwidth + hwidth local z = ry return x, z end function drawWall(wx1, wy1, wx2, wy2) local hwidth = love.graphics.getWidth() / 2 local hheight = love.graphics.getHeight() / 2 local x1, z1 = transform(wx1, wy1) local x2, z2 = transform(wx2, wy2) if z1 < 0 and z2 < 0 then -- Fully outside of viewport, don't bother return end if z1 < 0 or z2 < 0 then local clippingx = playerx + 0.001*sin[angle] local clippingy = playery + 0.001*cos[angle] local x = nil local y = nil if angle == 1 or angle == 5 then y = clippingy if wx1 == wx2 then x = wx1 elseif (wx1 < wx2) == (wy1 < wy2) then x = wx1 - wy1 + y else x = wx1 + wy1 - y end elseif angle == 3 or angle == 7 then x = clippingx if wy1 == wy2 then y = wy1 elseif (wx1 < wx2) == (wy1 < wy2) then y = wy1 - wx1 + x else y = wy1 + wx1 - x end elseif angle == 2 or angle == 6 then if wy1 == wy2 then x = clippingx + clippingy - wy1 y = wy1 elseif wx1 == wx2 then x = wx1 y = clippingx + clippingy - wx1 else x = (wx1 + clippingx + clippingy - wy1) / 2 y = (wy1 + clippingy + clippingx - wx1) / 2 end elseif angle == 4 or angle == 8 then if wy1 == wy2 then x = clippingx - clippingy + wy1 y = wy1 elseif wx1 == wx2 then x = wx1 y = clippingy - clippingx + wx1 else x = (wx1 + clippingx - clippingy + wy1) / 2 y = (wy1 + clippingy - clippingx + wx1) / 2 end end if z1 < 0 then x1, z1 = transform(x, y) else x2, z2 = transform(x, y) end end local wall1 = hwidth * 60 / z1 local wall2 = hwidth * 60 / z2 love.graphics.setColor(1, 1, 1) love.graphics.line(x1, hheight - wall1, x2, hheight - wall2) love.graphics.line(x1, hheight + wall1, x2, hheight + wall2) love.graphics.line(x1, hheight - wall1, x1, hheight + wall1) love.graphics.line(x2, hheight - wall2, x2, hheight + wall2) end function love.draw() local hwidth = love.graphics.getWidth() / 2 local hheight = love.graphics.getHeight() / 2 drawWall(-300, -200, -100, 0) drawWall(-100, 0, -300, 200) drawWall(-150, 200, 300, 200) drawWall(300, 200, 300, -200) drawWall(300, -200, -300, -200) love.graphics.setColor(1, 1, 1) anglecw = angle - 1 if anglecw < 1 then anglecw = 8 end anglecc = angle + 1 if anglecc > 8 then anglecc = 1 end love.graphics.line(hwidth, hheight, hwidth + sin[anglecw] * 5, hheight + cos[anglecw] * 5) love.graphics.line(hwidth, hheight, hwidth + sin[anglecc] * 5, hheight + cos[anglecc] * 5) end