Lua 光线投射问题
Lua raycasting issues
我日复一日地在为 Ti Nspire CX(使用 Lua)构建的光线投射引擎上工作,但我遇到了光线碰撞问题。
我已经摆弄了我认为有问题的区域,因为在屏幕上绘制光线没有问题:
我在这方面也做了很多调试,比如显示从播放器向外射出的光线所在的坐标。我说我认为碰撞部分有问题,因为我打印每条射线的半径时,它们都达到了最大距离,我设置为40。这是碰撞和单射线管理代码:
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 循环可以被压缩,但我在调试过程中这样做是为了找出为什么它不能正常工作。
------------------------------------周围的区域是光线照射的地方't collide/over-reach/miss...我不知道为什么这不起作用,有人有任何建议吗?
仅供参考,此碰撞基于 python 程序,我在 中遇到问题,当然,在碰撞部分。
变量值:
x, y 是玩家的位置(光线投射时这将保持静态)
radius为单条射线的当前半径,只要未检测到碰撞就会继续递增
rayf 是射线的当前度数(与玩家无关)。在程序开始时计算玩家的度数(此处未显示,但称为 'facing'),加上 30,然后顺时针旋转,直到满足 60 度的 FOV。
X-ray,y_ray是单条射线的当前点,会朝着指定的rayf值不断递增,并且会递增1的值,使半径等于n中的最后一个for循环。 (必须注意,典型单位圆中的度数是相同的,并且不会镜像以匹配此镜像的 y 轴;即 90 度向上,180 度向下。)
这不是代码审查网站,但我将尝试首先以更易于理解的方式编写代码,然后猜测代码注释中的错误。
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 ) > 1
(1 是半径循环的步长)和 (wall_bottom_edge - wall_top_edge ) > 1
。在拐角处,墙必须重叠,或者共享长度至少为 1 的边界。
光线总是超过 40 的原因是因为 for-loop 没有被取消,这是包含 return 的重要原因跳出函数并继续代码(我以为包含了 return,但它没有正常运行,正如您在:
中看到的
--return true
在此之后,光线投射工作正常,但不是数学。floor-ing新的光线坐标也使光线射出超过 40,原因不明。
我日复一日地在为 Ti Nspire CX(使用 Lua)构建的光线投射引擎上工作,但我遇到了光线碰撞问题。
我已经摆弄了我认为有问题的区域,因为在屏幕上绘制光线没有问题:
我在这方面也做了很多调试,比如显示从播放器向外射出的光线所在的坐标。我说我认为碰撞部分有问题,因为我打印每条射线的半径时,它们都达到了最大距离,我设置为40。这是碰撞和单射线管理代码:
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 循环可以被压缩,但我在调试过程中这样做是为了找出为什么它不能正常工作。
------------------------------------周围的区域是光线照射的地方't collide/over-reach/miss...我不知道为什么这不起作用,有人有任何建议吗?
仅供参考,此碰撞基于 python 程序,我在
变量值:
x, y 是玩家的位置(光线投射时这将保持静态)
radius为单条射线的当前半径,只要未检测到碰撞就会继续递增
rayf 是射线的当前度数(与玩家无关)。在程序开始时计算玩家的度数(此处未显示,但称为 'facing'),加上 30,然后顺时针旋转,直到满足 60 度的 FOV。
X-ray,y_ray是单条射线的当前点,会朝着指定的rayf值不断递增,并且会递增1的值,使半径等于n中的最后一个for循环。 (必须注意,典型单位圆中的度数是相同的,并且不会镜像以匹配此镜像的 y 轴;即 90 度向上,180 度向下。)
这不是代码审查网站,但我将尝试首先以更易于理解的方式编写代码,然后猜测代码注释中的错误。
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 ) > 1
(1 是半径循环的步长)和 (wall_bottom_edge - wall_top_edge ) > 1
。在拐角处,墙必须重叠,或者共享长度至少为 1 的边界。
光线总是超过 40 的原因是因为 for-loop 没有被取消,这是包含 return 的重要原因跳出函数并继续代码(我以为包含了 return,但它没有正常运行,正如您在:
中看到的--return true
在此之后,光线投射工作正常,但不是数学。floor-ing新的光线坐标也使光线射出超过 40,原因不明。