Stage 1: Отрисовка стен
Проекция отрезков
На этом шаге мы можем воспользоваться следующей идеей: зная высоту предмета на конкретном расстоянии, мы можем найти его высоту на любом другом расстоянии, используя пропорцию. А зная высоту, мы можем получить координату Y для нижней и верхней части этого предмета.
Таким образом, для каждой вершины из отрезка мы вычисляем расстояние, затем получаем два значения Y для его верхней и нижней части. Теперь, если соединить эти точки, то мы получим четырехугольник.
2.5D Renderer
2D Renderer
Управление камерой WASD
Как это рассчитать
Определим расстояние от позиции камеры до точки:
Пусть на расстоянии 1 высота стены будет равна константе H wall, тогда на расстоянии d высота:
На основе проекции screenX на экран и найденной высоты стены h формируем координаты четырёхугольника.
Немного кода
Ранее спроецированные точки достраиваем до четырёхугольника:
function projectionToPoints(
camera: Camera,
vertexProjectionStart: VertexProjection,
vertexProjectionEnd: VertexProjection,
): Vertex[] {
const wallStartHeight = vertexProjectionStart.height;
const wallEndHeight = vertexProjectionEnd.height;
const horizontalHeight = camera.screen.height / 2;
return [
{
x: vertexProjectionStart.screenX,
y: horizontalHeight - wallStartHeight / 2,
},
{
x: vertexProjectionStart.screenX,
y: horizontalHeight + wallStartHeight / 2,
},
{ x: vertexProjectionEnd.screenX, y: horizontalHeight + wallEndHeight / 2 },
{ x: vertexProjectionEnd.screenX, y: horizontalHeight - wallEndHeight / 2 },
];
}
И теперь на их основе рисуем многоугольник на экране:
function render25d(
ctx: CanvasRenderingContext2D,
settings: Settings,
) {
for (const linedef of settings.level.linedefs) {
const vertexProjectionStart = projectVertexToScreen(settings.camera, linedef.start);
const vertexProjectionEnd = projectVertexToScreen(settings.camera, linedef.end);
if (!vertexProjectionStart || !vertexProjectionEnd) {
continue;
}
drawPolygon(
ctx,
projectionToPoints(settings.camera, vertexProjectionStart, vertexProjectionEnd),
);
}
}