我正在编程一个光线投射引擎。
射线的起始位置由站在2D网格内的玩家的位置给出。
当把光线投射到一个方向上时,我必须确定光线相交的网格。
(以下是对该概念的深入描述:http://www.permadi.com/tutorial/raycast/rayc7.html)
有一个小的不准确性,这会引起一些麻烦。我认为这个问题是由网格步长的错误计算引起的。
然而,我缺乏解决这个问题的数学理解。
问题描述:
当光线向左移动时,栅格交点步长与向右移动时的步长略有不同。
(为什么我会关心这个?:当垂直和水平交叉点彼此靠近时,特别是在角落里,这会导致一些水平网格交叉点比垂直网格交叉点离玩家更远的问题。由于我对垂直交叉点使用不同的纹理,水平墙的外观会被破坏,因为在墙的小部分,即使是水平墙。)
这个问题是由我的算法中的缺陷引起的吗?这就是我计算第一个水平网格交点和网格步长的方法:
查找第一个网格交点:
if (current_angle > 180) {
first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width + Field::width;
} else {
first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width - 1;
}
first_grid_horizontal_x = p.pos_x + (p.pos_y - first_grid_horizontal_y) / tan( 180 - current_angle);
计算步长:
if (current_angle > 180) {
grid_stepsize_horizontal_y = Field::width;
grid_stepsize_horizontal_x = Field::width / tan(current_angle - 180);
} else {
grid_stepsize_horizontal_y = -Field::width;
grid_stepsize_horizontal_x = Field::width / tan(180 - current_angle);
}
正如你所看到的,我总是使用"180-当前角度"来确定x值的方向。这会导致不准确吗?我必须更多地区分角度吗?
三角函数使用弧度,而不是度数。所以
tan(180 - current_angle)
应该看起来像
tan(Math.Pi - current_angle)
注意,它等于
- tan(current_angle)
如果你的当前角度以度为单位,那么:
current_angle_radians = current_angle_degrees * Math.Pi / 180
我认为你的不准确性来自向上移动时的子动作1。
这背后的想法可能是你想得到块的最后一个像素的索引,但这是不必要的:你在这里做浮点运算,下一个水平交点的y
值应该代表网格单元之间的线。若向下,它表示单元格的最高坐标;如果你往上走,它代表最下面的坐标。
(除此之外:(int) y / w
将向零取整,因此仅适用于非负数。您可以考虑使用floor(x / w)
。)