Движки-крохотульки
Всем привет!
В мире разработки веб-игр существует множество малоизвестных, но мощных и минималистичных игровых движков, которые могут стать отличной альтернативой крупным решениям — как для простых задач, так и для более сложных проектов. Они часто ориентированы на простоту, минимализм, быструю разработку и компактный размер.
Почему размер игрового движка для веб-игр — это не просто цифры, а магия скорости
Размер игрового движка — как размер чемодана для космонавта: чем компактнее, тем лучше. Представьте: вы заходите на сайт, кликаете «Играть», а вместо загрузки видите бесконечно вращающееся «колесо». Скорее всего, вы закроете вкладку. Веб-игры живут по законам мгновенного удовольствия: если игра грузится дольше, чем нужно, чтобы заварить кофе, пользователь сбежит.
Например, движок весом в 100 КБ загрузится за 0.1 секунды на 4G, а 5 МБ — за 4 секунды. А теперь вспомните, как часто вы ждёте эти 4 секунды… Для игроков из стран, где интернет дорогой, каждый килобайт на счету.
Сколько Вам надо место для игры?
Среди конкурсов выделяется уникальный формат — Js13kGames. Это ежегодное соревнование, где разработчики создают игры размером не более 13 КБ в ZIP-архиве.
Правила Js13kGames:
- Размер: Игра должна уместиться в ZIP-архив до 13 КБ.
- Технологии: В архиве — только index.html, работающий минимум в двух браузерах. Никаких внешних ресурсов или библиотек. Исходники публикуются на GitHub
Тема 2024 года — Трискайдекафобия (боязнь числа 13). Участники представили 188 игр, которые можно посмотреть здесь.
Kontra.js
Для этого конкурса Стивен Ламберт (straker) создал микро библиотеку Kontra.js. Её ключевые преимущества — простота и минимализм.
import { init, Sprite, GameLoop } from 'kontra';
let { canvas } = init();
let sprite = Sprite({
x: 100, // начальная позиция (x, y)
y: 80,
color: 'red', // цвет заливки
width: 20, // ширина и высота
height: 40,
dx: 2 // перемещает на 2px/кадр
});
// Создаём основной цикл игры
let loop = GameLoop({
update: function() { // обновляем состояние игры
sprite.update();
// Меняем позицию спрайта, когда он достигнет края экрана
if (sprite.x > canvas.width) {
sprite.x = -sprite.width;
}
},
render: function() { // отрисовываем состояния игры
sprite.render();
}
});
loop.start(); // начать игру
Игры на движке можно посмотреть по этой ссылке.
Кажется, что в движке есть всё: Animation, Assets, Button, Core, Events, GameLoop, GameObject, Gamepad, Gesture, Grid, Helpers, Keyboard, Plugin, Pointer, Pool, Quadtree, Random, Scene, Sprite, SpriteSheet, Text, TileEngine. Но не совсем. Системы частиц нет, но, используя пул объектов, это легко решается.
Без минусов никуда:
- рендеринг через Canvas, а не WebGL — нет шейдеров, ниже производительность;
- нет физики и коллизий — нужно писать самому;
- нет автоматической поддержки изменения размеров окна (мелочь конечно, но пишем сами).
Весь исходный код занимает 7827 строк, но в них входят пустые строки, с одной фигурной скобкой, комментариями и примерами в них. То есть за 1−2 вечера можно полностью изучить исходники движка и пользоваться им, модернизировать.
LittleJS
Следующим движком, на изучение которого уйдёт почти столько же времени это LittleJS. В нём всего 5878 строк кода (с комментариями и всем остальные), но с одной стороны он более продвинутый в плане возможностей по сравнению с Kontra.js, с другой некоторых вещей в нём не хватает.
Всё по порядку… Автор движка является Фрэнк Форс (Frank Force, KilledByAPixel). Разработчик игр и генеративный художник с более чем 20-летним опытом. Он известен тем, что создает цифровое искусство с помощью чрезвычайно маленьких программ и выпустил более 1000 работ. Это исследование привело к другим более крупным проектам, таким как умопомрачительная «Dual Axis Illusion», которая выиграла премию «Оптическая иллюзия года 2019». В прошлом он участвовал в разработке игр Psi-Ops, Starhawk, Doom. Его инди проект Piroot ожидает выхода в Steam в марте этого года.
Игровой движок LittleJS быстрый, легкий. Он использует WebGL для рендеринга, что обеспечивает плавную работу даже на слабых устройствах. Даёт больше пространства для эффектов. Через систему плагинов в одном из примеров реализована постобработка с шейдером. Встроенный простой и быстрый физический движок. Через плагины можно подключить другие (или не через плагины).
Интересно ещё то, что в этот маленький движок добавлена своя «звуковая система». Фрэнк реализовал свою версию утилиты по созданию звуковых эффектов по названием ZzFX. В движок он добавил функции воспроизведения, поэтому можно задавать звуки набором чисел. Например:
// Взрыв
zzfx(...[2.1,,37,.06,.26,.65,4,.1,,,,,,.8,.6,.5,.45,.3,.12]);
И это не всё. Можно писать музыку в онлайн-трекере/секвенсоре под названием ZzFXM и воспроизводить её в движке. Разумеется у всего это открыт исходный код (ZzFX, ZzFX Music Generator).
Я изучал движок более подробно и писал на нём тестовый проект Пузыри. Код движка довольно простой. Для инициализации необходимо выполнить следующее:
// Звуковой эффект
const soundClick = new Sound([1, 0.5]);
// Для системы частиц
let particleEmitter;
function gameInit() {
// Начальные настройки игры
setGravity(-0.01); // устанавливаем гравитацию
// Создаём систему частиц
particleEmitter = new ParticleEmitter(
vec2(16, 9), 0, 0, 0, 500, PI,
tile(0, 16), hsl(1, 1, 1), hsl(0, 0, 0), hsl(0, 0, 0, 0),
hsl(0, 0, 0, 0),
2, 0.2, 0.2, 0.1, 0.05,
0.99, 1, 1, PI, 0.05, 0.5, true, true
);
particleEmitter.elasticity = 0.3;
particleEmitter.trailScale = 2;
}
function gameUpdate() {
// Здесь описывается обновление игровой логики
if (mouseWasPressed(0)) {
// Проигрываем звук при нажатии
soundClick.play(mousePos);
// Изменяем цвет частиц и режим затухания
particleEmitter.colorStartA = hsl();
particleEmitter.colorStartB = randColor();
particleEmitter.colorEndA = particleEmitter.colorStartA.scale(1, 0);
particleEmitter.colorEndB = particleEmitter.colorStartB.scale(1, 0);
}
// Двигаем систему частиц за курсором мыши
if (mousePosScreen.x) particleEmitter.pos = mousePos;
}
function gameUpdatePost() {
// Подготовка перед отрисовкой
}
function gameRender() {
// Отрисовка эффектов, которые появляются за игровыми объектами.
// Вызывается перед отрисовкой игровых объектов.
}
function gameRenderPost() {
// Вызывается после отрисовки игровых объектов.
// Эффект, UI, всё что должно быть перед объектами
}
// Запуск LittleJS
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, [
"tiles.png",
]);
Для создания игровых элементов мы наследуем нужные объекты от класса EngineObject и описываем его «работу». Все созданные таким образом объекты автоматически попадают в массив, объекты из которого, движок рисуем сам.
Какие же минусы я обнаружил:
- объекты рисуются в порядке создания. У класса есть параметр renderOrder, отвечающий за глубину, но нужно его определять вручную. Не зависимо от положения объекта в иерархии, он будет рисоваться в соответствии с этим параметром и месте в массиве объектов;
- в этой системе иерархии объектов не учитывается изменения размера родителям.
Т. е. все дочерние элементы нужно масштабировать самому; - нет встроенного UI для игры. Сейчас автор с сообществом уже добавляет через плагины такой функционал;
- нельзя применить шейдер к конкретному объекту, текстуре. Мы с автором немного обсудили эту функцию, и он записал её себе в работу, но когда будет реализовано, не известно пока;
- ограниченная работа с текстурами (только предзагруженные атласы).
О последней проблеме чуть подробнее. Как видно в коде, в функции `engineInit` один из аргументом это массив изображений, который будет использоваться в игре. Так вот это единственный способ добавить в игру текстуры. Разработчик и так реализовано в движке, что ты работаешь с текстурным атласом.
В игровых объектах ты указываешь из какого атласа (индексом), какой участок (изображение) ты будешь рисовать. И нельзя удалить, подгрузить новые, просто нет таких функций. Технические, в движке это один массив textureInfos, который и хранит указанные картинки. Легко написать самому пару функций, для его изменения. Но такая реализация от автора.
Пример и игры созданные на данном движке можно посмотреть по этой ссылке. Совсем недавно прошёл джем по движку.
Kaplay
Игровой движок Kaplay (бывший Kaboom.js) из другой весовой категории. Без комментариев, пустых строк и переносов, его размер чуть меньше 200 килобайт. В нём много всего встроено, страдает производительность при большом количестве объектов, но сообщество вместе с разработчиком занимается этим вопросом. Меня он лично заинтересовал своим API. Вот пример кода:
// Инициализация
kaplay()
// Установка значения гравитации
setGravity(2400)
// Загрузка спрайта и указание ему имени "bean"
loadSprite("bean", "sprites/bean.png")
// Добавление на сцену игрового объекта, который состоит из компонентов
const bean = add([
sprite("bean"), // указываем спрайт
pos(80, 40), // задаём позицию
area(), // формируется маска столкновения
body(), // задаётся "физическое" тело
fadeIn(0.5), // объект будет "появляться" в течение 0.5 секунды
])
// При нажатии на кнопку Space наш объект прыгает.
onKeyPress("space", () => {
// Данные метод есть у объекта, потому ему был присвоен компонент "body"
bean.jump()
})
// Если у объекта есть компонент "area", то можно ещё обработчики добавить
bean.onClick(() => {
destroy(bean);
});
// Добавим текст
const label = add([
text("Hello world!"),
pos(80, 40),
]);
Если посмотреть, то очень легко настраиваются разные объекты, добавляются к ним обработчики. Будто это делаешь просто в конструкторе. Такое легко и простое взаимодействие с движком меня порадовало, когда я делал текстовый проект Пузыри на нём.
Экскурсия закончилась
Такие интересные игровые движки существуют. А знаете, сколько их ещё? Уууууу…
Спасибо, что дочитали! Удачи! =)
- 27 января 2025, 21:59
- 016
Gyt, тут разметка сломалась:
Я копировал текст, и он подставил этот отступ в самом посте. Там его не видно, но на превью делает так. Не смог его инструментами убрать.
Поправил, это какие-то div'ы и прочее с ВК скопировалось, можно через исходный код в редакторе посмотреть.
Я с ВК и копировал, сначала там оформил. Копируется почти нормально, не считая этого.
Буду знать, спасибо.
Unity!
Это web-движок с открытым исходным кодом, которые помещаeтся на 3.5″ дискету? Не думаю.
Я скорее о:
Не слышал про такой 🤷♂️
Если не ошибаюсь, это знаменитый опен сорс движок, доступ к которому есть только у мегаинформатика.
Предлагаю джем, где за неделю нужно разобраться в движке информатика и написать на нем игру :В
Или игру, в которой вместо монстра тебя везде преследует Мегаинформатик и постит интервью с тобой, которое ты ему не давал.
Я давал ему интервью -_-
902 байта всего!
О нифига, у тебя шеститысячная версия
Это типа Unity 6. У них давно уже нумерация была по годам, и версии движков были буквально 2021.xxxx 2022.xxxx и вот теперь чтобы версия движка была не меньше пришлось 6000 ставить. Попались в собственную ловушку короче.
и да, я тебе в личку черканул, ответь плиз
PuzzleScript ещё хороший, но под определённый жанр.
Когда у меня сломается ноутбук, который я купил 10 лет назад, у меня больше не будет CD-дисковода. 3.5" что, простите? :D
Я описал универсальные движки...
если для браузера в сотню мегабайт который требует win10+ и тормозит на компах семилетней давности можно писать крохотные движки, то почему бы не писать их для юнити!
Кстати, Стим-клиент - это же по сути тоже веб-сайт. Могли бы и веб-игры туда засунуть тогда! :yak:
Да он сам себя не выдерживает уже, учитывая все эти анимированные обводки для профиля! Хватит! Остановитесь!
Да сейчас куча программ это "сайты": Steam, Discord, Evernote, VSCode...
а в дискорде кстати есть игры
Ходят слухи, что в Дискорде есть игры, но не ясно, где их там найти :D
Заходишь ты такой в Дискорд, а там... китайские нейросети в маджонг играют!
Однажды я выражал такую мысль, чтобы играть прям на сайте Стима. Кажется, это было на волне выхода очередного облачного гейминга.
Но вообще, представьте демки больших игр запускать прямо в браузере или клиенте магазина. Для этого правда нужны непонятно какие мощности, чтобы любой мимо-крокодил пусть и с аккаунтом ходил играть.
Почему больших игр? Какие смогут портировать в веб и какие захотят вообще выпускать демку бесплатно, такие и демки. И не только демки - купил игру, начал играть в браузере, потом установил игру, скачал сейв из Стим-облака и продолжил.
В Google ещё в 2018 году анонсировали и потом реализовали Google Play Instant. Технология, которая позволяет открывать некоторые приложения и использовать их функции без предварительной установки. Они называются "приложения с мгновенным запуском". Но Steam`у похоже просто лень...