Дисклеймер: перевод статьи публикуется с одобрения оригинального автора
Поиграть можно тут (Chrome/Edge), исходный код здесь, текст статьи ниже.
На этой неделе я прочитал статью Брайана Брауна — "Я всё ещё продолжаю экспериментировать с чекбоксами". Там он рассказывал про свою библиотеку Checkboxland.
JavaScript-библиотека для отображения текста и анимаций на сетке из чекбоксов
Это довольно приятная библиотека. Её API и документация лучше некоторых библиотек, с которыми мне приходится иметь дело на работе. С её помощью можно рендерить текст, фигуры, изображения и видео. Есть низкоуровневое API. В ней есть всё, что надо. Брайан использовал Checkboxland для создания шикарных интерактивных анимаций.
Кто-то на Hacker News прокомментировал статью:
Я не думаю, что вы исчерпаете все возможности библиотеки, до тех пор пока не отренедерите с её помощью DOOM
После проверки, что Брайан ещё не взялся за реализацию этой идеи, я начал скрещивать Checkboxland и WebAssembly-порт DOOM Корнелиуса Дайкменна.
Корнелиус во всех деталях описывает процесс портирования DOOM в README. Я взял его порт за основу и написал glue-код для интеграции с Checkboxland.
В моём проекте DOOM запускается с помощью WebAssembly и рендерится в невидимый <canvas>
. Я использую HTMLCanvasElement.captureStream() для его преобразования в MediaStream
. Элемент <video>
отображает MediaStream
и передаётся методу renderVideo из Checkboxland. Я экспериментировал с разными пороговыми значениями, чтобы картинка получилась настолько чёткой, насколько это возможно. Одно из возможных улучшений — использовать что-то похожее на дизеринг.
Элемент <video>
тоже можно было спрятать, но по моим наблюдениям пользователи не могли выйти из главного меню без посторонней помощи, если они не видели оригинальную картинку.
Наш экран — это сетка 160 на 100, состоящая из нативных чекбоксов. С более высоким разрешением FPS падал совсем низко. Изображение в начале статьи из ранней версии с разрешением 320x200.
const cbl = new Checkboxland({
dimensions: "160x100",
selector: "#checkboxes",
});
Стигматизированное CSS-свойство zoom используется для уменьшения размера чекбоксов. Использование transform: scale(x)
приводило к худшей производительности и качеству картинки. К сожалению, это означает, что пользователи Firefox должны вручную уменьшить масштаб страницы.
Эта нестандартное свойство, и оно не находится в процессе стандартизации. Не используйте его на публичных сайтах — оно не будет работать у всех пользователей.
События нажатия клавиш форвардятся в скрытый <canvas>
, чтобы избежать проблем с фокусом.
const forwardKey = (e, type) => {
const ev = new KeyboardEvent(type, {
key: e.key,
keyCode: e.keyCode,
});
canvas.dispatchEvent(ev);
};
document.body.addEventListener("keydown", function (e) {
forwardKey(e, "keydown");
});
document.body.addEventListener("keyup", function (e) {
forwardKey(e, "keyup");
});
На время загрузки и компиляции WebAssembly-модуля на сетке отображается сообщение с помощью метода print:
После загрузки выводится сообщение о том, что нужно где-нибудь кликнуть, чтобы инициализировать <video>
. После клика запускается игра!
Пока вы всё ещё тут, вы знали, что Билл Гейтс однажды поместил себя в DOOM, чтобы прорекламировать Windows 95?
Примечание переводчика: если вам понравися перевод, то вам скорее всего понравится мой телеграм-канал, где я публикую рецензии на статьи про веб-стандарты, производительность и т.п.