Привет, друзья. В этом посте мне бы хотелось рассказать, как я писал маленькие HTML5-игры для конкурса js13k, какие подводные камни повстречались на этом тернистом пути, и что получилось в результате.
Рассказ изобилует ссылками на разные штуки, которые помогли мне в работе, а значит, с некоторой вероятностью пригодятся и вам в схожей ситуации. Вообще цель этого поста — рассказать, как всё на самом деле просто делается. Уверен, это сразу же мотивирует тысячи людей писать всякие видеоигры и другие программы, или не мотивирует.
Но сначала 77 слов про js13k
Если кто-то пропустил, вкратце про конкурс: js13k это такой специальный способ для убиения свободного времени наповал. Нужно написать видеоигру, времени на это отводится месяц (я написал сразу две, от жадности как-то само получилось).
Основное требование — размер всех исходников приложения в архиве (zip) должен быть не более 13 килобайт. Программа должна работать оффлайн, сиречь подгрузить любимые шрифты с серверов гугла, а музыку с серверов SoundCloud не получится — нужно всё брать с собой в архив.
Получилось вот что
Такая постановка задачи сразу подталкивает, конечно, к генерированию ресурсов по большей части прямо на клиенте. Поскольку никаких особенных Соединенных Штатов в процедурных алгоритмах я так и не открыл, давайте сразу покажу, что получилось — может быть, дочитывать до конца тотчас же станет неинтересно, и вы сэкономите до десяти минут жизни.
Вот две ссылки, первая и вторая. Гитхаб там внутри есть.
Если кто-то еще не плачет кровью из глаз от внешнего вида моих программ, то давайте я теперь расскажу как это все происходило, чтобы уж наверняка. Скучные исходники в пост копировать не стану, но они есть — всё оформлено ссылками на работающие примеры или гитхаб.
Итак, рассказ про запчасти видеоигр:
Планета, похожая на дискотечный шарик
Сначала у меня не было ни малейшего представления, что написать, но очень хотелось сотворить какую-нибудь твердь посреди ничего. Не то чтобы я возомнил себя таким уж иудео-христианским Б-гом, но почему бы и не твердь.
Первый попавшийся алгоритм развертки текстуры на шарик замечательно подошел. Вот дискотечная планета отдельно (по ссылке работающий пример). Настоящий исходник живет, конечно, в гитхабе.
И вот тут сразу начинаются ошибки проектирования.
Мне хотелось сделать прилично выглядящую планету с зелеными континентами и синим морьком, в которую прилетали бы астероиды, оставляя красивые черные пятна погибели и зла. Соответственно, шариковый рендерер это всё теоретически поддерживает, но желание реализовывать все крутые штуки в результате пропало, тем более на геймплей они совершенно никак не влияют. В сухом остатке тяжелый и довольно бессмысленный в контексте дискотечного шарика рендерер.
Лучше было обойтись чем-то попроще, хотя бы даже и статичной (или вращающейся в плоскости экрана, например) картинкой. Такое решение дало бы некислый выигрыш по производительности, да и смотрелось бы на 20-25% лучше, чем ничего. Ну да ладно, переделывать не стал — пусть будет диско-шарик.
(Про оверкилл: там в финальном варианте ещё вместо текстуры затайленный шум Перлина. Половина программы только и делает, что рисует ненужный шарик, безблагодатно, непрестанно.)
Астероиды
Дальше весёлая шизофрения в виде падающих на планету разноцветных астероидов. Тут такая штука: хотелось, чтобы они летели не по прямой, а как-нибудь вычурно. Моих отрывочных ностальгических воспоминаний о школьном курсе математики хватило на траекторию в виде дуги окружности. Для простоты все астероиды падают против часовой стрелки.
Вот маленькая программа, которой я тестировал математику. Можно шевелить мышкой и наблюдать, как эта штука силится построить дугу от мышки в центр экрана и найти точку пересечения с воображаемой планетой.
Сами астероиды простенькие, такие кривоватые многоугольники (к каждой вершине добавлена пара случайных чисел в пределах нескольких пикселей). Многоугольник рендерится в текстуру один раз и кешируется на протяжении всего жизненного пути астероида, после чего выкидывается.
Скорость у космических объектов исключительно угловая и совершенно одинаковая, поскольку автор оказался сказочно ленив.
И прочий космос
Об остальном космосе даже рассказать толком нечего. Звездочки ходят строем с шагом 5 пикселей. Хотел еще атмосферу планете нарисовать, получилась вот такая штука, но потом убрал — конструкция в сборе выглядела безобразно, и мой внутренний роскомнадзор Максвелла не пропустил эту гуманитарно-эстетическую катастрофу в мир живых.
(Вообще атмосферу надо бы, конечно, изображать поверх планеты. Но в браузере Firefox рендерер и так ощутимо тормозит, не хотелось его насиловать еще больше. Да, там можно оптимизировать копирование из одной текстуры в другую, но я не оптимизировал.)
Искусственный канонерский спутник, который вокруг планеты кружится, вообще очень скучный и не заслуживает ни капельки внимания. А при попадании астероида в планету включается вот такой эффект дрожания на CSS.
На этом прочий космос как-то сам собой закончился, и началось
Звуковое сопровождение
Вот тут меня приятно удивили сразу многие вещи.
Во-первых, библиотека для «восьмибитных» звуковых эффектов с непроизносимым названием jsfxr. Сочетая эту библиотеку с простенькой оберткой, можно ценой двух с половиной килобайт кода издавать душераздирающее пиликанье из любого места программы. Вот работающий пример (там целый пост в блоге с более подробным рассказом), оцените лаконичность, это ведь совершенно прекрасно.
Во-вторых, хотелось какой-то фоновой музыки, для этого jsfxr не подходит. Вспомнил про эту штуку, вкратце это такой своеобразный хак: берем целые числа от 0 и пока не надоест, для каждого считаем формулу, пишем байт в звуковую карту.
Некоторые маньяки прямо настоящую музыку делают таким способом.
В деле обретения формулы для неотвратительной фоновой мелодии мне очень помог демосценер ryg (Fabian Giesen, из Farbrausch). Вот тут в Твиттере можно пронаблюдать, как этот замечательный человек и талантливый программист дарит мне формулу. Было очень приятно. Да что там, до сих пор приятно.
Минимальный синтезатор звука вот тут, в нем всего несколько строк.
Кстати, если вас заинтересовала процедурная музыка, получаемая таким способом, то вот небольшая коллекция формул.
Трехмерные кубики
Во второй видеоигре существенно меньше элементов, в основном там просто доска с разноцветными кубиками посреди ничего. Программирование графики при помощи canvas меня необычайно к тому времени утомило, поэтому решил использовать CSS3. Получилось вроде классно:
Поиграться с прототипом тут. Можно вертеть доской при помощи слайдера. Слово nopsp (ненастоящее) означает бесперспективность, её надо выключить.
Про браузерную совместимость: в этом проекте я с префиксами не перетрудился, поэтому где работает, там работает. Последний Firefox и Хром/Хромиум обычно OK. (Проблема с префиксами в том, что они не только в CSS.)
Еще Firefox рисует торчащие пиксели без сглаживания, что могло бы смутить какого-нибудь слегка эстетствующего разработчика, а мне так больше нравится, чем мыльные края полигонов в Хроме — такое восьмибитное очарование. Обожаю старые видеоигры.
Поиск пути и другие вещи
Чтобы враги догоняли персонажа, понадобился поиск пути. Ничего изобретать не стал, использовал алгоритм A*, вот эту реализацию. Очень классная версия алгоритма, маленькая и быстрая.
Прочие аспекты игры не представляют, как мне кажется, технического интереса.
Если вы можете узнать названия уровней без гуглевания, мы могли бы подружиться, наверное.
Вывод
Конечно, в интернете можно без труда найти адскую прорву материала на тему программирования графики, звука и чего угодно еще.
Писать видеоигры — достаточно трудоемкий, но захватывающе интересный процесс, особенно спонтанно и «for fun», когда выдумываешь всё на ходу без предварительного планирования и разного там менеджмента.
Знаете, как в больших фирмах бывает — собираем, значит, совещание, чтобы обсудить результаты обсуждения результатов позапрошлого совещания… И немногочисленная радость от работы уходит, оставляя после себя гнетущую пустоту и безысходность. А тут получается совершенно наоборот, души прекрасные порывы идут во все поля.
И помните: попытка — первый шаг к провалу.
Такой вот мотивационный пост. Пожалуйста, напишите мне личные сообщения про то, как я не дружу с живым великорусским языком, и хорошего времени суток вам.
Автор: printf