commit 36f0188f0f02a52d0c239a613f97be6decfb8577
Author: Matthew Ryan Dillon <matthew@akdillon.net>
Date:   Sat Dec 28 21:59:15 2024 -0500

    initial

diff --git a/main.lua b/main.lua
new file mode 100644
index 0000000..4dee6ac
--- /dev/null
+++ b/main.lua
@@ -0,0 +1,246 @@
+function love.load()
+  p2 = math.pi / 2
+  p3 = 3 * math.pi / 2
+
+  fov = 30
+
+  love.graphics.setBackgroundColor(0.3, 0.3, 0.3, 1)
+  love.window.setMode(1024, 512)
+
+  player = {}
+  player["x"] = 300
+  player["y"] = 300
+  player["size"] = 8
+  player["angle"] = 0
+  player["dx"] = math.cos(player.angle) * 5
+  player["dy"] = math.sin(player.angle) * 5
+
+  map = {}
+  map["x"] = 8
+  map["y"] = 8
+  map["size"] = 64
+
+  map["map"] = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+    1, 0, 1, 0, 0, 0, 0, 1,
+    1, 0, 1, 0, 0, 0, 0, 1,
+    1, 0, 1, 0, 0, 0, 0, 1,
+    1, 0, 0, 0, 0, 0, 0, 1,
+    1, 0, 0, 0, 0, 1, 0, 1,
+    1, 0, 0, 0, 0, 0, 0, 1,
+    1, 1, 1, 1, 1, 1, 1, 1,
+  }
+end
+
+function love.update()
+  if love.keyboard.isDown("a") then
+    player.angle = player.angle - 0.1
+    if player.angle < 0 then player.angle = player.angle + 2 * math.pi end
+    player.dx = math.cos(player.angle) * 5
+    player.dy = math.sin(player.angle) * 5
+  end
+  if love.keyboard.isDown("d") then
+    player.angle = player.angle + 0.1
+    if player.angle > 2 * math.pi then player.angle = player.angle - 2 * math.pi end
+    player.dx = math.cos(player.angle) * 5
+    player.dy = math.sin(player.angle) * 5
+  end
+  if love.keyboard.isDown("w") then
+    player.x = player.x + player.dx
+    player.y = player.y + player.dy
+  end
+  if love.keyboard.isDown("s") then
+    player.x = player.x - player.dx
+    player.y = player.y - player.dy
+  end
+end
+
+function love.draw()
+  drawMap()
+  drawPlayer()
+  drawRays3D()
+end
+
+function drawPlayer()
+  love.graphics.setColor(1, 1, 0)
+  love.graphics.rectangle("fill",
+    player.x - player.size / 2, player.y - player.size / 2,
+    player.size, player.size
+  )
+  love.graphics.line(player.x, player.y, player.x + player.dx * 5, player.y + player.dy * 5)
+end
+
+function drawMap()
+  for y = 1, map.y do
+    for x = 1, map.x do
+      local color = map.map[(y - 1) * map.x + x]
+      love.graphics.setColor(color, color, color)
+      local xo = (x - 1) * map.size
+      local yo = (y - 1) * map.size
+      love.graphics.polygon("fill",
+        xo            + 1, yo            + 1,
+        xo            + 1, yo + map.size - 1,
+        xo + map.size - 1, yo + map.size - 1,
+        xo + map.size - 1, yo            + 1
+      )
+    end
+  end
+end
+
+function dist(ax, ay, bx, by, ang)
+  return math.sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay))
+end
+
+function drawRays3D()
+  local ray = {}
+  ray["angle"] = player.angle - math.rad(fov)
+  ray["x"] = 0
+  ray["y"] = 0
+  ray["xo"] = 0
+  ray["yo"] = 0
+  ray["mx"] = 0
+  ray["my"] = 0
+  ray["mp"] = 0
+
+  if ray.angle < 0 then
+    ray.angle = ray.angle + 2 * math.pi
+  end
+  if ray.angle > 2 * math.pi then
+    ray.angle = ray.angle - 2 * math.pi
+  end
+
+  for r = 1, fov * 2 do
+    local dof = 0
+    local disT = 0
+    local disH = 1000000
+    local hx = player.x
+    local hy = player.y
+
+    local aTan = -1 / math.tan(ray.angle)
+
+    if (ray.angle > math.pi) then
+      ray.y = bit.lshift(bit.rshift(player.y, 6), 6) - 0.0001
+      ray.x = (player.y - ray.y) * aTan + player.x
+      ray.yo = -map.size
+      ray.xo = -ray.yo * aTan
+    end
+
+    if (ray.angle < math.pi) then
+      ray.y = bit.lshift(bit.rshift(player.y, 6), 6) + map.size
+      ray.x = (player.y - ray.y) * aTan + player.x
+      ray.yo = map.size
+      ray.xo = -ray.yo * aTan
+    end
+
+    if ray.angle == 0 or ray.angle == math.pi then
+      ray.x = player.x
+      ray.y = player.y
+      dof = 8
+    end
+
+    while dof < 8 do
+      ray.mx = bit.rshift(ray.x, 6)
+      ray.my = bit.rshift(ray.y, 6)
+      ray.mp = ray.my * map.x + ray.mx
+      if ray.mp > 0 and ray.mp < (map.x * map.y + 1) and map.map[ray.mp + 1] == 1 then
+        hx = ray.x
+        hy = ray.y
+        disH = dist(player.x, player.y, hx, hy, ray.angle)
+        dof = 8
+      else
+        ray.x = ray.x + ray.xo
+        ray.y = ray.y + ray.yo
+        dof = dof + 1
+      end
+    end
+
+    dof = 0
+    local disV = 1000000
+    local vx = player.x
+    local vy = player.y
+    local nTan = -math.tan(ray.angle)
+
+    if (ray.angle > p2 and ray.angle < p3) then
+      ray.x = bit.lshift(bit.rshift(player.x, 6), 6) - 0.0001
+      ray.y = (player.x - ray.x) * nTan + player.y
+      ray.xo = -map.size
+      ray.yo = -ray.xo * nTan
+    end
+
+    if (ray.angle < p2 or ray.angle > p3) then
+      ray.x = bit.lshift(bit.rshift(player.x, 6), 6) + map.size
+      ray.y = (player.x - ray.x) * nTan + player.y
+      ray.xo = map.size
+      ray.yo = -ray.xo * nTan
+    end
+
+    if ray.angle == 0 or ray.angle == math.pi then
+      ray.x = player.x
+      ray.y = player.y
+      dof = 8
+    end
+
+    while dof < 8 do
+      ray.mx = bit.rshift(ray.x, 6)
+      ray.my = bit.rshift(ray.y, 6)
+      ray.mp = ray.my * map.x + ray.mx
+      if ray.mp > 0 and ray.mp < (map.x * map.y + 1) and map.map[ray.mp + 1] == 1 then
+        vx = ray.x
+        vy = ray.y
+        disV = dist(player.x, player.y, vx, vy, ray.angle)
+        dof = 8
+      else
+        ray.x = ray.x + ray.xo
+        ray.y = ray.y + ray.yo
+        dof = dof + 1
+      end
+    end
+
+    if disV < disH then
+      ray.x = vx
+      ray.y = vy
+      disT = disV
+      love.graphics.setColor(0.9, 0, 0)
+    end
+
+    if disH < disV then
+      ray.x = hx
+      ray.y = hy
+      disT = disH
+      love.graphics.setColor(0.7, 0, 0)
+    end
+
+    love.graphics.line(
+      player.x, player.y,
+      ray.x, ray.y
+    )
+
+    local ca = player.angle - ray.angle
+    if ca < 0 then
+      ca = ca + 2 * math.pi
+    end
+    if ca > 2 * math.pi then
+      ca = ca - 2 * math.pi
+    end
+    disT = disT * math.cos(ca)
+
+    local lineH = map.size * 320 / disT
+    if lineH > 320 then
+      lineH = 320
+    end
+    local lineO = 160 - lineH / 2
+    love.graphics.setLineWidth(8)
+    love.graphics.line(
+      r * 8 + 530, lineO,
+      r * 8 + 530, lineH + lineO
+    )
+
+    ray.angle = ray.angle + math.rad(1)
+    if ray.angle < 0 then
+      ray.angle = ray.angle + 2 * math.pi
+    end
+    if ray.angle > 2 * math.pi then
+      ray.angle = ray.angle - 2 * math.pi
+    end
+  end
+end