Stage 0: Введение
Двумерная карта
Если вы вдруг не знали или забыли, то ранние шутеры Wolfenstein 3D и DOOM от компании id Software были псевдотрёхмерными. Разработчики особым образом достраивали ещё одно измерение на основе двумерной карты и делали проекцию на воображаемый экран камеры. Поэтому вполне очевидно, что разработку отрисовщика необходимо начать с реализации двумерной карты. Для этого нам потребуется ввести некоторые абстракции.
Введём такие сущности, как Vertex (вершина) и Linedef (отрезок):
interface Vertex {
x: number;
y: number;
}
interface Linedef {
start: Vertex;
end: Vertex;
}
Для работы с углами опишем класс Angle со вспомогательными методами:
class Angle {
private _degrees: number;
constructor(degrees: number) {
this._degrees = ((degrees % 360) + 360) % 360;
}
get degrees() {
return this._degrees;
}
get radians() {
return this._degrees * Math.PI / 180;
}
get cos() {
return Math.cos(this.radians);
}
get sin() {
return Math.sin(this.radians);
}
}
Опишем камеру, которую планируем перемещать по карте и на которую будет проецироваться будущее изображение:
interface Camera {
angle: Angle;
fov: Angle;
x: number;
y: number;
moveSpeed: number;
rotationSpeed: number;
}
Для каждого отрисовщика, а на странице их может быть несколько, добавим его настройки:
interface Settings {
camera: Camera;
level: Level;
}
type Level = {
linedefs: Linedef[];
}
Теперь добавим вспомогательный виджет, который будет показывать для карты сверху камеру, ее угол обзора и уровень как множество линий. Если рядом с картой будут присутствовать элементы управления, значит на этой странице можно управлять картой, например, перемещать камеру, приближать объекты на карте и прочее. Этот виджет будет сопровождать большинство заметок.
Управление камерой WASD
Кстати, если вы читаете эти заметки с мобильного устройства, то можете смело нажимать на все кнопки рядом с картой. Если они есть рядом с картой, значит они точно должны работать.