您好stackoverflow社区。最近,我一直在努力使适当的光线投射系统正常工作。目前,我一直在2D地图和播放器表示方面完全以2D进行工作。但是在正确创建基于网格的环境时遇到了问题。我认为问题在于我投射光线的方式根本不是基于网格的。我有一个问题here的示例。如您所见,射线显得断断续续且畸形。谁能给我一些有关基于网格的系统如何工作的见解?任何帮助表示赞赏,谢谢。
这是完整的源代码(我正在使用PIXI.js进行渲染):
var world = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1],
[1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,0,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1],
[1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1],
[1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
var width = world[0].length;
var height = world.length;
var scale = 8;
var posX = 1;
var posY = 1;
var yaw = 0;
var m = 0;
var renderer = new PIXI.WebGLRenderer(width * scale,height * scale);
//var renderer = new PIXI.WebGLRenderer(320,200);
document.body.appendChild(renderer.view);
var stage = new PIXI.Stage(0xFFFFFF);
var graphics = new PIXI.Graphics();
stage.addChild(graphics);
function drawMap()
{
for(var x = 0;x < width;x++)
{
for(var y = 0;y < height;y++)
{
if(world[y][x])
{
graphics.beginFill(0xCCCCCC);
graphics.drawRect(x * scale, y * scale, scale, scale);
graphics.endFill();
}
}
}
}
function drawPlayer()
{
graphics.beginFill(0x000000);
graphics.drawRect(posX * scale, posY * scale, 4, 4);
graphics.endFill();
graphics.lineStyle(1,0x000000);
graphics.moveTo(posX * scale + 2, posY * scale + 2);
graphics.lineTo(posX * scale + Math.cos(yaw) * 20 + 2, posY * scale + Math.sin(yaw) * 20 + 2);
}
function move()
{
var newX = posX + Math.cos(yaw) * m * 0.3;
var newY = posY + Math.sin(yaw) * m * 0.3;
m = 0;
if(isColliding(newX,newY))
{
return;
}
posX = newX;
posY = newY;
}
function isColliding(x,y)
{
if(world[Math.floor(y)][Math.floor(x)])
{
return true;
}
return false;
}
function castRays()
{
var rayYaw = 0;
var rayX = posX;
var rayY = posY;
var dist = 0;
for(var x = -160;x < 160;x++)
{
rayYaw = x * 0.1875;
while(!isColliding(rayX,rayY))
{
rayX += Math.cos((rayYaw) * (Math.PI / 180) + yaw);
rayY += Math.sin((rayYaw) * (Math.PI / 180) + yaw);
if(rayX < 0 || rayX >= width || rayY < 0 || rayY >= height)
{
break;
}
}
dist = Math.sqrt(Math.pow(posX - rayX,2) + Math.pow(posY - rayY,2));
graphics.lineStyle(1,0x00FFCC);
graphics.moveTo(posX * scale + 2, posY * scale + 2);
graphics.lineTo(rayX * scale + Math.cos((rayYaw) * (Math.PI / 180)) + 2, rayY * scale + Math.sin((rayYaw) * (Math.PI / 180)) + 2);
//drawLine(x + 160,dist);
rayX = posX;
rayY = posY;
}
}
function drawLine(x,d)
{
var slice = (32 * d / 160);
var start = (100 - (slice/2));
graphics.lineStyle(1,0xCCCCCC);
graphics.moveTo(x,start);
graphics.lineTo(x,slice);
}
function main()
{
drawMap();
move();
drawPlayer();
castRays();
renderer.render(stage);
graphics.clear();
}
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38')
{
// up arrow
m = 1;
}
else if (e.keyCode == '40')
{
// down arrow
m = -1;
}
else if (e.keyCode == '37')
{
// left arrow
yaw -= 0.1;
}
else if (e.keyCode == '39')
{
// right arrow
yaw += 0.1;
}
}
setInterval(main,1000/30);
最佳答案
您的问题是将地图视为矩阵,而isColliding()过于简化。您确实应该将矩阵中的每个1视为一个正方形,以确定您的射线是否以及在何处精确地击中它。
我将完全将castRays重新编写为更传统的光线跟踪方法:
for each point on your "screen":
define vector V from point of view P through this point on screen
for each line S + L*y forming sides of each square, find if your vector intersects it:
P + V*k = S + L*y when k>0 and y is in 0..1
最短的k(如果存在)形成您的线。
当您沿着这条道路前进时,有很多优化的空间。
更新资料
不想全部写下来,但是这里是有关射线盒相交优化的好文章,尤其是当盒子或矩形与轴对齐时:http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/
关于javascript - 基于网格的环境中的2D射线广播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19969744/