gpt4 book ai didi

javascript - 基于网格的环境中的 2D 光线转换

转载 作者:行者123 更新时间:2023-11-29 19:45:36 25 4
gpt4 key购买 nike

你好 stackoverflow 社区。最近,我一直致力于让光线转换系统正常工作。目前,我完全在 2D 中工作,使用 2D map 和玩家表示。我在正确创建基于网格的环境时遇到问题。我认为问题在于我转换光线的方式根本不是基于网格的。我有一个问题的例子 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);

最佳答案

您的问题是您将 map 视为矩阵,而 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com