local map = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1},
{1,0,1,0,1,0,1,1,1,0,1,0,1,1,0,1},
{1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1},
{1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1},
{1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1},
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,1,1,1,0,1,1,0,1},
{1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1},
{1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1},
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1},
{1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1},
{1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1},
{1,0,1,0,1,1,1,0,1,1,1,0,1,1,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
}
local mapWidth, mapHeight = 16, 16
local player = {
angle = 0,
fov = math.pi / 3,
speed = 3,
rotSpeed = 0.003
}
local screenWidth, screenHeight = 800, 600
local halfHeight = screenHeight / 2
local rayCount = screenWidth / 2
function love.load()
love.window.setMode(screenWidth, screenHeight)
love.window.setTitle("Raycasting Maze")
love.mouse.setRelativeMode(true)
end
function love.update(dt)
local moveX, moveY = 0, 0
if love.keyboard.isDown("w") then
moveX = moveX + math.cos(player.angle) * player.speed * dt
moveY = moveY + math.sin(player.angle) * player.speed * dt
end
if love.keyboard.isDown("s") then
moveX = moveX - math.cos(player.angle) * player.speed * dt
moveY = moveY - math.sin(player.angle) * player.speed * dt
end
if love.keyboard.isDown("a") then
moveX = moveX + math.sin(player.angle) * player.speed * dt
moveY = moveY - math.cos(player.angle) * player.speed * dt
end
if love.keyboard.isDown("d") then
moveX = moveX - math.sin(player.angle) * player.speed * dt
moveY = moveY + math.cos(player.angle) * player.speed * dt
end
local newX, newY = player.x + moveX, player.y + moveY
if map[math.floor(player.y) + 1][math.floor(newX) + 1] == 0 then
player.x = newX
end
if map[math.floor(newY) + 1][math.floor(player.x) + 1] == 0 then
player.y = newY
end
end
function love.mousemoved(_, _, dx)
player.angle = player.angle + dx * player.rotSpeed
if player.angle < 0 then
player.angle = player.angle + 2 * math.pi
elseif player.angle > 2 * math.pi then
player.angle = player.angle - 2 * math.pi
end
end
function love.draw()
love.graphics.setColor(0.2, 0.2, 0.8)
love.graphics.rectangle("fill", 0, 0, screenWidth, halfHeight)
love.graphics.setColor(0.3, 0.3, 0.3)
love.graphics.rectangle("fill", 0, halfHeight, screenWidth, halfHeight)
local columnWidth = screenWidth / rayCount
for col = 0, rayCount - 1 do
local rayAngle = player.angle - player.fov / 2 + (col / rayCount) * player.fov
local rayX, rayY = player.x, player.y
local rayDirX, rayDirY = math.cos(rayAngle), math.sin(rayAngle)
local mapX, mapY = math.floor(rayX), math.floor(rayY)
local deltaDistX = math.abs(1 / rayDirX)
local deltaDistY = math.abs(1 / rayDirY)
local sideDistX, sideDistY
local stepX, stepY
local hit, side = false, 0
if rayDirX < 0 then
stepX = -1
sideDistX = (rayX - mapX) * deltaDistX
else
stepX = 1
sideDistX = (mapX + 1 - rayX) * deltaDistX
end
if rayDirY < 0 then
stepY = -1
sideDistY = (rayY - mapY) * deltaDistY
else
stepY = 1
sideDistY = (mapY + 1 - rayY) * deltaDistY
end
while not hit do
if sideDistX < sideDistY then
sideDistX = sideDistX + deltaDistX
mapX = mapX + stepX
side = 0
else
sideDistY = sideDistY + deltaDistY
mapY = mapY + stepY
side = 1
end
if mapX < 0 or mapX >= mapWidth or mapY < 0 or mapY >= mapHeight then
hit = true
elseif map[mapY + 1][mapX + 1] == 1 then
hit = true
end
end
local perpDist = (side == 0)
and (mapX - player.x + (1 - stepX) / 2) / rayDirX
or (mapY - player.y + (1 - stepY) / 2) / rayDirY
local lineHeight = screenHeight / perpDist
local drawStart = math.max(0, -lineHeight / 2 + halfHeight)
local drawEnd = math.min(screenHeight, lineHeight / 2 + halfHeight)
if side == 0 then
love.graphics.setColor(0.8, 0.2, 0.2)
else
love.graphics.setColor(0.5, 0.15, 0.15)
end
love.graphics.rectangle("fill",
col * columnWidth,
drawStart,
columnWidth + 1,
drawEnd - drawStart
)
end
love.graphics.setColor(1, 1, 0)
love.graphics.setLineWidth(1)
love.graphics.line(screenWidth/2 - 5, halfHeight, screenWidth/2 + 5, halfHeight)
love.graphics.line(screenWidth/2, halfHeight - 5, screenWidth/2, halfHeight + 5)
end
function love.keypressed(key)
if key == "escape" then
love.event.quit()
end
end