CANVAS 1K Tank Game
Решил попробовать уместить какую-нибудь игру с использованием тега CANVAS в 1КБ. После всех оптимизаций, который заняли у меня вдвое больше времени, чем написание игры, получилась несложная игрушка в 1020 1023 байта (то есть на четыре один байт меньше, чем килобайт).
Цель — подбить своим «танком» как можно больше вражеских ракет. Управление — курсорными клавишами, стрелять пробелом. Даётся три жизни, за каждые 20 сбитых ракет жизнь добавляется, если ракета долетит до вашей стороны или коснётся танка, жизнь теряется. Для рестарта игры просто перезагрузите страницу.
Должно работать везде, где поддерживается тег CANVAS, я тестировал в «Опере» 11, «Хроме» 10 и FF 3.6.13.
Have a fun!
Ещё позже: на заметку. Я вчера обращался к тегу CANVAS по идентификатору. Это очень длинный способ (не говоря уже о том, что тег должен иметь идентификатор, что ещё тратит место), вчера, когда мне показали JS1K, я там увидел способ короче: «document.body.children[0]», а сегодня я придумал способ ещё короче: «document.all[3]», это нестандартное свойство, но его поддерживают все браузеры.
Если использовать это свойство, то программа начинает занимать 1007 байт и у меня появляется ещё 17 байт. Может танк переделать? Мне пришлось упростить графику, из-за чего танк стал выглядеть странно.
И ещё позже: вернул прежний танк и сменил цвет «спецэффекта» при столкновении на красный, игра снова занимает 1020 байт. Если интересно, можно посмотреть как выглядит исходный код JavaScript моей игрушки. И ещё я внезапно придумал как ещё чуть-чуть сократить код.
И ещё: сократил чуть-чуть код, в частности, стрелять можно любой кнопкой, кроме курсорных. Освободилось несколько байт и я в левом верхнем углу нарисовал ракету, чтобы было понятно, что это количество сбитых ракет. Игра стала занимать 1023 байта.
В мобильном сафари тоже работает, только нечем управлять. Может, попробуете адаптировали под iPhone?
Комментарий для jankkhvej.blogspot.com:
Это интересно, кстати. Я не пробовал писать ничего под touchscreen. Правда, iPhone у меня нет, но, думаю, если адаптировать под «Андроид», то и iOS приложится.
Firefox 3.6.13, linux. Выглядит так:
http://ksim.ru/img/screenshot/scr_wFjtWY.png
никаких танков нет, размер страницы 278 байт, а не 1020. Если перегружать страницу, иногда появляется квадратное поле с работающей игрой.
Комментарий для maxim-zotov:
У меня негде понять что не так, увы. Никаких ошибок в консоли FF нет?
Это нормально, основной код лежит в PNG-файле (кстати, я создал, наверное, самый маленький загрузчик такого кода).
Комментарий для Евгения Степанищева:
Да, в консоли есть ошибка:
Error: uncaught exception: [Exception... «Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMCanvasRenderingContext2D.drawImage]» nsresult: «0x80040111 (NS_ERROR_NOT_AVAILABLE)» location: «JS frame :: http://bolknote.ru/files/tank-1k-game/ :: anonymous :: line 5» data: no]
Посмотрел по трафику: и при ошибке, и при правильной работе одно и то же приходит от сервера, скрипт и картинка.
Под вин7 и ФФ 3.6.13 тоже самое что и у Максима. Правда со второго раза как зашол игра запустилась, поиграл, вернулься в коменти и счас как и в впервый раз — тоже самое что уже Максим показал — сколько не заходи только прямоуголник и эта ошибка на 5 строке.
Комментарий для praeivis.lt:
Гм. Попробую разобрать в чём дело, но не обещаю. Ошибка очень невнятная, ещё и «плавает».
Явно какая-то ошибка в drawImage. Возможно, DOM не готов к работе.
Судя по тому, что пишут в интернетах, это действительно ошибка неготовности DOM. Обходят её, чаще всего, делая setTimeout(…, 0).
Не думаю, что это критично, у меня не хватит терпения записать ещё один таймер в четыре байта, которые остались мне до килобайта :)
Комментарий для Евгения Степанищева:
Дарю 45 байт.
n=’000’;G=n+n+914062108081923..toString(2);Z=n+6798437144058750..toString(2)
Комментарий для Евгения Степанищева:
Точнее 46 без учёта сжатия
s=’toString’;n=’000’;G=n+n+914062108081923[s](2);Z=n+6798437144058750[s](2)
Комментарий для LO:
Спасибо! Я пытался сократить код подобным образом, но вы не учитываете, что он у меня сжимается алгоритмом Deflate, а последовательность длинных однородных символом там сжимается очень хорошо. Поэтому как я не крутил это место, но лучше всего сжались единицы и нули (кстати, вместо нулей у меня в первом варианте были пробелы, нули сжались лучше, так как внутри кода есть ещё последовательность нулей).
Поэтому мой сжатый вариант занимает 753 байта, ваш — 766.
Комментарий для Евгения Степанищева:
ОК, не учёл этого. Спасибо!
По поводу идентификатора. Во всех означенных выше браузерах работает обращение к эл-ту из глобальной области по идентификатору, что экономит 14 байт.
<body onload=alert(t)><canvas width=1059 style=«border:5px solid #000»id=t>
Комментарий для Евгения Степанищева:
R=_(’’,’...’) --> R=_($,’...’) ?
Комментарий для LO:
Спасибо! Этого я не знал.
Там можно выкинуть массу переменных (например, «v»), но парадокс — сжимается хуже, поэтому я остановился. Думаю, что как-нибудь попробую уместить что-нибудь в килобайт без сжатия, вот там какая-то из идей может пригодиться.
Комментарий для LO:
Так что, если будут ещё идеи, буду благодарен, возможно просмотрел что-то.
Комментарий для Евгения Степанищева:
Есть ещё кое-что. Вот ,например, такой код:
_=function(p,b){return new Function(p,b)};
Проще заменить на:
_=Function;
И да, G=n+n+914062108081923[s=’toString’](2); // -2 это уже в порядке исправления самого себя
Комментарий для LO:
Вот это крутотенюшка!
Раз пошла такая пьянка замен, ещё можно заменить window на self :)
Комментарий для Евгения Степанищева:
на top! Ибо да!
Комментарий для Евгения Степанищева:
Да и вообще убрать, это же контекст!
<body onload=«eval(’onkeyup=function(){alert(1)}’)»>
Комментарий для LO:
На top нельзя будет в конкурсе JS1K, а тут можно, точно :)
Не, так не могу. У меня JS в PNG-файле весь, а на конкурсе JS1K нужно будет вообще дать чистый JS, без тегов.
Комментарий для Евгения Степанищева:
Можешь. Если говорить о первой версии правил js1k.com, то там, как видно из представленных работ, чистый код участников помещался в тег <script>, контекстом которого,как и у тега <body>, является window. Это значит, что как в твоём случае, так и в рамках правил конкурса, ты можешь вообще не думать на тему, как получить window. Тем более, что в кодах участников использован этот же подход. Т. е. w.onkeyup=... — плохо, onkeyup=... — хорошо. Вот что Я имею в виду!
И, кстати, в последней «рождественской» версии правил вообще запрещены ВСЕ eval-подобные вызовы, в т.ч. Function и setInterval(String).
Надо бы подбить все указанные выше оптимизации, убрать сжатие png и лишние, как оказалось, переменные. И посчитать чистый js , без html. Просто интересно, сколько там осталось.
Комментарий для LO:
А! Точно :)
Вот чёрт, я там правила не читал. Заразы :)
Впереди праздники, если будет время, попробую.
Комментарий для Евгения Степанищева:
Продолжи, как будет время. Пока 991
http://pastebin.com/tTYhag3h
Комментарий для LO:
Ага. Теперь надо от eval избавиться.
Комментарий для LO:
Вот версия, которая, вроде, укладывается во все требования:
http://bolknote.ru/files/tank-1k-game-2/
HTML без id, JS ровно килобайт.
Комментарий для LO:
1023 байта, переделал на HTML, который на сайте конкурса.
Комментарий для Евгения Степанищева:
Под «рождественские» правила подстраиваться нет смысла, т. к. тематика игры «не та». Разве что сделать так, чтобы танк палил по Дедам Морозам/Санта Клаусам, а не по ракетам...
Комментарий для LO:
Ну ладно, сделал уже :) При необходимости можно вернуть. Зато всё уместил, я там ещё код сократил и несколько замен сделал.
Комментарий для Евгения Степанищева:
Вобщем посмотрел код.
1)
заменить на:
c.style.border=’4px solid #000’
Но на этом можно не останавливаться и убрать ’#000’. Условия запуска сферического коня позволяют это сделать без вреда.
c.style.border=’4px solid’;
2)
Почти то же самое в строке
убираем второй fillStyle — разницы никакой!
fillStyle=«red»;fillRect(0,0,W,W);K=r
3)
Переменная R — лишняя, дает читабельность ценой в 4 байта. Убираем R=function(){...} и там, где K=R:
K=function(){...}
4)
В твоем коде вместо «;» «\n». Заменяем на:
with(a)x,y,z
Экономия 2 байта.
Общий код стал занимать 995 байт. Надеюсь, на Дедов Морозов хватит. Впрочем, цель уже в любом случае достигнута. http://pastebin.com/DhVDhWRg
Ага, ок.
Кроме того, что цифра счёта становится красной после первого же столкновения.
Точно, заменю.
Комментарий для LO:
border добавил, {} около with убрал, спасибо. Рано утром плохо думается. :)
Файл стал занимать 1021 байт.
Комментарий для LO:
И ещё на байт сократил — 1020 байт.
Комментарий для Евгения Степанищева:
Убрал из твоего последнего варианта функции j,B,R. Осталось 977 байт.
http://pastebin.com/ydLjHkWm
Комментарий для LO:
Круто :) Можно будет ещё что-нибудь впихнуть, например, цвет добавить. Надо будет подумать. С наступающим!
Комментарий для LO:
После отказа от Function это точно имеет смысл. Правда, насчёт B не уверен, надо будет померить. Я оказался от второго её вызова, так как он не помещался. Не критично, но танк себя неправильно ведёт в некоторых случаях.
Спасибо за помощь! Если буду выставлять этот код на JS1K, то тебя упомяну неприменно. Только что написать? LO?
Комментарий для LO:
В смысле, раз места хватает, надо будет вернуть все её вызовы на место.
Комментарий для LO:
Заменяем
(g=$.length<4&&r()>.93&&25+8*~~(r()*25))&&$.push([246,g]);K()
на
Kg=$.length<4&&r()>.93&&25+8*~~(r()*25&&$.push([246,g]))
сокращает ещё байт
Комментарий для LO:
С братишкой допёрли ещё до такого:
p.charAt(J)&1
на
+p.charAt(J)
Комментарий для LO:
Ещё:
в P: x=(x+~~y*W)*4;
и в S: y+J/8
Комментарий для LO:
Кажется, братишка меня натолкнул на мысль... Сейчас попробую, должно стать сильно меньше.
Комментарий для LO:
Кажется, получится ещё байт на 40 сократить. Прототип есть уже. Рабочий код сделаю после НГ.
Комментарий для Евгения Степанищева:
Функция B необходима, только если в коде она вызывается более 2-х раз. Инфа 100%.
Пилите, Шура, пилите! :)
Хм... Подождём окончания банкета. Ответ ниже.
Аналогично!
Комментарий для LO:
http://pastebin.com/Jqa2s0ux
937 байт.
Комментарий для Евгения Степанищева:
http://pastebin.com/F3t5fj5M
933
Комментарий для Евгения Степанищева:
http://pastebin.com/jW08FS3j
921
Под Фриске процесс идет особенно замечательно %)
Комментарий для LO:
Ого, про такие вложенные with я не знал. Всегда думал, что они должны «перешибать» друг друга, спасибо!
Комментарий для LO:
Круто!
Комментарий для Евгения Степанищева:
Какой всё-таки отличный язык JS! :) Жаль только есть очень странные ограничения. Когда братишка вчера спросил почему я сдвигом не пользуюсь, когда вывожу графику, я рассказал, что операции сдвига работают только с int, что так я уже пробовал. А потом осенило попробовать делить на два и использовать для этого число с плавающей точкой.
Комментарий для LO:
103 байта! Можно попробовать цвет сделать.
Комментарий для LO:
17853868722516492 → 0x3F6DFFBF12720C
27160417194573408 → 0x607E416AD57E60
Комментарий для LO:
Последний твой — 922, с заменой на hex — 920.
Комментарий для Евгения Степанищева:
922 — это позиция следующего символа, поэтому всё-таки 921 и 919 соответственно. Едем дальше!
Я заменил || на | в одном месте и && на & в нескольких местах, где обе части являются булевыми.
Кроме того, убрал лишнюю группировку в одном месте
В итоге имеем 909 ! Есть ещё идея, сейчас проверим.
http://pastebin.com/JGmEuHQ6
Комментарий для Евгения Степанищева:
Перешибают, если есть конкуренция. Просто в ином случае мы не могли бы вызвать, например, with(document)alert(’метод другого объекта’)
Мне, например, не нравится ограничение 32-мя битами при побитовых операциях. Да и вообще в числах JS пока слаб. Эти все погрешности... Приходится эмулировать 64-битные операции.
Ладно, завтра проверю идейку.
Комментарий для LO:
Я просто смотрю на длину получившегося файла.
Я про это и говорил выше.
Комментарий для LO:
Это понятно. Я не думал, что они образуют каскадные зоны.
Комментарий для LO:
h|x-t<0|x-t>9|b-y<0|b-y>9?0:h=splice(i,1)+(++s%20||++V)
907 байт
Комментарий для LO:
Ага, там перенос был лишний в коде.
906 байт, оказывается. Может pastebin лишний перевод вставил.
Комментарий для LO:
t=min(max(0,t+4),W-8)) → t=min(t+4,W-8)
899 байт
Комментарий для LO:
http://pastebin.com/b63YGP67
888 байт
Комментарий для Евгения Степанищева:
Херю твоё элитное число:
http://pastebin.com/KfWfGshs
872
Изменения коснулись обработки событий. Пытался реализовать onkeydown=onkeyup=... , но в разных браузерах выявлялись свои проблемы.
Ну, а я как бы согласился. ;)
Комментарий для LO:
Я вчера вертел как раз это место :) Только у меня другая идея была, но она не сработала.
Комментарий для LO:
860 байт
onkeydown=onkeyup=function(e){v=u[e.which];w=/u/.test(e.type)
v?v&1?L=!w&&v:U=!w&&v:w||h&&(h=0,t=X+8,b=Y+1)}
Комментарий для Евгения Степанищева:
Отлично! В таком варианте проблем пока не выявил. Теперь можно убрать переменную u:
v={38:-2,40:2,37:-1,39:1}[e.which]
И ещё один малоиспользуемый трюк:
h=splice(i,1)+(++s%20||++V) --> h=splice(i,1)+ ++s%20||++V
Итого: 855
Комментарий для Евгения Степанищева:
Впрочем так тоже можно:
splice(i,1)|++s%20||++V
854
Комментарий для Евгения Степанищева:
http://pastebin.com/kgPpQRMK
849
Еще раз подчистил обработку событий.
Комментарий для LO:
Круто!
Заметил первые глюки. Когда стреляю, пуля иногда проходит сквозь ракету, не причиняя вреда. Видимо, когда я инвертировал условие столкновения с ракетой, где-то ошибся. Посмотрю.
Комментарий для LO:
w=/w/.test(e.type)&&v
v?v&1?L=w:U=w
846
w=e.type.length&2&&v
845
Комментарий для Евгения Степанищева:
Словил ещё один глюк: если до ракеты оставалось расстояние примерно в длину танка, снаряд поражал танк и летел дальше (или выпускался еще один — это непонятно). Описанный тобой глюк возникал, если между снарядом и танком оставалось ещё меньшее расстояние. Мой глюк возник после моих 849, где Я убрал код в обработчике *w||*. Пришлось вернуть, попутно сделав апгрейт.
w=e.type.length&2&&v --> w=!!e.type[6]&&v
http://pastebin.com/t3TBpswq
846
Комментарий для LO:
// поражал танк --> поражал ракету
// между снарядом и танком --> между снарядом и ракетой
Комментарий для LO:
Странно, я вчера так пытался сделать. Проверил в «Опере» javascript:void(alert(«aaa»[0])), словил ошибку. А сегодня работает. Видимо, вчера уже спать хотел, где-то невнимателен был.
c w тут здорово придумано.
Комментарий для LO:
Там где цвет задаётся можно сократить. Там неочевидное место — используется цвет rgb(9,9,9), на практике выглядит как чёрный. Так что можно чёрный и использовать:
y++>>2&&W
845 байт, надо ещё подумать…
Комментарий для LO:
мне убегать надо, но рискну предложить w+h&&(h=0,t=X+8,b=Y+1)
не успеваю тщательно обдумать
842 байта
Комментарий для LO:
Kg=length<4&r()>.93&&25+r()*193)&&push([246,~~g]
840 байт
Комментарий для LO:
Хотя, сдаётся мне, последнее не очень хорошая идея. Первоначально это делалось для того, чтобы по вертикали был шаг, кратный 8. Сейчас его не будет. Лучше так не делать.
Комментарий для LO:
Так что 842.
Комментарий для Евгения Степанищева:
Сделал замены:
1)
x+=~~y*W
for(y=0;y<5;)I.data[x*4+y]=++y&4&&W
2)
for(J=0;J++<56;p/=2)
3) forEach --> map
http://pastebin.com/X6mqKL4p
833
Комментарий для LO:
Круто!
Вот блин, эту замену я сделал, но сейчас вижу, что не написал про неё.
Комментарий для LO:
Убираем with([]), вводим опять $=[]
перед push и length возвращаем $
вместо всего блока map:
$=$.filter(function(v){S(x=--v[0],y=v[1],G)
return!(x<1|x-X>=0&x-X<8&abs(y-Y)<8?V--+(K=function(){fillStyle=’red’
fillRect(0,0,W,W)
fillStyle=’#000’
K=r}):h|x-t<0|x-t>8|b-y>8?0:h=++s%20||++V)})
824
Комментарий для Евгения Степанищева:
Как будет время, выложи, плиз, полный код в этой редакции на pastebin, ибо у меня меньше 824 выходит и, соотв., глюки. Предположительно, что-то пропущено. Но первая мысль уже возникает: зачем убирать with([]), если далее у тебя как минимум 3 обращения к массиву? Считаем:
1) with($=[])$= // 12
2) $=[],$=$.$.$. // 13
Комментарий для LO:
Ок, сейчас попробую перепечатать (я отдыхаю в Казани, разрабатываю на ноуте, который не подключен к инету).
with не сработает, так как одна из операций обращения к массиву — $=$.filter всё портит. Тут создаётся новый объект, который перетирает старый.
Комментарий для LO:
Вот: http://pastebin.com/QZNTZHK3
Комментарий для LO:
{38:-2,40:2,37:-1,39:1}[e.which]
меняем на
{2:-2,3:2,0:-1,1:1}[e.which-37]
823 байта
Комментарий для LO:
[-1,-2,1,2][e.which-37]
Комментарий для LO:
815 байт
Комментарий для Евгения Степанищева:
http://pastebin.com/wz2mgV3w
806
Объединил 4 функции в 2.
Комментарий для Евгения Степанищева:
Выявлен еще один баг: подкатываешь к ракете сзади и стреляешь — ракета уничтожается. Баг появился после версии на 888 http://pastebin.com/b63YGP67
Комментарий для Евгения Степанищева:
http://pastebin.com/PxYBB2Af
803
Завершил объединение 4 функций в 1.
Комментарий для Евгения Степанищева:
точнее там 801
Комментарий для Евгения Степанищева:
Вынес переопределение цвета из P в setInterval и убрал группировку.
http://pastebin.com/3sCzyFms
799
Комментарий для LO:
Сильный ход :)
Он уже исправлен?
Комментарий для LO:
http://pastebin.com/gp50UGBv
797
Комментарий для LO:
http://pastebin.com/RKHm1Yvs
796
баг, вижу, не исправлен. Посмотрю.
Комментарий для LO:
http://pastebin.com/wqRc8xx1
794 и исправлен баг
Комментарий для Евгения Степанищева:
$=[s=t=L=U=0]
793
Комментарий для LO:
Но так в массиве $ в самом начале будет элемент ноль, т. е. массив будет выглядеть так: [0].
Комментарий для LO:
Подумал что будет в этом случае, похоже, filter сразу отфильтрует этот элемент, так что всё ок.
Комментарий для LO:
g=!$[3]&r()>.93&&25+(r()*25<<3)
788
Комментарий для LO:
p-X>=0 на p>=X
786
Комментарий для Евгения Степанищева:
http://pastebin.com/a8c1scT0
781
То же самое нужно сделать с третьим циклом. Чуть позже гляну, если успею.
Комментарий для LO:
У меня есть идея, проверю.
Комментарий для LO:
for(i=V;i;
так плохо — браузер зависает, так как уходит вечный цикл.
Комментарий для LO:
Я убрал это, 784 байта.
Комментарий для LO:
http://pastebin.com/rdhtbnZ9
783
идея не выгорела
Комментарий для LO:
http://pastebin.com/t2jeMFu8
776
Комментарий для LO:
http://pastebin.com/4td8HL5m
773
Жесть, если бы весь софт ТАК писали, мы бы, наверное, до сих пор могли ОС с дискетки грузить...
Комментарий для Евгения Степанищева:
for(J=0;J++<56;p/=2) --> for(J=0;J++<W;p/=2)
772
Тормозов Я не наблюдаю, даже в Safari.
Комментарий для Евгения Степанищева:
h=(t+=4)>251
Нужно подумать, так ли принципиально число 251? Я так понимаю, что на одной чаше 0.07 секунды у пользователя, а на другой 2 байта.
Комментарий для LO:
Вроде особой деградации производительности нет. Если что, позволит увеличить размер спрайта.
Комментарий для LO:
for(J=2;p/=2;J++)
770 байт
Комментарий для LO:
Можно, наверное, поставить W, это координата, когда пуля достигает стены. Но иногда может возникнуть ситуация, когда пуля «вылетит» за стену.
Насколько я знаю CANVAS, он «заворачивает» координаты, то есть при попытке вывести что-то в координату 256 у нас пуля появится слева. Как-то неаккуратно.
Это поведение наблюдается сейчас и у танка, я ещё не правил. Когда-то я ограничение убрал, чтобы в размер влезть.
Надо TODO записать:
1) ввести цвет: танка, стены, ракеты. В качестве цвета стены можно взять «tan» (это имя цвета), что позволит сэкономить байт.
2) сделать ограничение танка, чтобы он не выезжал за стену.
3) что-то сделать с пулей, чтобы она была заметнее (может цвет заменить или сделать, чтобы она переливалась).
4) какое-то подобие уровней. Увеличивать скорость? Количество врагов?
Все 4 пункта в килобайте?
Комментарий для SmallFish:
Конечно.
Комментарий для SmallFish:
Есть целых 254 байта для этого, должно хватить.
Комментарий для Евгения Степанищева:
http://pastebin.com/iRxqjhZm
768
Перенёс всё добрецо в filter.
Особенно понравилось.
Комментарий для Евгения Степанищева:
Наблюдаю такое, только если сам танк вывести за левую границу, чтобы он появился из-за правой границы. Тогда, действительно, пуля пролетает через стену и вылетает из-за левой границы. Но это связано с танком и не зависит от 251 или 255. Иные случаи «пролета» стены Я отловить не могу.
Комментарий для Евгения Степанищева:
У меня чувство, что сам потенциал идеи исчерпан в текущей реализации. Может быть, замахнуться на что-нибудь поражающее воображение? :)
Комментарий для LO:
Это да, мне уже не хочется доделывать, но я доведу до конца, иначе чувства завершённости нет :) А так, да, хочется замахнуться :) Пока, правда, никаких идей на что :)
Комментарий для LO:
Да, у меня тоже не вышло. Тогда меняем 251 на W, будет 766 байт.
Иглуску паламали! АААА!!!111
Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13
длинный прямоугольник без вкусного внутри
Комментарий для SmallFish:
Только что проверил на FF3.6.13,FF4b7 — всё работает. Судя по описанию, у тебя нет на странице объявления переменных, которые даются по условиям «даром» и в подсчете не участвуют (тут смотри http://bolknote.ru/files/tank-1k-game-2/ ). Если причина не в этом — консоль ошибок в студию!
Комментарий для Евгения Степанищева:
http://pastebin.com/KGQ94YiE
761
V--+(K=P) --> K=P , V-- перенёс в P
t>p||p-t>9|y>b||b-y>9 --> t>p|p-t>9|y>b|b-y>9
Комментарий для LO:
Из-за этого возникает баг, когда танк может объехать ракету, выстрелить и она пропадёт.
Комментарий для Евгения Степанищева:
Мда. 763
Комментарий для LO:
У меня почему-то 761. Можешь опубликовать твой текущий код?
Я пробовал заменить создание красного экрана на цикл, получается либо очень медленно (когда цикл пробегает всё заново, 255*255*4 итерации), либо размером больше (если я кеширую цикл).
Комментарий для Евгения Степанищева:
http://pastebin.com/Kd73EY3T
763
Может быть, ты во сне уже что-нибудь заменил? :)
Комментарий для Евгения Степанищева:
Упомяну ещё об одном памятнике на кладбище идей. Пытался вытаскивать имена свойств и методов через цикл for in и трюк с использованием сокращенной версии метода exec в не-IE браузерах ( alert(/xyz/(’xyzzzz’)) ). Не уложился в размеры, но трюк перспективен на больших просторах (5К,10К).
Комментарий для LO:
Нашёл ошибку :) Я куда-то дел «h|». Это породило бы баг, когда ракеты «спотыкались» о то место, где в последний раз была пуля.
Комментарий для LO:
Из-за того, что ты перенёс V-- внутрь вызова, рисующего красный, стало возможным сократить ещё на два байта: http://pastebin.com/gK38C55g
for(i=V;i>0;P(W-i--*10,245,Z=0x3F6DFFBF12720C)) на for(i=V;i;P(W-i--*10,245,Z=0x3F6DFFBF12720C))
и
K(r(V>0&&P(4,3,G=0x607E416AD57E60) на V>0&&K(r(P(4,3,G=0x607E416AD57E60)
761
теперь V не становится отрицательным и браузер не зависает в конце игры
Комментарий для Евгения Степанищева:
V>0&&K --> V&&K
759
Комментарий для Евгения Степанищева:
Наверное, ты это имел в виду.
Комментарий для LO:
Блин, не успел :)
Комментарий для LO:
756 байт:
V&&K(r(P(4,3,G=0x607E416AD57E60)+putImageData(I,0,0)+fillText(s,15,10))>.93&!$[3]&&$.push([246,r()*25<<3]))
меняем на
V&&K(P(4,3,G=0x607E416AD57E60)+putImageData(I,0,0)+fillText(s,15,10))>.93&!$[3]&&$.push([246,r()*25<<3])
Комментарий для Евгения Степанищева:
abs(y-Y)<8
заменяем на
A=y-Y,A*A<64
,что позволяет нам отказаться от with(Math)
http://pastebin.com/RNDaQEmX
753
Комментарий для Евгения Степанищева:
I=createImageData(W,W) -->
I=createImageData(c.height=c.width=W=255,W)
751
Комментарий для Евгения Степанищева:
От последнего предложения придется отказаться, ибо в FF и GC это убирает красную заливку в конце игры.
753
Комментарий для LO:
Круто :)
Комментарий для LO:
Я пытался оптимизировать место с abs, но ни одна идея не прокатила:)
Комментарий для LO:
Меняем P(W-i--*10,245,Z=0x3F6DFFBF12720C) на P(i--*-10,245,Z=0x3F6DFFBF12720C)
Как я уже упоминал, CANVAS «заворачивает» значения (почему-то только по горизонтали, надо почитать спецификацию), которые выходят за пределы холста.
752 байта
Комментарий для LO:
Хе. Так это не CANVAS заворачивает, это реализация «setPixel» ещё даже в моём коде так работает :)
Я надеюсь, мы всё уже выжали из этого кода :)
Комментарий для Евгения Степанищева:
(c) Буба Касторский
Комментарий для Евгения Степанищева:
В такого рода занятиях нужно как минимум неделю подумать, чтобы сказать «дальше некуда».
Комментарий для Евгения Степанищева:
if(x[1])return!(P(p=--x[0],y=25+x[1],G,A=y-Y) на
if(F=x[1])return!(P(p=--x[0],y=25+F,G,A=y-Y)
751
Комментарий для LO:
Очевидная штука, а мы оба пропустили до последнего момента :)
Я вот что подумал, доделывать пункты из TODO я не буду, иначе снова захочется оптимизировать, а у меня уже фана нехватает, превращается в рутину.
Комментарий для LO:
Ты загадку своей личности-то откроешь? :)
Комментарий для Евгения Степанищева:
Так и правильно, Я бы не смог её не пооптимизировать. :)
Мой ник LeverOne, по реальному имени в сети почти никто не знает и слава богу.
Уверен, что момент последний?
Комментарий для LO:
Я в том смысле, что долго оптимизировали всякие тонкие вещи, а очевидная была перед глазами :)
Комментарий для Евгения Степанищева:
Так, ладно, вот версия на 744
http://pastebin.com/Gb9mdjDC
Убран, чёрный цвет у border, т. к. он и так во всех браузерах чёрный, и переформированы условия в функции P.
За темой перестаю пристально следить (желание, время) и откланиваюсь.
Комментарий для LO:
Да, у меня тоже желание уже пропало, хватит :) Спасибо тебе!
Комментарий для LO:
http://pastebin.com/X3kZF6ZL
737
Установка ширины или высоты канваса очищает канвас:
Комментарий для LO:
Попробовал ещё with(c) сделать, но не прокатило: keyup/keydown в этом случае биндятся на CANVAS, несмотря на то, что CANVAS (по крайней мере в «Опере») их не поддерживает. Из-за этого не работает нажатие на клавиши.
И, кстати, вспомнил, в копилку мёртвых идей: пробовал заменить циклы на рекурсивные вызовы, код вырос.
Комментарий для LO:
if(y&&!p) на if(y*!p)
736
Комментарий для Евгения Степанищева:
Теперь первое, что приходит в голову, просто убрать первое «c.width=»
728
Комментарий для LO:
У меня в «Опере» размер некрасиво скачет. Сначала виден первый кадр с неправильными размерами.
Ребят, ну вы даете!
Вдохновляет.
(особенно порадовал JS под бой курантов :) )
Комментарий для Олег:
Может и нас вдохновит на что-то грандиозное :)
Комментарий для Евгения Степанищева:
Если задержка в 0.07 сек существенна, то решается это просто: убираем c.style.border=’4px solid’
за c.width=W (т. е. рисуем рамку после).
Комментарий для Олег:
Тогда 5 мин хватало, чтобы выдернуть из кода чего-нибудь и пойти к своим салатам.
Комментарий для Евгения Степанищева:
вот так это выглядит в общем
http://pastebin.com/rFfeAPNW
728
Комментарий для LO:
Так намного лучше :)
Комментарий для LO:
http://pastebin.com/14pXKTRq
726
передвинул c.width внутрь createImageData
Комментарий для LO:
А… мы же это проходили, это убивает заливку красным в конце игры в некоторых браузерах.
*спс* ребзя, напомнили мне асмовые гонки за байтами )))
вот только не понимаю, баг или фича: вторая пуля не вылетает из танка, пока первая жива
тестирую на Chromium 8.0.552.224 (68599) Ubuntu 10.10
в этом же chromium не работает отсылка комментария по ctrl+enter (
Комментарий для chun lu:
Да уж, помню. Я писал на трёх ассемблерах, на последнем (x86) — несколько лет.
Фича, иначе просто всё будет.
Ого, странно, я использую jQuery, а что за версия?
кстати, подумал
годы назад (на асме) гонки за байтами хоть как-то были оправданы практически--память была дорога, процессорное время тоже
то, что вы делаете сейчас, на javascript, требует как минимум «интерпретатор» скрипта, т. е. в принципе ваши 200 с лишним байт оптимизации никому особой погоды не сыграют
выходит, что, загоняя себя в такие строгие рамки при фантастических возможностях современных обычных настольных компьютеров или айфоней там всяких, вы творите искусство, просто ради искусства
радостно, что можно не брюзжать «как было раньше здато, а ща не здато», ведь появился например js1k
Комментарий для Евгения Степанищева:
Chromium 8.0.552.224 (68599) Ubuntu 10.10
Комментарий для chun lu:
Точно так :) Практической пользы от этого никакой.
Комментарий для chun lu:
В теме выше дана ссылка на превосходную статью неизвестного автора, в которой есть фраза, справедливая для всех времен:
В этом Я и усматриваю практическую пользу для себя: какая-то часть меня создана вместе с частью этой программы.
Комментарий для Евгения Степанищева:
В таком виде — да, но не в таком:
http://pastebin.com/neBx30pY
726
Комментарий для LO:
Точно :)
Комментарий для LO:
http://pastebin.com/WNS9gTb1
723
if(y*!p)for(z=5;z; → for(z=5;y*!p*z;
Комментарий для Евгения Степанищева:
http://pastebin.com/Q2k16LPk
721
Изменения в последней строчке.
Комментарий для Евгения Степанищева:
И, кстати, пройдено знаменательное число — 300 байт от первоначального размера! :D
Комментарий для LO:
Не, так глючит — координаты получаются putImageData(I, 1, 1) и так «режется» перед краем (если до конца влево поехать), замена на ~ несколько улучшает ситуацию (получается putImageData(I, -1, -1)), но тогда танк на пиксель «проваливается» (правда это куда менее заметно), но надо сдвинуть координаты печати текста очков.
Комментарий для Евгения Степанищева:
В процессе теста обнаружил, ещё один глюк, присутствовавший в игре изначально. Заводим танк влево чуть более, чем до башни, и поднимаем до верхней границы, чтобы шасси оставалось едва видимым: результат — текст очков становится красным, игра зависает.
Комментарий для Евгения Степанищева:
Нужно таки сильно приглядываться, чтобы это заметить!
Может быть, тем более, что это экономит ещё 1 байт.
Комментарий для LO:
Ого, надо будет глянуть.
Комментарий для LO:
http://pastebin.com/S97wbMyn
Hotfix ошибки (я решил её саму не искать, а убить два зайца махом — ещё и запретить танку заезжать за границы) + сделал, чтобы при выстреле танк подавался назад, как при отдаче.
761 байт
Комментарий для LO:
Есть классная идея, но сложная. Проверю.
Комментарий для LO:
Да, вполне получается.
В общем, надо заменить все координаты на одну. Из расчёта C=x+y*W
При выборе клавиш будет что-то вроде
v=[-1,-510,1,510][x.which-37],w=!!x.type[6]&&v,v?S=w:…
И вообще всё (кроме расчёта столкновений) сильно упрощается.
Но дописать пока не могу — хочется сегодня выспаться.
Комментарий для Евгения Степанищева:
Класс! Эффект с отдачей на два байта вызывает какую-то детскую радость. :)
Там нужно опять вернуть abs, но подождём окончательной реализации последней идеи.
Комментарий для LO:
Ага, вчера времени не было на это. Всё-таки очень много переделывать нужно.
Комментарий для LO:
Немного отложу. Сейчас сильно занят. Нужно в комнате сделать перестановку мебели. Так что вечера пока заняты.
Комментарий для LO:
Что-то я так и не вернулся к той идее, лень было. Но сейчас немного стряхнул пыль с проекта и сделал следующее:
dhcp-218-158-wifi:Tanks bolk$ diff index.js index.js.old
1c1
< for(i in a)a[i[V=4]]=a[i]
---
6c6
< setInterval(function(){X+=L
---
8c8
< I=a.t(W=255,W)
---
12c12
< y?0:x?(v=[-1,-2,1,2][x.which-37],w=!!x.type[6]&&v,v?v&1?L=w:U=w:w+h&&(h=0,t=X+8,b=Y+1)):a.R(0,!V--,W,W,a.fillStyle=’red’,K=r)})
---
17c17
< V&&K(P(4,3,G=0x607E416AD57E60)+a.m(I,0,0)+a.T(s,15,10))>.93&!$[3]&&$.push([246,r()*25<<3])},70)
---
http://pastebin.com/2y1UJ2Ky
14 байт экономии
Комментарий для Евгения Степанищева:
Восстановил with(a), убрав конфликт имен (замены имен переменных: m --> e, t --> d). Переместил with выше имен глобальных переменных. Повезло, что в контексте «a» нет конфликта с глобальной «c», иначе пришлось бы искать другой индекс.
Экономия целых 3 байта.
// 709
http://pastebin.com/r5xMCUQZ
И Я как-то заблудился средь просек аллейных. Я так понял, ты взял предыдущую версию на 726, тогда как последней бажной была версия на 720. Т. е. еще 6 байт скинуть можно.
Комментарий для LO:
Что-то я не разобрался. А можешь дать ссылку на версию в 720?
Комментарий для Евгения Степанищева:
720
http://pastebin.com/mEZ9keii
Комментарий для LO:
Как разгребусь немного, посмотрю в чём разница. И я сейчас не могу проверять под IE, кстати. У меня ОС сменилась.
Комментарий для Евгения Степанищева:
Строковые индексы работают, начиная с IE 8 standards mode, cаnvas — c IE9. Таким образом, всё отлично работает в IE9. Проверил.
Комментарий для LO:
Ok, спасибо!