我正在用纯JavaScript创建一个光线投射引擎,我刚刚实现了用于优化的DDA算法。但是,渲染中存在一个问题,即每个长方体之间存在间隙:
DDA算法旨在自动跳到下一个点,在该点它将击中构成地图的一个方框。这是为每条光线实现以下功能的函数:
function getDistances() {
for (var i = 0; i < Game.rays.quantity; i++) {
// get current angle of the ray
var angle = Game.toRad((Game.player.angle - (Game.rays.fov / 2)) + ((Game.rays.fov / Game.rays.quantity) * i));
var rayX = Game.player.x;
var rayY = Game.player.y;
// pre-calculate sin, cos, and tan for angle
var sin = Math.sin(angle);
var cos = Math.cos(angle);
var tan = Math.tan(angle);
var hitWall = false;
for (var j = 0; j < Game.rays.renderDistance; j++) {
// get the closest X and Y coordinate for the ray
var stepX, stepY;
if (sin < 0) {
stepY = (Math.floor((rayY - 1) / Game.mapConfig.blockSize) * Game.mapConfig.blockSize) - rayY;
} else {
stepY = (Math.ceil((rayY + 1) / Game.mapConfig.blockSize) * Game.mapConfig.blockSize) - rayY;
}
if (cos < 0) {
stepX = (Math.floor((rayX - 1) / Game.mapConfig.blockSize) * Game.mapConfig.blockSize) - rayX
} else {
stepX = (Math.ceil((rayX + 1) / Game.mapConfig.blockSize) * Game.mapConfig.blockSize) - rayX;
}
// closest coordinate pairs where ray intersects a box (rounded to X and Y)
var nearX = [rayX + stepX, (stepX * tan) + rayY]; // blue
var nearY = [(stepY / tan) + rayX, rayY + stepY]; // purple
// take the X and Y coordinates and get the box it hit from Game.map.data
// this is where the issues are
var mapX, mapY;
if (Game.distanceTo([rayX, rayY], nearX) < Game.distanceTo([rayX, rayY], nearY)) {
// hits side of box
rayX = nearX[0];
rayY = nearX[1];
if (cos < 0) { // facing left
mapX = Math.floor(rayX / Game.mapConfig.blockSize) - 1;
mapY = Math.floor(rayY / Game.mapConfig.blockSize);
} else { // facing right
mapX = Math.floor(rayX / Game.mapConfig.blockSize);
mapY = Math.floor(rayY / Game.mapConfig.blockSize);
}
} else {
// hits top/bottom of box
rayX = nearY[0];
rayY = nearY[1];
if (sin < 0) { // facing down
mapX = Math.floor(rayX / Game.mapConfig.blockSize);
mapY = Math.floor(rayY / Game.mapConfig.blockSize) - 1;
} else { // facing up
mapX = Math.floor(rayX / Game.mapConfig.blockSize);
mapY = Math.floor(rayY / Game.mapConfig.blockSize);
}
}
// check if the box is solid; if so, stop the ray
if (Game.checkSolid(mapY, mapX)) {
hitWall = true;
var distance = Math.sqrt(Math.pow(rayX - Game.player.x, 2) + Math.pow(rayY - Game.player.y, 2));
Game.rays.distances[i] = [distance, Game.map.data[mapY][mapX]];
break;
}
}
if (!hitWall) {
Game.rays.distances[i] = [Infinity, " "];
}
}
}
似乎每当光线遇到长方体的角时,它都会在检查长方体是否为实心时跳过它,因为它检查错了长方体。我想我在计算
mapX
和
mapY
错误,但我不完全确定。
映射是一组嵌套数组,因此要访问左上角的单元格,需要调用
Game.map.data[0][0]
。
有人知道这里可能出了什么问题吗?
对于感兴趣的人,可以在这里找到完整的代码:
raycaster
。