首页 > 解决方案 > Lua - 如何补偿奇怪的 2D raycaster 引擎翘曲效果(不是鱼眼效果)

问题描述

基本上我在lua中写了一些代码:

function love.keypressed( key )
   if key == "f11" then
     fullscreen = not fullscreen
   end
end
pPosX,pPosY = 1,8
pRot,pFOV,pViewRange = -90,95,15
lines = {{0,0,10,0},{10,0,10,10},{0,10,3,10},{7,10,10,10},{3,10,5,8},{5,8,7,10},{0,10,0,0},{2,2,2,8},{8,2,6,4},{2,5,4,5},{6,4,8,4}}

function love.conf(t)
    t.console = true
end

function love.load()
    fullscreen = true
    love.window.setTitle("Raycaster")
    love.window.setMode(1280,720,{})
    love.window.setFullscreen(true, "desktop")
    ScreenX,ScreenY = love.graphics.getDimensions()
end

function love.update(dt)
  love.window.setFullscreen(fullscreen, "desktop")
  if love.keyboard.isDown("w") then
    pPosX,pPosY = math.cos(math.rad(pRot))*dt*3+pPosX,math.sin(math.rad(pRot))*dt*3+pPosY
  end
  if love.keyboard.isDown("s") then
    pPosX,pPosY = math.cos(math.rad(pRot))*dt*-3+pPosX,math.sin(math.rad(pRot))*dt*-3+pPosY
  end
  if love.keyboard.isDown("left") then
    pRot = pRot - dt*250
  end
  if love.keyboard.isDown("right") then
    pRot = pRot + dt*250
  end
  if love.keyboard.isDown("a") then
    pPosX,pPosY = math.cos(math.rad(pRot-90))*dt*3+pPosX,math.sin(math.rad(pRot-90))*dt*3+pPosY
  end
  if love.keyboard.isDown("d") then
    pPosX,pPosY = math.cos(math.rad(pRot+90))*dt*3+pPosX,math.sin(math.rad(pRot+90))*dt*3+pPosY
  end
  fps = 1/dt
end
function love.draw()
    love.graphics.setColor(0.5, 0.55, 1)
    love.graphics.rectangle("fill",0,0,ScreenX,ScreenY/2)
    love.graphics.setColor(0.35, 0.3, 0.3)
    love.graphics.rectangle("fill",0,ScreenY/2,ScreenX,ScreenY/2)
    ScreenX,ScreenY = love.graphics.getDimensions()
    for i = 1,ScreenX,1 do
       local scanX = pRot+(i-1)*pFOV/ScreenX-pFOV/2
       local lx1,ly1 = math.cos(math.rad(scanX))*pViewRange+pPosX,math.sin(math.rad(scanX))*pViewRange+pPosY
       local closest = 999999
       for lns = 1,#lines,1 do
          local x1,y1,x2,y2,x3,y3,x4,y4 = pPosX,pPosY,lx1,ly1,lines[lns][1],lines[lns][2],lines[lns][3],lines[lns][4]
          t,u = ((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)),
          ((x1-x3)*(y1-y2)-(y1-y3)*(x1-x2))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4))
          if t >= 0 and t <= 1 and u >= 0 and u <= 1 then
            x,y = x1+t*(x2-x1),y1+t*(y2-y1)
            Dist = math.sqrt((x - pPosX) ^ 2 + (y - pPosY) ^ 2)*math.cos(math.rad(pRot)-math.rad(scanX))
          else
            Dist = 999999
          end
          if Dist < closest then
            closest = Dist
            mmX,mmY = x,y
          end
       end
      love.graphics.setColor(1.2-closest/pViewRange, 1.2-closest/pViewRange, 0)
      love.graphics.line(pPosX*ScreenX/50,pPosY*ScreenX/50,mmX*ScreenX/50,mmY*ScreenX/50)
      if closest <= pViewRange then
        love.graphics.setColor(1.2-closest/pViewRange, 1.2-closest/pViewRange, 1.2-closest/pViewRange)
        love.graphics.rectangle("fill",i,(ScreenY-(ScreenY*(pViewRange-closest)/pViewRange))/2,1,ScreenY*(pViewRange-closest)/pViewRange)
      end
    end
    love.graphics.setColor(1,0,0)
    for lns = 1,#lines,1 do
      love.graphics.line(lines[lns][1]*ScreenX/50,lines[lns][2]*ScreenX/50,lines[lns][3]*ScreenX/50,lines[lns][4]*ScreenX/50)
    end
    love.graphics.setColor(1,1,1)
    love.graphics.print(math.floor(fps+0.5),0.975*ScreenX,0)
end

pPosX,PposY 是玩家坐标 pRot,pFov,pViewRange 是以度为单位的玩家旋转,以度为单位的视野和视野范围,lines = {} 包含分为线 {x1,y1,x2,y2 的地图},引擎检查屏幕的分辨率并启动一个 for i 循环,该循环在 -pFov/2 处启动 scanX 变量并将其增加 pFov/ScreenX 直到达到 pFov/2,线段相交方程是从 wikipedia 复制的,我已经通过将 Dist(从玩家到交叉点的距离)乘以玩家角度的余弦减去 scanX 来补偿鱼眼效应,但仍然存在非常强烈的翘曲效果: https ://i.stack.imgur.com/ ztUN0.png 正如你在小地图中看到的那样,玩家正在向下看一条笔直的走廊,但看起来前面好像在弯曲。

标签: lualove2d

解决方案


推荐阅读