Привет, сообщество stackoverflow. Недавно я работал над созданием правильной системы raycasting. В настоящее время я полностью работаю в 2D, с 2D-картой и представлением игроков. У меня возникли проблемы, но правильно создаю среду с сеткой. Я думаю, что проблема заключается в том, как я использую лучи, не основанные на сетке. У меня есть пример моей проблемы here. Как вы можете видеть, лучи кажутся изменчивыми и искаженными. Может ли кто-нибудь дать мне некоторое представление о том, как будет работать система на основе сетки? Любая помощь приветствуется, спасибо.2D Raycasting в среде на основе сетки
Вот полный исходный код (я использую 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);