Stage 1: Отрисовка стен
Проекция вершин
Самое тяжелое в проектировании — это определить базовый набор идей и абстракций. И честно говоря, в свое время мне было тяжело понять, какой шаг нужно было сделать первым, пока не познакомился с заметками DIYDoom, а в частности с тем, как необходимо сделать горизонтальную проекцию.
На этом шаге необходимо сделать проекцию вершины на камеру в виде вертикальной линии.
2.5D Renderer
2D Renderer
Управление камерой WASD
Как это рассчитать
Введем условные обозначения:
Вычисляем угол между направлением камеры и вершиной на карте:
Если угол входит в поле обзора камеры, мы линейно преобразуем его относительное положение внутри области видимости в координату X на экране:
Немного кода
Получившийся мир для нас — это множество спроецированных точек в виде вертикальных линий:
function render25d(ctx: CanvasRenderingContext2D, settings: Settings) {
const camera = settings.camera;
for (const linedef of settings.level.linedefs) {
for (const vertex of [linedef.start, linedef.end]) {
const screenX = projectVertexToScreen(vertex, camera);
if (screenX == null) {
continue;
}
ctx.fillStyle = "black";
ctx.fillRect(screenX, 0, 1, screen.height);
}
}
}
Проекция вершины на экран:
function projectVertexToScreen(vertex: Vertex, camera: Camera) {
const vertexAngle = toAngle(vertex, camera).degrees;
const cameraAngleFrom = camera.angle.degrees - camera.fov.degrees / 2;
const cameraAngleTo = camera.angle.degrees + camera.fov.degrees / 2;
if (cameraAngleTo < vertexAngle || vertexAngle < cameraAngleFrom) {
return null;
}
return (
((vertexAngle - cameraAngleFrom) / camera.fov.degrees) * camera.screen.width
);
}