我正在尝试编写this文章中描述的光线投射算法。我使用坐标系,其中y向上增加,x增加到左边。以下代码片段中的变量名称取自文章,我将对其进行描述,以便代码更易于阅读:
rayDirX
和rayDirY
是向量的坐标,指向玩家在地图上投射光线的方向上的位置,alpha
是两者之间的角度这条光线和原点。
Px, Py
是玩家在地图上的位置的精确坐标
Ax, Ay
是第一个水平交叉点的精确坐标,后来是其他水平交叉点。
Bx, By
是第一个垂直交叉点的精确坐标,后来是其他垂直交叉点。
horXa, horYa, vertXa, vertYb
是步长增量,在找到第一个交点后不变。我怀疑算法的问题是这些值没有正确计算。
mapX, mapY
是地图上十字路口左下角的坐标。这用于检查数组map[][]
中此位置是否有墙。
交替检查水平和垂直交叉点。 Ax, Ay
或Bx, By
应保持交叉点的精确位置。
// Calculate the initial intersections
// Horizontal intersections
// If the ray is facing up
if (rayDirY > 0)
{
horYa = 1;
Ay = mapY+1;
}
// If the ray is facing down
else
{
horYa = -1;
Ay = mapY;
}
horXa = Math.abs(horYa)/tanAlpha;
Ax = Px + (Ay-Py)/tanAlpha;
// Vertical intersections
// If the ray is facing right
if (rayDirX > 0)
{
vertXa = 1;
Bx = mapX+1;
}
// If the ray is facing left
else
{
vertXa = -1;
Bx = mapX;
}
vertYa = Math.abs(vertXa)*tanAlpha;
By = Py + (Px-Bx)*tanAlpha;
//Loop to find where the ray hits a wall
//Number of texture to display
int texNum;
boolean horizontal = Math.abs(Ax * Math.cos(alpha)) < Math.abs(Bx*Math.cos(alpha));
//This loop runs for each ray with the setup above
while(true) {
// Check horizontal intersection
if (horizontal)
{
mapX = (int)Math.floor(Math.abs(Ax));
mapY = (int)Math.floor(Math.abs(Ay));
if(mapX > mapWidth-1) mapX = mapWidth-1;
if(mapY > mapHeight-1) mapY = mapHeight-1;
if(mapX < 0) mapX = 0;
if(mapY < 0) mapY = 0;
texNum = map[mapX][mapY];
if(texNum > 0) break;
Ax += horXa;
Ay += horYa;
horizontal = false;
}
else {
mapX = (int)Math.floor(Math.abs(Bx));
mapY = (int)Math.floor(Math.abs(By));
if(mapX > mapWidth-1) mapX = mapWidth-1;
if(mapY > mapHeight-1) mapY = mapHeight-1;
if(mapX < 0) mapX = 0;
if(mapY < 0) mapY = 0;
texNum = map[mapX][mapY];
if (texNum > 0) break;
Bx += vertXa;
By += vertYa;
horizontal = true;
}
}
使用此算法,图像无法正确渲染,请参见屏幕截图。我怀疑是因为horYa, Ay, vertXa, Bx
无法正确计算。更新:经过一些调试工作后,似乎有时我们选择计算水平交叉而不是垂直交叉,反之亦然......真的很奇怪!
您能否在算法中发现错误?感谢您的任何意见!