habrahabr

Пост о маленьких видеоиграх

  • понедельник, 15 сентября 2014 г. в 03:11:18
http://habrahabr.ru/post/236713/

Привет, друзья. В этом посте мне бы хотелось рассказать, как я писал маленькие HTML5-игры для конкурса js13k, какие подводные камни повстречались на этом тернистом пути, и что получилось в результате.

Подводные камни на тернистом пути
(Подводные камни на тернистом пути — это русло пересыхающей реки, например. Летом в нем растет всякая трава и другие вегетарианские штуки, а осенью начинаются дожди, и всё уходит под воду. Получается терновник вместе с подводными камнями, очень метафорично и травмоопасно.)

Рассказ изобилует ссылками на разные штуки, которые помогли мне в работе, а значит, с некоторой вероятностью пригодятся и вам в схожей ситуации. Вообще цель этого поста — рассказать, как всё на самом деле просто делается. Уверен, это сразу же мотивирует тысячи людей писать всякие видеоигры и другие программы, или не мотивирует.

Но сначала 77 слов про js13k


Если кто-то пропустил, вкратце про конкурс: js13k это такой специальный способ для убиения свободного времени наповал. Нужно написать видеоигру, времени на это отводится месяц (я написал сразу две, от жадности как-то само получилось).

Основное требование — размер всех исходников приложения в архиве (zip) должен быть не более 13 килобайт. Программа должна работать оффлайн, сиречь подгрузить любимые шрифты с серверов гугла, а музыку с серверов SoundCloud не получится — нужно всё брать с собой в архив.

Получилось вот что


Такая постановка задачи сразу подталкивает, конечно, к генерированию ресурсов по большей части прямо на клиенте. Поскольку никаких особенных Соединенных Штатов в процедурных алгоритмах я так и не открыл, давайте сразу покажу, что получилось — может быть, дочитывать до конца тотчас же станет неинтересно, и вы сэкономите до десяти минут жизни.

Это очень серьезная экономия
(Это очень серьезная экономия: среднее количество просмотров моих постов (на выборке из последних четырех) — почти 20 тысяч. Если сэкономить 20 тысяч раз по 10 минут, получается четыре с половиной месяца — дети в этом возрасте уже родителей визуально отличают от других предметов.)

Вот две ссылки, первая и вторая. Гитхаб там внутри есть.

Если кто-то еще не плачет кровью из глаз от внешнего вида моих программ, то давайте я теперь расскажу как это все происходило, чтобы уж наверняка. Скучные исходники в пост копировать не стану, но они есть — всё оформлено ссылками на работающие примеры или гитхаб.

Итак, рассказ про запчасти видеоигр:

Планета, похожая на дискотечный шарик


Сначала у меня не было ни малейшего представления, что написать, но очень хотелось сотворить какую-нибудь твердь посреди ничего. Не то чтобы я возомнил себя таким уж иудео-христианским Б-гом, но почему бы и не твердь.

Первый попавшийся алгоритм развертки текстуры на шарик замечательно подошел. Вот дискотечная планета отдельно (по ссылке работающий пример). Настоящий исходник живет, конечно, в гитхабе.

И вот тут сразу начинаются ошибки проектирования.

Мне хотелось сделать прилично выглядящую планету с зелеными континентами и синим морьком, в которую прилетали бы астероиды, оставляя красивые черные пятна погибели и зла. Соответственно, шариковый рендерер это всё теоретически поддерживает, но желание реализовывать все крутые штуки в результате пропало, тем более на геймплей они совершенно никак не влияют. В сухом остатке тяжелый и довольно бессмысленный в контексте дискотечного шарика рендерер.

Лучше было обойтись чем-то попроще, хотя бы даже и статичной (или вращающейся в плоскости экрана, например) картинкой. Такое решение дало бы некислый выигрыш по производительности, да и смотрелось бы на 20-25% лучше, чем ничего. Ну да ладно, переделывать не стал — пусть будет диско-шарик.

(Про оверкилл: там в финальном варианте ещё вместо текстуры затайленный шум Перлина. Половина программы только и делает, что рисует ненужный шарик, безблагодатно, непрестанно.)

Астероиды


Дальше весёлая шизофрения в виде падающих на планету разноцветных астероидов. Тут такая штука: хотелось, чтобы они летели не по прямой, а как-нибудь вычурно. Моих отрывочных ностальгических воспоминаний о школьном курсе математики хватило на траекторию в виде дуги окружности. Для простоты все астероиды падают против часовой стрелки.

Вот маленькая программа, которой я тестировал математику. Можно шевелить мышкой и наблюдать, как эта штука силится построить дугу от мышки в центр экрана и найти точку пересечения с воображаемой планетой.

Сами астероиды простенькие, такие кривоватые многоугольники (к каждой вершине добавлена пара случайных чисел в пределах нескольких пикселей). Многоугольник рендерится в текстуру один раз и кешируется на протяжении всего жизненного пути астероида, после чего выкидывается.

Скорость у космических объектов исключительно угловая и совершенно одинаковая, поскольку автор оказался сказочно ленив.

И прочий космос


Об остальном космосе даже рассказать толком нечего. Звездочки ходят строем с шагом 5 пикселей. Хотел еще атмосферу планете нарисовать, получилась вот такая штука, но потом убрал — конструкция в сборе выглядела безобразно, и мой внутренний роскомнадзор Максвелла не пропустил эту гуманитарно-эстетическую катастрофу в мир живых.

(Вообще атмосферу надо бы, конечно, изображать поверх планеты. Но в браузере Firefox рендерер и так ощутимо тормозит, не хотелось его насиловать еще больше. Да, там можно оптимизировать копирование из одной текстуры в другую, но я не оптимизировал.)

Искусственный канонерский спутник, который вокруг планеты кружится, вообще очень скучный и не заслуживает ни капельки внимания. А при попадании астероида в планету включается вот такой эффект дрожания на CSS.

На этом прочий космос как-то сам собой закончился, и началось

Звуковое сопровождение


Вот тут меня приятно удивили сразу многие вещи.

Во-первых, библиотека для «восьмибитных» звуковых эффектов с непроизносимым названием jsfxr. Сочетая эту библиотеку с простенькой оберткой, можно ценой двух с половиной килобайт кода издавать душераздирающее пиликанье из любого места программы. Вот работающий пример (там целый пост в блоге с более подробным рассказом), оцените лаконичность, это ведь совершенно прекрасно.

Во-вторых, хотелось какой-то фоновой музыки, для этого jsfxr не подходит. Вспомнил про эту штуку, вкратце это такой своеобразный хак: берем целые числа от 0 и пока не надоест, для каждого считаем формулу, пишем байт в звуковую карту.

Некоторые маньяки прямо настоящую музыку делают таким способом.

В деле обретения формулы для неотвратительной фоновой мелодии мне очень помог демосценер ryg (Fabian Giesen, из Farbrausch). Вот тут в Твиттере можно пронаблюдать, как этот замечательный человек и талантливый программист дарит мне формулу. Было очень приятно. Да что там, до сих пор приятно.

Минимальный синтезатор звука вот тут, в нем всего несколько строк.

Кстати, если вас заинтересовала процедурная музыка, получаемая таким способом, то вот небольшая коллекция формул.

Трехмерные кубики


Во второй видеоигре существенно меньше элементов, в основном там просто доска с разноцветными кубиками посреди ничего. Программирование графики при помощи canvas меня необычайно к тому времени утомило, поэтому решил использовать CSS3. Получилось вроде классно:



Поиграться с прототипом тут. Можно вертеть доской при помощи слайдера. Слово nopsp (ненастоящее) означает бесперспективность, её надо выключить.

Про браузерную совместимость: в этом проекте я с префиксами не перетрудился, поэтому где работает, там работает. Последний Firefox и Хром/Хромиум обычно OK. (Проблема с префиксами в том, что они не только в CSS.)

Еще Firefox рисует торчащие пиксели без сглаживания, что могло бы смутить какого-нибудь слегка эстетствующего разработчика, а мне так больше нравится, чем мыльные края полигонов в Хроме — такое восьмибитное очарование. Обожаю старые видеоигры.

Поиск пути и другие вещи


Чтобы враги догоняли персонажа, понадобился поиск пути. Ничего изобретать не стал, использовал алгоритм A*, вот эту реализацию. Очень классная версия алгоритма, маленькая и быстрая.

Прочие аспекты игры не представляют, как мне кажется, технического интереса.

Если вы можете узнать названия уровней без гуглевания, мы могли бы подружиться, наверное.

Вывод


Конечно, в интернете можно без труда найти адскую прорву материала на тему программирования графики, звука и чего угодно еще.

Писать видеоигры — достаточно трудоемкий, но захватывающе интересный процесс, особенно спонтанно и «for fun», когда выдумываешь всё на ходу без предварительного планирования и разного там менеджмента.

Знаете, как в больших фирмах бывает — собираем, значит, совещание, чтобы обсудить результаты обсуждения результатов позапрошлого совещания… И немногочисленная радость от работы уходит, оставляя после себя гнетущую пустоту и безысходность. А тут получается совершенно наоборот, души прекрасные порывы идут во все поля.

И помните: попытка — первый шаг к провалу.



Такой вот мотивационный пост. Пожалуйста, напишите мне личные сообщения про то, как я не дружу с живым великорусским языком, и хорошего времени суток вам.