【问题标题】:Lua raycasting issuesLua 光线投射问题
【发布时间】:2018-03-30 23:24:36
【问题描述】:

我在为 Ti Nspire CX(使用 Lua)构建的光线投射引擎上日复一日地工作,但遇到了光线碰撞问题。

我已经摆弄了我认为有问题的区域,因为在屏幕上绘制光线没有问题:

我在这方面也做了很多调试,比如显示光线从玩家向外射出时的坐标。我说我相信碰撞部分有问题,因为当我打印每条射线的半径时,它们都达到了最大距离,我设置为40。这就是碰撞和单射线管理 em> 代码:

function ray()
    radius = 1
    for n = 1, 40, 1 do -- increase of testdot
        x_ray = x + (radius * math.cos(rayf * 3.141592653/180))
        y_ray = y - (radius * math.sin(rayf * 3.141592653/180))
        --print(math.floor(x_ray,3), math.floor(y_ray,3), rayf, radius)
        for i = 1, 4, 1 do --for k,v in pairs(map) do -- testing for collision of testdot and a wall
            --print("X  ",v[1],"<-->",math.floor(x_ray),"<-->",v[3])
            --print("Y  ",v[2],"<-->",math.floor(y_ray),"<-->",v[4])'

            ------------------------------------
            if (
                math.min(map[i][1],map[i][3]) <= x_ray and x_ray <= math.max(map[i][1],map[i][3])
            ) and (
                math.min(map[i][2],map[i][4]) <= y_ray and y_ray <= math.max(map[i][2],map[i][4])
            ) then
                print("Collision")
                --return true
            end
            ------------------------------------
        end
        radius = n
    end
end

我知道第二个 for 循环可以被压缩,但我在调试过程中这样做是为了找出它不能正常工作的原因。

------------------------------------ 周围的区域是光线不照射的区域碰撞/超出/错过...我不知道为什么这不起作用,有人有什么建议吗?

仅供参考,此碰撞基于我遇到的here 问题的python 程序,当然,在碰撞部分。

变量的值:

x, y 是玩家的位置(光线投射时它会保持静态)

radius是单条射线的当前半径,只要没有检测到碰撞就会继续增加

rayf 是射线的当前度数(与玩家无关)。在程序开始时计算玩家的度数(此处未显示,但称为“面对”),加上 30,然后顺时针旋转直到满足 60 度的 FOV。

X-ray, y_ray 是单条射线的当前点,会继续向指定的rayf值递增,并且会递增1,使半径等于最后一个for循环中的n。 (必须注意,典型单位圆中的度数是相同的,并且不会镜像以匹配此镜像的 y 轴;即向上 90 度,向下 180 度。)

【问题讨论】:

  • 不清楚你在问什么。目前尚不清楚该程序应该做什么。 x、y 和 rayf 是升值吗?你有什么问题?
  • 好的,我更新了问题
  • 我遇到的问题是,由于某种原因,光线穿过墙壁,因为它们总是返回 40 的值。我的墙壁基本上是正方形,我的播放器在中间45 度。

标签: lua collision-detection raycasting ti-nspire


【解决方案1】:

这不是代码审查网站,但我将尝试先以更易于理解的方式编写代码,然后将 cmets 中的错误猜测到代码中。

function ray(x,y,rayf,map)
  %Are you sure that your global variables x,y,rayf are not overwritten?
  %I believe these are correct if 0 degrees is "right", "90" - top and "180" - left
  %is it so?
  local x_proj = math.cos(rayf* 3.141592653/180);
  local y_proj = -math.sin(rayf* 3.141592653/180);
  for radius=1,40 do
    local x_ray = x + radius * x_proj
    local y_ray = y + radius * y_proj
    for i=1,4 do
      %I take it the map[i] is a particular rectangle located at a particular side of the room (so map[1] is located at the left edge of the screen, for example)
      %is it so?
      local wall_left_edge = math.min ( map[i][1],map[i][3] )
      local wall_right_edge = math.max ( map[i][1],map[i][3] )
      %if I understood correctly, the smaller y is above bigger y
      local wall_top_edge = math.min ( map[i][2], map[i][4] ) 
      local wall_bottom_edge = math.max ( map[i][2], map[i][4] )
      %it is beyond me why couldnt you just sort the wall coordinates beforehand 
      %(say, top - 1 , bottom - 2 left - 3, right - 4)
      if (wall_left_edge < x) and (x < wall_right_edge)
      and (wall_top_edge < y) and (y < wall_bottom_edge) then
        %this does not detect collision, 
        %it detects whether beam steps into the rectangle "map[i]"
        print("Collision")
      end
    end
  end
end

因此,考虑到最后一条评论,您定义的墙必须足够宽和厚,以保证梁可以跨入一个:(wall_right_edge - wall_left_edge ) &gt; 1(1 是半径环的步长)和(wall_bottom_edge - wall_top_edge ) &gt; 1 .在拐角处,墙必须要么重叠,要么共享长度至少为 1 的边界。

【讨论】:

  • 我已经解决了this的问题,不过谢谢你的帮助。
【解决方案2】:

光线总是超过 40 的原因是因为 for 循环没有被取消,这是包含 return 以跳出函数并继续代码的重要原因(我认为包含退货,但它无法正常运行,正如您在以下内容中看到的那样:

--return true

在此之后,光线投射工作正常,但不是数学。由于某种未知原因,新的光线坐标也使光线射出超过 40。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多