raycaster-demo/main.lua
2024-12-28 21:59:15 -05:00

246 lines
5.8 KiB
Lua

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