Пользователь
0,0
рейтинг
19 августа 2010 в 15:09

Разработка → Наш опыт участия в 10K Apart или как ужать 40 Кбайт кода в 10

Не так давно на Хабре уже писали о контесте 10К Apart — соревновании на лучшее веб-приложение общим объемом до 10К, созданное с использованием только клиентских технологий: (HTML, CSS, Javascript, SVG и т.д).

image

Я хочу представить вашему внимаю нашу работу для этого контеста, которую мы с private_face делали по вечерам в течение двух недель: адвенчуру в стиле dungeon-crawler под названием «Fontanero» (исп. водопроводчик).

  • Генератор случайных связных подземелий.
  • Раскрытие карты по мере прохождения, раскрытие комнат.
  • 13 монстров c примитивным AI и алгоритмом нахождения пути.
  • Еда, питьё, 4 разных книги заклинаний: vision, heal, cure и genocide.
  • Эффекты отравления и ослепления.
  • Мини-игра с вращением и починкой труб
  • И даже чудовищный босс в конце.

Всё это многообразие в трёх файлах общим весом 10230 байт. Если вы когда-нибудь найдете на антресолях дискету 1.44МБ, то вы сможете записать на нее 144 такие игры.
После того, как мы определились с характером приложения (адвенчура), жанром (dungeon crawler в стиле nethack) и сеттингом (водопроводчик спускается в подвал, чтобы починить трубу и попадает в ад), настало время прикинуть сможем ли мы вообще реализовать задуманное и при этом уложиться в 10К.

Zip


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

Меня, как низкоуровнего программиста, сразу же очень заинтересовала возможность зажать js в zip, чтобы потом распаковать его во время выполнения. Первой мыслью было написать свой LZSS, но чуть позже родилась гораздо более простая мысль: положить js в PNG, ведь данные в нем сжимаются всё тем же zip-ом. (Как выяснилось позже — мы были не первыми, кому эта идея пришла в голову).

Изучив технологию, мы проверили возможность загрузить произвольный код через Canvas из палитровой png, закодировав символы в одной из компонент цвета. Тест успешно выполнился во всех требуемых браузерах, включая IE 9 preview (который теперь тоже поддерживает Canvas). Это был успех. Восьмибитная палитра может хранить 256 цветов, но после обфускатора остались только символы с кодами 32-94, и \n (10). Кодирование их в 64 значения, а не в 256, тоже дало значительную экономию (Странно, но png не умеет компрессить палитру).

Таким образом, стала ясна структура нашего будущего приложения: HTML страница-загрузчик со скриптом, восстанавливающим javascript из PNG, который содержит всю игровую логику, а так же динамически создает весь необходимый HTML и CSS. В финальной версии проекта загрузчик занимал 850 байт, включая даже alert(“no canvas”); (Нельзя же оставить пользователей старых браузеров перед белым экраном).

Обфускация


Zip увеличил фактическое число кода, которое мы могли себе позволить, но этого по прежнему было мало. Поэтому следующим шагом по оптимизации размера стал выбор обфускатора для JS.

Из представленных на рынке бесплатных решений мы выбирали между yui compressor и google closure compiler. В соревновании, разумеется, победил google closure compiler (далее gcc), который, положа руку на сердце, на сегодняшний день является лучшим по степени сжатия, плюс, выводит предупреждения, в большинстве своём, полезные.

Мы использовали gcc в аdvanced режиме, в котором он выкидывает неиспользуемый код, переименовывает все идентификаторы в одно-двухбуквенные, перестраивает ветвления, инлайнит функции и всячески курочит код, в погоне за байтами экономии.

Однако даже при использовании gcc в advanced mode все равно остается место для оптимизации. Во-первых, gcc боится переименовывать поля со стандартными, по его мнению, именами: left, right, top, bottom, name, type, width, height и т. п. Поэтому мы препроцессили наш код перед запуском gcc переименовывая такие имена сами. Во-вторых, после обфускации в коде остаются множество часто повторяющихся слов “function” и “this”. Чтобы сэкономить, мы заменяли их символы @ и `. Загрузчик при этом немного вырос на обратную замену: replace(/@/g, ‘function’).replace(/\`/g. ‘this’) и код после такой обрабоки выглядел достаточно чудовищно:
;`.g=n;`.K=`.v=o;`.F=@(d){var c=`.e;,
но это того стоило: в целом, с каждой замены получалось байт по 50.

CSS сжимали при помощи yui compressor и подкладывали прямо в конец javascript, предварительно порезав точки с запятыми перед закрывающимися скобками (60 байт экономии!).

Когда мы определялись с внешним видом игры, наши мнения с private_face разошлись. Я предлагал классический 2D вид:


Вова-2 настаивал на изометрии типа такого:


Поэтому далее я, набросав простой олдскульный рендер (всё рисовалось текстом внутри тэга textarea), продолжил писать игровую логику, и генератор карт, а вова начал возиться с своей изометрией. Он еще не знал, какой сюрприз ему готовит IE9. Ахахахахахахахах :((

Страсти по изометрии


private_face:
Реализация изометрии предполагалась следующая: прямоугольные блоки с наложенными на них текстурами переводились в изометрическую проекцию CSS-трансформациями skew и scale, после чего абсолютно позиционировались на нужное место.

Это решение требовало создания отдельного элемента DOM на каждый тайл, однако выглядело проще и компактнее (а главное производительнее), чем рисование на канве.
Кроме того, использование DOM-элементов позволяло не только накладывать текстуры, но и легко писать на стенах любой текст, что могло стать киллер-фичей для нашей игры.

Спустя некоторое время прототип был готов. Рендер получился достаточно компактным (все рисование было вынесено в CSS, javascript только позиционировал блоки)
и выдавал вполне неплохую картинку (хотя и ощутимо подтормаживал в Firefox 3.6):


Жизнь казалась прекрасной и безоблачной. Однако, загоревшись идеей изометрии, я забыл сделать одну важную вещь: убедиться, что CSS-трансформации поддерживаются новым Internet Explorer 9. Эта ошибка стоила мне бессмыслено потраченного времени и тонны невинно убиенных нервных клеток в финале. Потому что выяснилось, что единственный вариант реализовать трансформацию в IE9 — это фильтр Matrix. Но производительность такого решения была просто никакая.
В общем, от изометрии пришлось отказаться.

Назад к истокам


После провала 3D версии мы решили вернуться к простой тайловой версии.

Все тайлы рисовались в обычном GIMP-е и объединялись в PNG спрайт с 4-х битной (16 цветов) палитрой, после чего последний пережимался утилитой pngcrush с ключом -brute.

Некоторую объемность картинке удалось придать за счет установки свойства box-shadow тайлам стены и пола. Однако это неожиданно отрицательно повлияло на производительность Internet Explorer 9, в то время как остальные браузеры работали с нормальной скоростью. Чтобы не расстраивать пользователей IE9 тормозами, пришлось добавить к интерфейсу игры опцию “Включить тени”, которая по умолчанию отключена в этом браузере. Будем надеяться, что к релизу производительность box-shadow в IE9 поправят.

У перехода к 2D была и хорошая сторона: суммарный объем кода отрисовки значительно уменьшился, по сравнению с изометрическим вариантом, и высвобожденное место мы, в конечном счете, использовали для того чтобы добавить в к игровому процессу миниигру про починку труб.

Эпилог


Такова краткая история того, как мы делали эту игру. Начиная работать над этим проектом никто из нас не предполагал, что это будет так интересно — работать в жёстких ограничениях и экономя драгоценные байты. Мы получили огромное количество фана, а 10k отлично справились со своей задачей — reinspire the web.

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

А в завершение этого топика приведу еще раз краткий список оптимизаций, позволивших нам впихнуть почти 40К кода в 10К.
Оптимизация CSS:
  1. Упаковка CSS YUI Compressor-ом в строку, добавление результата в исходный .js файл.
  2. Удаление необязательных точек с запятой в конце каждого блока правил.
  3. Вставка полученной строки стилей к JS(то бишь упаковка css + js в одном архивном блоке).
Оптимизация JS:
  1. До обфускации: замена полей с именами left, right, name, type и т.д. на другие (т.к. GCC не переименовывает их даже в advanced режиме).
  2. Обфускация кода GCC в режиме advanced mode.
  3. После обфускации: замена ключевых слов function и this на однобуквенные сокращения ('@' и ' `').
  4. Инкапсуляция в протонный контейнер Упаковка в PNG.
Оптимизация картинок:
  1. Все изображения хранились в одном спрайте.
  2. Количество цветов в палитре было ограничено 16.
  3. После любого изменения, файл пережимался pngcrush'ем с параметром -brute, чтобы гарантировать наилучшее сжатие.

Небольшое обновление: Сегодня по многочисленным просьбам мы починили отображение миниигры в опере, хотя этого нет в требованиях конкурса. Патч на пути в 10K Apart.

Большое спасибо за внимание, мы будем очень рады, если вы оцените нашу игру на странице конкурса.
PS Жмём дальше, продолжение.
PPS Конкурс закончился, всем спасибо!
Владимир @whoozle
карма
117,2
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (123)

  • +46
    Запихнуть рогалик в десять килобайт на языке высокого уровня вместе с графикой?
    Ребят, вы реально больные, вы это знаете?
    • +35
      жалко что с 3d не вышло :D
      • НЛО прилетело и опубликовало эту надпись здесь
        • +24
          доделойте для себя 3d. и многочисленных фанатов (я и слава)
          • +4
            дадада, хочу диабло в броузере: Р
          • 0
            Поддерживаю! Офигенная игра в изометрии!!!
    • +1
      помнится в начале век на flasher.ru пару раз проводился «килогеймз», там в 1k надо было уложиться. и получалось :)
      • 0
        во флеше всё хорошо жмётся сразу, извращаться надо только интеллектуально, что конечно плюс)
  • +5
    вообще крутые вы!
  • 0
    Игра супер! Затягивает, очень трудно поверить, что это лишь 10 килобайт.
    • –1
      А мне сложно поверить, что пошлявшись по подвалам я за 10 минут накопал $548.
      Ушел за фонариком %)
  • 0
    Это круто! Я даже где уже писал, мы в свое время писали на спор программы под windows кто меньше размером получит исходный pe executable
  • +5
    Ребята, вы реально крутые! Желаю вам победы в этом конкурсе.
  • +5
    А не было ли в мыслях доделать 3D версию и черт с ним, с IE9?
    Очень хочется посмотреть на результат.

    И да — очень круто!
    • НЛО прилетело и опубликовало эту надпись здесь
      • +1
        не для конкурса, а просто для себя
        тем более, насколько я понял, 3D была уже почти готова
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Если доделаете 3D, то это будет просто супер!
          • 0
            к тому моменту как мы напишем, 4.0 выйдет, быхыхы
      • +2
        и это странно!
  • +4
    очень круто. еще и 10кб. вы просто демоны.
    проголосовал
  • 0
    Реально молодцы, и игра интересная. Удачи в конкурсе.
  • 0
    Очень круто! Молодцы!
  • +1
    Отлично.

    Только в ZIP алгоритм сжатия ZIP, а в PNG — DEFLATE. Кстати, а почему в PNG вы использовали только одну компоненту цвета? Вполне можно было использовать три компоненты цвета + прозрачность (она изменяется в пределах от 0 до 127, но у вас же алфавит ещё меньше).
    • +3
      Подозреваю потому, что они использовали не полноцветный PNG, а с палитрой.
    • 0
      В Zip используется (по умолчанию) тот же самый Deflate, не пишите ерунды
      • –1
        «The ZIP file format permits a number of compression algorithms, but as of 2009, the Deflate method continues to be dominant»

        Написано в Википедии.

        А чуть-чуть пониже: «WinZip, starting with version 12.1, uses the extension .zipx for ZIP files that use compression methods newer than DEFLATE; specifically, methods BZip, LZMA, PPMd, Jpeg and Wavpack – the last 2 are applied to appropriate file types when «Best method» compression is selected»

        Так что сами не пишите ерунды.
        • 0
          Мля, zip стандарт, когда создавался, использовал в основном Deflate, и до сих пор это есть наиболее используемый алгоритм сжатия.
          То, что потом его расширили для использования дополнительных алгоритмов, это уже другое дело.
          Даже в вашей цитате имеется «but as of 2009, the Deflate method continues to be dominant»
          Написать «Алгоритм сжатия ZIP» это полнейшее профанство.
          • 0
            Нет, это не так.

            Вы совершенно не учитесь на ошибках. DEFLATE появился только в версии 2.0, а не «когда ZIP был придуман». В первой версии использовался алгоритм, который назывался ZIP.
            • 0
              И снова мимо.
              Первые версие PKZip поддерживали алгоритмы Reduce & Implode.
              Поддержка Deflate появилась в 1993 году (ага, совсем недавно).
              И таже википедия, которую вы похоже не любите дочитать до конца, говорит про алгоритм Deflate:
              PKZIP: the first implementation, originally done by Phil Katz as part of PKZip.
              • –1
                Поддержка Deflate появилась в 1993 году (ага, совсем недавно).
                А я где-то сказал «недавно»?

                Ок. Вы меня убедили — ZIP не алгоритм сжатия.
                • +1
                  «Ага, недавно» — это насчет «только в версии 2.0», которая была 17 лет назад.
  • +3
    А может где-то таки завалялся работающий изометрический пример?
    Очень хотелось бы взглянуть…
  • +1
    После любого изменения, файл пережимался pngcrush'ем с параметром -brute, чтобы гарантировать наилучшее сжатие.
    Не нужно использовать эту устаревшую утилиту. Используйте связку optipng + pngout
    • +1
      optipng не смог больше ужать ни t.png, x.png, устаревший pngcrush смог ужать x.png на 1 байт. :D
      • +6
        Вы не прочитали мой комментарий внимательно. Там написано «связку optipng + pngout». Могу прислать вам ваш x.png, ужатый этой связкой ещё на 116 байт.
        • НЛО прилетело и опубликовало эту надпись здесь
          • +5
            Чего ж вы раньше мне не написали, я многое знаю об оптимизации :)))
        • 0
          А он работает после этого? Блин, 100 байт хватит на какую-нибудь крутую фичу! :)
          Лучше скажите как это делать, мы встроим в тулчейн, и попробуем.
          • +1
            PNG это формат без искажений, так что обязан работать :)

            Вот простой CMD-скрипт:

            @ECHO OFF

            IF "%1"=="" EXIT 1

            FOR /F "usebackq delims==,IDAT tokens=5" %%i in (`optipng -o4 -full -sim "%1"`) DO SET f=%%i

            IF "%2"=="" (
                pngout /k0 /n2 /f%f:~1,1% "%1" || EXIT 3
            ) ELSE (
               pngout /k0 /n2 /f%f:~1,1% "%1" "%2" || EXIT 3
            )

            Подробно есть в книге: speedupyourwebsite.ru/books/reactive-websites/
            • 0
              Ну как, несмотря на то что png lossless, бывают loss оптимизации, например, сокращение палитры. Если кто-нибудь сократит палитру x.png, то всё развалится. Я попробую.
              • 0
                Я понимаю. Это без сокращения палитры, blur и прочего такого.
            • 0
              если к этому еще дописать перекомпоновщик исходного кода, который меняет местами методы (без потери работоспособности, ессно), то может еще больше экономии получиться
            • +1
              $ ./pngout-static -k0 -n1 -f0 -y x.png x2.png
              In: 8229 bytes x.png /c3 /f0 /d8
              Out: 8083 bytes x2.png /c3 /f0 /d8, 95 colors
              Chg: -146 bytes ( 98% of original)

              с -n2 — всего лишь 138 байт, но это все равно больше 116и
              • 0
                собственно, интересно, это у меня pngout другой (порт на линух брал тут: www.jonof.id.au/pngout), или уже другую png-шку на 10kapart положили?
                • НЛО прилетело и опубликовало эту надпись здесь
            • 0
              попробовал переделать png с палитрой в grayscale png:

              $ convert x.png -channel R -separate x3.png && ./pngout-static -c0 -f0 -k0 -n1 -y x3.png x3crushout.png
              In: 8072 bytes x3.png /c0 /f0 /d8
              Out: 7807 bytes x3crushout.png /c0 /f0 /d8
              Chg: -265 bytes ( 96% of original)
              • 0
                в смысле весь цикл дает экономию в 8229 — 7807 = 422 байта
          • +4
            вот вам еще ~100байт, ваш переписанный распаковщик

            map=null;(function(f,j){var g=document,a=g.createElement(«canvas»),c,e=new Image,h=e.style,i=a.style,d=127;if(!a.getContext||!(c=a.getContext(«2d»))||!c.getImageData)alert(«No canvas»);else{h.position=«absolute»;h.top="-1000px";g.body.appendChild(e);e.onload=function(){a.width=a.height=d;i.width=i.height=d+«px»;c.drawImage(e,0,0);d=c.getImageData(0,0,d,d).data;b="";for(c=0;c<64516;c+=4){a=d[c];b+=String.fromCharCode(a>0?a+31:10)}j(b)};e.src=f}})(«x.png»,function(f){eval(f.replace(/@/g,«function»).replace(/\`/g,«this»));S()});
            • 0
              кстати g.body.appendChild(e); тоже не нужно — это еще +22bytes
            • 0
              ну и вместо
              map=null;(function…
              сделать
              map=(function…
              и; в конце убрать
              еще +6 :)
            • +2
              Думаете это все? ;)
              Вот финальная версия первоначального распаковщика:
              map=function(c,a,e){var d=document.createElement(a),b=new Image;b.onload=function(){d.width=d.height=a=127;c.drawImage(b,b=0,0);a=c[e](0,0,a,a).data;for(e="";b<64516;b+=4)e+=String.fromCharCode((d=a[b])?d+31:10);eval(e.replace(/@/g,«function»).replace(/\`/g,«this»));S()};d[c]&&(c=d[c](«2d»))&&c[e]?b.src=«x.png»:alert(«No „+a)}(“getContext»,«canvas»,«getImageData»)

              368 байта против 636 байт первоначального вида, то есть +268 байт в ваше распоряжение :)
              Идеи кончились: как пожать еще — не знаю :(
          • +4
            И еще моменты для нахождения свободных байт:
            — заменяйте не «this» а «this.»: ~15 «this» останутся незамещенными, зато код похудеет на 200+ байт (с 16108 до 15880)
            — можно заменить еще return и length, и возможно еще другие частые слова. если нет возможности добавить еще символы, можно использовать безопасно @@, @`, ``, `@:
            * после замены «return» -> @@, ".length" -> @` получаем еще +400 байт (от 15880 получаем 15478)
            * а если есть возможность использовать новые символы то получает еще +90 байт (15388)
            — переписать код с учетом того как жмет gcc, это может дать еще больше экономии и вполне вероятно более килобайта, так что можно будет засунуть еще что нить интересное ;)

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

            ЗЫ Если что, обращайтесь — поможем с дальнейшим сжатием ;)
            • +1
              Мы пробовали return, стало хуже сжиматься. Про this. это мы протупили, да, я сегодня утром сам догадался. :)
              Можно попробовать заменить .length на ^. Спасибо. :)
              На самом деле есть ещё 6 дней, можно добавить какую-нибудь смешную фичу.
            • +1
              замена this на this. дало результирующий размер 10308. fail. :)
            • +1
              замена .length на @@, вместе с патчем загрузчика дало 10226, то есть 4 байта экономии :D
            • +1
              ой, насчёт this накосячил, там прилично -30 байт! Спасибо! :)
              • +1
                Я и писал, что нужно смотреть как замены влияют на результат — а то исходный текст может оказаться и меньшим, а жаться от этого лучше не будет — а может еще и хуже. По сути zip как раз и делает такие замены только для всего текста.
                Были бы исходники — можно было бы посмотреть как пожать. Недавно имел опыт по оптимизации под сжатие gcc :) Для него порядок операторов может сыграть на результат, да еще и различные конструкции можно заюзить к которым gcc не сводит. Хотя опять же все изменения исходного кода могут оказаться пустой тратой времени и ухудшить конечный результат :)
                • 0
                  да, именно с этой развлекухой мы столкнулись и провели немало прекрасных часов :))))
                • 0
                  исходники fontanero
                  habrahabr.ru/blogs/personal/116811/
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        оптипнг судя по выводу делает тоже самое. :) Я только что проверил.
      • +1
        Совсем подробно можно почитать в книге: speedupyourwebsite.ru/books/reactive-websites/
  • +2
    Мега чуваки =) Особенно идея с PNG.
    • +2
      Я когда в первый раз смотрел эту игрушку, про PNG не знал (пришел не с хабра). Долго искал в коде <script>, который подключает те самые 10кб.
  • +1
    Потрясающе! Вот это качественная работа!
  • +2
    Потому что выяснилось, что единственный вариант реализовать трансформацию в IE9 — это фильтр Matrix.
    Можно было попробовать рисовать в векторе (SVG).
    • +1
      Имхо много кода получится.
  • +14
    Радуюсь комментариям на странице вашей игрушки:
    wow! great! pish pish!!! I will put it into my sait for bisnes!

    Itc is the cool gama! Kstate, toooooo vacuum. HALLO !!1

    very cute little game! obojayu takie igrushki!!!

    И только один человек не стал выпендриваться и просто написал:
    Молодцы! 5 баллов.
  • +2
    Прикольная игра, всю прошел. :) Жаль что не сделали Зал славы. :(
    • +1
      Ну вот там выше в комментариях на 116 байт ужали, может сделают.
  • +1
    Молодцы! На мой взгляд, у вас лучшая работа на конкурсе.
  • 0
    This is AWESOME!
  • 0
    С удовольствием прочитал топик.
    Вспомнилась книга Майкла Абраша, в которой он извращался над asm кодом с таким же упорством (цель, правда, была немного иной — там он бился за производительность, а не за сокращение объема кода)
    а веб-приложений тогда не было (вздыхает)
  • 0
    Прикоооольно )) Не веритсо даже что 10к. риальне
  • 0
    это круто
    насчет графики и IE9: для этих целей правильнее использовать canvas или SVG, они и ускорены через GPU и возможностей больше дадут
    но наверное не в рамках конкурса, но я надеюсь вы выкатите внеконкурсную версию с 3D :-)
  • +3
    Ааа, проклятый кролик! Я был так богат!..
  • –5
    В IE8 ошибка No Canvas. В Мозилле не работают actions вообще… Короче я зря 5 звёзд поставил :)))
    • +3
      В IE8 нет Canvas, по условиям конкурса нужна поддержка IE9
    • НЛО прилетело и опубликовало эту надпись здесь
      • +2
        Наверное из за раскладки, ибо счас работает. НУ тогда извиняюсь… :)
  • +1
    круто ;-) молодцы потратил N времени понравилось. В конце надо было чуть посложнее

    PURE WIN!!!
    Got $91093474
    Being dead 0 times.
    • 0
      Крутота! книжек к боссу принесли? :D
      • 0
        угу, только ниодной не воспользовался все берег их )))
        • 0
          Странно, кролик очень злой. Повезло значит.
      • 0
        да еще слишком быстро надо решать головоломки чтобы получить много денег… максимум что я выбил это 97 уе на 5х5 трубах. А босса убил случайно 2 раза стукнул 1 раз съел чего-то а он оказывается меня бьет в это время… стал убегать и случайно напоролся на него и убил… мне бы еще 1 удар и я был бы мертв
  • 0
    Awesome!
  • +1
    а я поставил 5 звезд и даже не играл.
    Игры не люблю, а сделали все круто. За державу не обидно.
    Спасибо ребята, промотивировали.
  • 0
    А переход на 8-й уровень не влез в 10кб? :(
    Я так заигрался…
    • +1
      надо выйти в выход вниз и будет босс :D
      • +1
        А, спасибо. Продолжу… :)
        • +2
          Заяц успешно завершил свое существование! :)
  • +4
    > (Как выяснилось позже — мы были не первыми, кому эта идея пришла в голову).

    Там, кстати, на бэкграунде Марио, в который можно побегать. Правда всего 1 уровень и без монеток, грибов и монстров.
  • 0
    рабочий день потерян )
    • 0
      надо пройти игру, чтобы он не прошел напрасно? :)
      • 0
        да уже раза три прошёл )
  • +10
    Из конкурса… автосимулятор :) 10k.aneventapart.com/Uploads/198/
    • 0
      А это вообще жесть: ~5kb javascript'а, без всяких ухищрений с png, к тому же сам код еще есть куда жать (думаю процентов на 25% еще можно)…
    • 0
      Забавно, что на Google Chrome машина едет быстрее, чем на Firefox. Именно машина, не сама игра — отрыв в 24 секунды.
    • 0
      физическая модель там работает с приближением кругового движения линейным %-)
      И траса генерируется каждый раз рандомно.
  • 0
    не буду оригинальным:
    прекрасная работа!

    не понял, каким образом, но как-то справился со всеми трубами) каким-то образом смог убить кролика не умирая — в основном отжирался запасами, несколько раз стукнул)
  • 0
    Победа?
  • 0
    Молодчаги! Надеюсь, победа будет ваша :)
  • –4
    а vml тут разве не мог бы помочь?
    • –1
      4 минуса — это не тот ответ, который я ожидал =_="
  • 0
    А последнего кролика без книг не убить, получается? Пробовал пить все что можно — убивает быстрее.
    • 0
      как повезёт, но вообще лучше иметь 3+ book of healing. Кто-то со второго раза кролика убивает. :)
  • +1
    Отличная игра! Прошел целиком и считаю, что с пользой потратил время.
    Единственное что — есть несколько замечаний по поводу игрового процесса и багов:

    1. Откуда такие астрономические суммы денег, выпадающие из монстров?
    2. Монстры слишком слабые, я пробегаю по уровням как джаггернаут, изредка потребляя пару из десятков найденных напитков и еды
    3. Если я решил выпить что-то, а потом передумал, как отменить?
    4. Я отказался чинить две трубы из трех, но оно все равно пишет, что найдено и починено три.

    Надеюсь, чем-то помогу сделать эту игру еще лучше :)
    • 0
      1. Если из монстра выпадает золотишко, то выпадает от 1/20 до 1/10 суммы, нужной чтобы получить новый левел.
      2. Мы не хотели задрачивать игрока, и сделали игру более казуальной. Монстры таки иногда бьют и иногда надо пить или есть.
      3. Никак. Да и плевать, будто бы еда или выпивка — редкость. :) Достаточно нажать s и что-нибудь да выпадет. :)
      4. Это кнопка(give up) значила не отменить, а сдаться. Если вы сдаётесь — получаете победный $1 на счёт и чините трубу. :)
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          нет, если ты не нажимаешь fix, и/или не открыл комнату где лежит труба — то всё, не выйдешь. надо обязательно чинить.
      • 0
        1. Тогда хотя бы количество денег делайте как X + 30%, а то реально жествко выглядит
        2. Ну, хозяин-барин, но если есть пара лишних байт и можно воткнуть уровни сложности — было бы очень здорово, чтобы игрок хотя бы немножко думал, а не ломился сквозь игру
        4. Лучше уж пусть она тогда оставляет трубу непочиненной
  • +4
    Ну! Кто ещё скажет что Хабр не торт?!
    Желаю удачи в конкурсе!
  • 0
    Ждём изометрию! Исключите мини-игру, проведите все оптимизации, которые вам насоветовали…

    Так же будет интересна диаграмма процентного распределения ресурсов. Ну, типа:
    Javascript: 60%
    — Генерация карты: 5%
    — Управление: 5%
    — Логика монстров, кроме кролика: 10%
    — Логика кролика: 40%
    CSS: 10%
    Спрайты (графика): 30%
    • 0
      логика кролика вроде стандартная:
      if (player.isMoving()) {
        this.copulate(player);
      } else {
        this.move(player);
        this.copulate(player);
      }
      • 0
        Цифры я привёл просто для примера, абсолютно левые и для смеха :-)
        • –1
          *facepalm*
  • 0
    > Жмём дальше, продолжение

    :-( не работает

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