Посмотрите на картинку. Вы для определения видимой высоты стенки в текущей точке используете расстояние от зрачка до пересечения луча с данной точкой стены, это и дает эффект рыбьего глаза.
Чтобы это исправить вместо данного расстояния вам надо использовать расстояние от точки пересечения до перпендикуляра к направлению взгляда.
Смотрите сноску в верхнем правом углу на рисунке.
Где:
A - камера
B - точка пересечения луча с преградой
Ось Y - направление взгляда
Ось X - перпендикуляр к направлению взгляда
α - угол между текущим лучем и осью x
R - расстояние от камеры до точки пересечения луча с преградой
l - расстояние от точки пересечения луча с преградой до перпендикуляра к направлению взгляда
Вот пример
https://jsfiddle.net/lastuniverse/0t1jo8cr/4/ , в нем есть некоторые искажения, возникающие из-за неправильного расчета length. Дело в том, что ваш алгоритм не находит точные координаты пересечения луча с гранью блока, а находит некую точку внутри блока, что так же добавляет искажения.
Вот еще вариант
https://jsfiddle.net/lastuniverse/6nrsL28g/8/ (переделал из ответа на вопрос
Почему данный код работает неправильно? от товарища
twobomb ). В нем эффект рыбьего глаза полностью нивелирован (смотрите функцию
drawGame(...)
). Как бонус - данный пример работает в несколько десятков раз быстрее, и позволяет ставить блоки нестандартного размера)))