<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-244194832140162947</atom:id><lastBuildDate>Wed, 28 Aug 2024 21:40:39 +0000</lastBuildDate><title>No Canvas</title><description>Написать 3D с z-buffer-ом, субпиксельной точностью и освещением по Гуро на javascript используя canvas может каждый.&#xa;А без него - только ненормальные психи :) одним из которых я и являюсь.&#xa;&#xa;Блог посвящён трюкам и эффектам на javascript, не использующим canvas.</description><link>http://nocanvas.blogspot.com/</link><managingEditor>noreply@blogger.com (Restorer)</managingEditor><generator>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-2957959299539033326</guid><pubDate>Wed, 28 Jul 2010 21:10:00 +0000</pubDate><atom:updated>2010-07-29T00:22:37.773+03:00</atom:updated><title>Pool&#39;s closed. Due to AIDS</title><description>&amp;nbsp;Концерт окончен, довольные зрители расходятся по домам.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0009/&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;230&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6XKW8rPd6rnLHsBVXnKDnRqHk58qXkToB_GcedtQE4EmDyRlgwn_gfbzZ7bh26x87RKUMjLOFqGXYfOZuUxWFzbxXigmE_PBmiLKCpszmsyWu9TJxxJNhrZ06_zWkwCqA7ldAk3NR4MFZ/s400/illust.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;На неопрелделённый срок я закрываю проект.&lt;br /&gt;
Причин тому &amp;nbsp;несколько, и основная — банальная нехватка времени.&lt;br /&gt;
Пишу игру под андроид, пишу игру для соцсетей (кстати, на js и без канвы :), работаю в конце концов.&lt;br /&gt;
&lt;br /&gt;
Промежуточные итоги (надеюсь они не станут окончательными):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;срок публикаций выдерживался (изменения были, но я оповещал заранее);&lt;/li&gt;
&lt;li&gt;эффекты были интересными (для меня, по крайней мере);&lt;/li&gt;
&lt;li&gt;обещанную игру так и не сделал (хотя демка была);&lt;/li&gt;
&lt;li&gt;посещаемость довольно низкая (менее 50 юников в сутки), rss читают около 100 человек;&lt;/li&gt;
&lt;li&gt;комментируемость никакая;&lt;/li&gt;
&lt;li&gt;при публикации на хабре посещаемость возрастала до 4к юников, но быстро падала;&lt;/li&gt;
&lt;li&gt;хабравчане демосцену особо не жалуют, комментарии не по теме, активность низкая (кстати, судя по одним и тем же лицам, комментирующим топики связанные с демосценой, прихожу к выводу, что сценеров на хабре три с половиной человека);&lt;/li&gt;
&lt;li&gt;я поднял свой скилл написания блогозаписей (c).&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Всегда ваш restorer/fct^fsb&lt;br /&gt;
&lt;br /&gt;
Если вы ещё не кликнули на картинку, сделайте это. Right now!&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;И специально для милых двачеров - я один из тех 3.5 олдфагов, которые помнят события давних времён.&lt;/span&gt;</description><link>http://nocanvas.blogspot.com/2010/07/pools-closed-due-to-aids.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6XKW8rPd6rnLHsBVXnKDnRqHk58qXkToB_GcedtQE4EmDyRlgwn_gfbzZ7bh26x87RKUMjLOFqGXYfOZuUxWFzbxXigmE_PBmiLKCpszmsyWu9TJxxJNhrZ06_zWkwCqA7ldAk3NR4MFZ/s72-c/illust.png" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-821890973235553074</guid><pubDate>Wed, 16 Jun 2010 18:16:00 +0000</pubDate><atom:updated>2010-06-16T21:16:54.714+03:00</atom:updated><title>Effect X1</title><description>Я тут проходил мимо, и совершенно случайно нашел &lt;a href=&quot;http://nocanvas.zame-dev.org/0008/&quot;&gt;новый эффект&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0008/&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3fEAJ22yEFxgF2r33ODNgrFU98ih27BRzANbZHyVCOJWDZmxV-Hl32BLkbcT_dii3AwZYXiTOyRNhr57END30fF1CxiQTeEh8FpfW4dU02nxSIk10Ien33lw6HRWijhL9VwrZEa2Nhh4/s320/illust.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Я просто оставлю его здесь, ведь можно же? Правда?</description><link>http://nocanvas.blogspot.com/2010/06/effect-x1.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk3fEAJ22yEFxgF2r33ODNgrFU98ih27BRzANbZHyVCOJWDZmxV-Hl32BLkbcT_dii3AwZYXiTOyRNhr57END30fF1CxiQTeEh8FpfW4dU02nxSIk10Ien33lw6HRWijhL9VwrZEa2Nhh4/s72-c/illust.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-2564881998786196488</guid><pubDate>Fri, 21 May 2010 12:58:00 +0000</pubDate><atom:updated>2010-05-21T16:05:39.205+03:00</atom:updated><title>3D №2 или Illustrate! своими руками</title><description>Помните первую запись в этом блоге (ту, которая &quot;&lt;a href=&quot;http://nocanvas.blogspot.com/2010/01/nocanvas-introduction.html&quot;&gt;Да кто угодно сможет это сделать, используя canvas!&lt;/a&gt;&quot;)? Сегодня я представляю вашему вниманию вариант без канвы.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0007/&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1IOx5j7Ysu9ua7uj_liqjQmD9u0CNwxWl9aa2N7vC5KcdliyVFgqOHQ1t4_KKxVwZldrruVKD3z3r5YcG4qUEJG80ZViIqk7ZUOMHzM8L5rHCvb2AunldRj-gSzQu0wEZKr1NU3z-5YKq/s320/illust-1.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Это всего-лишь тестовые наработки, но, тем не менее, они работают (да чего я тут буду расписывать, лучше &lt;a href=&quot;http://nocanvas.zame-dev.org/0007/&quot;&gt;посмотрите сами&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Рисовать полигоны без канвы - просто. Залитые, с градиентом и без.&lt;br /&gt;
Рисовать 3D без канвы - просто. Используя алгоритм художника, например.&lt;br /&gt;
Рисовать 3D с самопересечениями полигонов без канвы - сложно. Потому что &quot;художник&quot; уже не подходит, и необходим z-buffer.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRXlKqQV4xlXT11-I7O3qSA99AKFV6I6ccG2jCJ3A4mj24QpCfgpPgwI56-UZ3cbRr7P-P9WHlcZpWYs0cLWW_L_4V6hgwz6NlUnKcYF9BWYqstnt3Kw6SfQ31GIh5rOpbeGgycCnc3o1I/s1600/illust-4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRXlKqQV4xlXT11-I7O3qSA99AKFV6I6ccG2jCJ3A4mj24QpCfgpPgwI56-UZ3cbRr7P-P9WHlcZpWYs0cLWW_L_4V6hgwz6NlUnKcYF9BWYqstnt3Kw6SfQ31GIh5rOpbeGgycCnc3o1I/s320/illust-4.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
На иллюстрации выше - классическая проблема алгоритма художника. В каком бы порядке не были бы отрисованы полигоны, правильной картинки всё равно не получится.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYFFhR8azvucvg2gbGVjS3OuhhMEcJiIdgCkZTdfFFOyvaDST5qDouHAjJ_7R4xgoI9wxz61AdbdKKtUvQLUyd6MzMkVdAGFK0gKYTpIAempqyZG6goZ5j-fuyjuwOpWh9CnwuEnZxyJit/s1600/illust-5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYFFhR8azvucvg2gbGVjS3OuhhMEcJiIdgCkZTdfFFOyvaDST5qDouHAjJ_7R4xgoI9wxz61AdbdKKtUvQLUyd6MzMkVdAGFK0gKYTpIAempqyZG6goZ5j-fuyjuwOpWh9CnwuEnZxyJit/s320/illust-5.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Однако, если разбить эти полигоны на несколько полигонов поменьше,&amp;nbsp;то проблема исчезает.&lt;br /&gt;
&lt;br /&gt;
Существует несколько замечательных книжек, в которых описываются различные алгоритмы разбиения полигонов. К сожалению, я не читал ни одной из них, поэтому пришлось изобрести велосипед. Велосипед этот без переключателя скоростей, с колёсами &quot;восьмёркой&quot;; но, тем не менее, он едет вперёд.&lt;br /&gt;
&lt;br /&gt;
Как это водится, смотреть лучше всего в Chrome. На втором месте, поднявшись на два пункта, следует Opera. Затем FireFox.&amp;nbsp;В Internet Explorer ... работает (но лучше взять любой другой браузер).&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;К моему сожалению, библиотека Raphael (SVG/VML) не работает в мобильном Chrome (под Android).&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.davidgould.com/Gallery/Images/Cow1.htm&quot;&gt;Illustrate&lt;/a&gt;? Кто сказал &lt;a href=&quot;http://www.davidgould.com/Gallery/Flash/ENSLogo.htm&quot;&gt;Illustrate&lt;/a&gt;?&lt;br /&gt;
&lt;br /&gt;
В отличие от традиционного рендера с использованием z-buffer-а, такой подход позволяет делать разные клёвые штуки, например &lt;a href=&quot;http://nocanvas.zame-dev.org/0007/?cel=1&quot;&gt;такие&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0007/?cel=1&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgt8CfuR-zCum45rcsRJhABqYnW6CgMH43kbIEuBvb4X3oFhVlzKihB17ATZIi8UNWKDyJPFw-Kqjqdu8hf0sFcYHa6Iua8PoES_F8GESfeTU1de5rt-wH5Prujb7hQUqbHEOfj5wiuZaY/s320/illust-2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
или &lt;a href=&quot;http://nocanvas.zame-dev.org/0007/?cel=2&quot;&gt;такие&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0007/?cel=2&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2-3WRMBW6_eTM5iDmB8IabdyBeRCA-JSEbZE3wlOOZzNk3NWTOoVfTU-9igyYXWtgGmb2fljhMWk_JviK16JbcQo4XEPXTvEUBsjPi2H1DfS5maWiWhMVjWkCm10NEFnMqYv6BBo9aHyE/s320/illust-3.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Кстати, если всё-таки прочитаю хоть одну книжку с описанием таких алгоритмов, обещаю переделать рендерер.&lt;br /&gt;
&lt;br /&gt;</description><link>http://nocanvas.blogspot.com/2010/05/3d-2-illustrate.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1IOx5j7Ysu9ua7uj_liqjQmD9u0CNwxWl9aa2N7vC5KcdliyVFgqOHQ1t4_KKxVwZldrruVKD3z3r5YcG4qUEJG80ZViIqk7ZUOMHzM8L5rHCvb2AunldRj-gSzQu0wEZKr1NU3z-5YKq/s72-c/illust-1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-7081463158540693189</guid><pubDate>Tue, 27 Apr 2010 14:24:00 +0000</pubDate><atom:updated>2010-04-27T17:27:40.082+03:00</atom:updated><title>Рисовалка без канвы</title><description>Сегодняшняя запись (кстати, с недельным отставанием от графика) посвящена скорее не техническим аспектам, а человеческим взаимоотношениям.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://sai.detstwo.com/jisdraw/draw.php&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;231&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdOMsfw-5WCDUKSFXuT-zPmrIUSyVryzk47v0QQ3XrW9yKFvqsGt0Y-1Yy6NygE5WSXaGkXfySpG59-HzkBKAIbEtST1jN0eOXRwoYPRVzeiqatPF9-mMqTLSi26VSYoezJq2E0ig1f9-J/s400/jisdraw.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Как обмануть человека, чтоб он остался доволен?&lt;/span&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;Предистория&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Как-то так получилось, но я админю один форум, посвящённый программе для рисования графики Paint Tool SAI (кстати, офигенная штука, на самом деле). И захотелось мне под новый год сделать какой-нибудь эвент. А чём можно порадовать всякого рода художников? Конечно же, маленьким графическим редактором.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Процесс&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Было решено сделать графический редактор на javascript, чтоб люди не заморачивались установкой и запуском. Флэш подошёл бы, конечно, лучше, но я на флэшэ не умею :-P&lt;br /&gt;
&lt;br /&gt;
Доля IE на форуме где-то около 15%, так что игнорить его нельзя.&amp;nbsp;Chome Frame использовать не хотелось, мой патентованный ®™ метод рисования кругов я ещё не придумал, а значит решение очевидно - использовать вектора в виде замечательной библиотеки &lt;a href=&quot;http://raphaeljs.com/&quot;&gt;raphaël&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Проблема стёрки&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Код рисовалки был написан достаточно быстро, и осталось сделать стёрку.&amp;nbsp;Однако, в векторах это не так просто.&amp;nbsp;Если вы когда-нибудь рисовали во флэшэ, вы знаете о чём я; остальных прошу взглянуть на картинку ниже:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqDmUWOKISPCz7_ckEw1ASaKOF8TCJJomVcirXWhkoDZhTipI3vkSiF9c9vLMVF8ToEkMYawZZvpdHpUl3I2h9bhywadMtkyd_QHkmqwuxEZ_I5rNXwPmYlHUug9nuxzKZO7JXGJzvJ1y_/s1600/vector-eraser.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqDmUWOKISPCz7_ckEw1ASaKOF8TCJJomVcirXWhkoDZhTipI3vkSiF9c9vLMVF8ToEkMYawZZvpdHpUl3I2h9bhywadMtkyd_QHkmqwuxEZ_I5rNXwPmYlHUug9nuxzKZO7JXGJzvJ1y_/s400/vector-eraser.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Скажем так... Несколько неожиданно получить скруглённые края после стёрки.&lt;br /&gt;
Так как в мои планы не входило написание полноценного векторного редактора с 2D полигонами и булевыми операциями над ними, я решил проблему проще.&lt;br /&gt;
&lt;br /&gt;
Как-то давно, когда Riva TNT 2 была ещё неплохой видеокартой, попалась мне на глаза игра &lt;a href=&quot;http://www.elizium.nu/scripts/lemmings/&quot;&gt;Lemmings на javascript&lt;/a&gt;. Так как в то время о канвасе только ходили слухи, то меня невероятно заинтересовало как это они (авторы игры) умудряются стирать части картинки на javascript.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Решение&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Всё оказалось гениально просто - вместо того, чтобы стирать части картинки, они дорисовывали поверх неё чёрные дырки.&lt;br /&gt;
Этот же метод применил и я, только стёрка рисует белым цветом.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;На закуску&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Касаясь конкретно графических редакторов, мы получаем ряд существенных ограничений при использовании этого метода (например, нельзя использовать слои), однако пробуя применять нестандартные подходы в других областях (и не только программирования), можно добиться весьма впечатляющих результатов.&lt;br /&gt;
&lt;br /&gt;
Код не сжат, и весьма прост (&lt;a href=&quot;http://sai.detstwo.com/jisdraw/js/main.js&quot;&gt;скачайте его&lt;/a&gt;, если есть желание).</description><link>http://nocanvas.blogspot.com/2010/04/blog-post.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdOMsfw-5WCDUKSFXuT-zPmrIUSyVryzk47v0QQ3XrW9yKFvqsGt0Y-1Yy6NygE5WSXaGkXfySpG59-HzkBKAIbEtST1jN0eOXRwoYPRVzeiqatPF9-mMqTLSi26VSYoezJq2E0ig1f9-J/s72-c/jisdraw.png" height="72" width="72"/><thr:total>5</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-6833922257141433945</guid><pubDate>Wed, 24 Mar 2010 14:19:00 +0000</pubDate><atom:updated>2010-03-26T15:27:54.987+02:00</atom:updated><title>Dangerous</title><description>&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Здравствуйте&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Этот пост особенный - ведь прошло уже два месяца с момента публикации первой записи.&lt;br /&gt;
Как и обещалось, сегодня я презентую демо версию игры (тут я немного слукавил - это больше похоже на техническую демку движка).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0005/&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiTzkakgSH4PUMZj4y_I5Qrk0_ndYqydeGZeKQtXT5EuM2mOUZ3gu10pulPyLlz8VjHPyUmJh1qdQp2BB27_IxkAs8-bbyEZ9WsXCLeLPl7VvDBb6OUWaDb-66IlIZrdL94LQBq0GcsBeN/s320/illust.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Игра называется Dangerous (что как бы &lt;a href=&quot;http://en.wikipedia.org/wiki/Elite_(video_game)&quot;&gt;намекает&lt;/a&gt;). Если вы ещё не посмотрели на эффект, обязательно &lt;a href=&quot;http://nocanvas.zame-dev.org/0005/&quot;&gt;сделайте это&lt;/a&gt;&amp;nbsp;(для просмотра настоятельно рекомендуется Google Chrome), ведь в этом движке нашли применение почти все no-canvas технологии, про которые я уже успел написать в блоге.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;No Canvas&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Stars Sky - обычные div-ы размером 1x1 px.&lt;br /&gt;
Planets - мой метод &lt;a href=&quot;http://nocanvas.blogspot.com/2010/02/nocanvas-universe.html&quot;&gt;рисования кругов без канваса&lt;/a&gt;™&lt;br /&gt;
Polygons - &lt;a href=&quot;http://www.uselesspickles.com/triangles/demo.html&quot;&gt;http://www.uselesspickles.com/triangles/demo.html&lt;/a&gt; (не позволяет рисовать треугольники с освещением по гуро или текстурами, но зато генерит очень мало DOM элементов).&lt;br /&gt;
Cross - прицел нарисован так же, как и звёздное небо, обычными дивами.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;JavaScript&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Изначально я хотел использовать jQuery для доступа к DOM элементам, но решил попробовать &lt;a href=&quot;http://yass.webo.in/&quot;&gt;Yet Another cSS selector&lt;/a&gt; (или сокращённо - yass).&lt;br /&gt;
В результате оказалось, что ни jQuery, ни yass мне на самом деле не нужны :), но в yass я нашёл управление зависимостями файлов искаропки, так что решил оставить.&lt;br /&gt;
Честно говоря сделано оно несколько странно, но чтобы не изобретать ненужный для моих целей велосипед, я решил пока оставить yass.&lt;br /&gt;
&lt;br /&gt;
В очередной раз я использую кастомную функцию random, чтобы была возможность на лету генерировать целые вселенные (как в оригинальной Elite).&lt;br /&gt;
&lt;br /&gt;
Так же, в этот раз я решил изменить своим принципам, и добавлять методы в объекты через прототипы (обычно я добавляю методы в конструкторе, что даёт возможность использовать &quot;множественное наследование&quot;).&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Math&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Теперь о вещах, ни с канвой, ни с её отсутствием, ни даже с javascript никак не связанных.&lt;br /&gt;
Поговорим о математике.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Matrix&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Повороты и движение выполняются с помощью привычной матрицы 4x3 (обычно используется матрица 4x4, но так как последний ряд всегда равен [0 0 0 1], его можно опустить).&lt;br /&gt;
Попробуем вывести объект.&lt;br /&gt;
&lt;br /&gt;
1) Объект надо повернуть (матрица OBJROT)&lt;br /&gt;
2) Перенести в координаты где он находится (матрица OBJMOV)&lt;br /&gt;
3) Перенести относительно камеры (матрица CAMMOV)&lt;br /&gt;
4) Повернуть относительно камеры (матрица CAMROT)&lt;br /&gt;
&lt;br /&gt;
Даже если шаги 2 и 3 слить и сделать без матриц, всё равно потребуется 18 умножений на точку.&lt;br /&gt;
Значит для 20 объектов о 6-ти вершинах каждый (а именно столько таких объектов используется в качестве &quot;космического мусора&quot;) потребуется 20*6*18 = 2160 умножений.&lt;br /&gt;
&lt;br /&gt;
Однако, можно заметить, что&lt;br /&gt;
&lt;br /&gt;
(CAMROT * (CAMMOV * (OBJMOV * (OBJROT * point)))) =&lt;br /&gt;
(CAMROT * (CAMMOV * (OBJMOV * OBJROT))) * point =&lt;br /&gt;
((CAMROT * CAMMOV) * (OBJMOV * OBJROT)) * point&lt;br /&gt;
&lt;br /&gt;
Итого требуется:&lt;br /&gt;
&lt;br /&gt;
1) Единоразово выполнить умножение 2х матриц камеры (36 умножений)&lt;br /&gt;
2) Для каждого объекта выполнить умножение 3х матриц (72 умножения)&lt;br /&gt;
3) Для каждой точки объекта выполнить всего 9 умножений&lt;br /&gt;
&lt;br /&gt;
Учитывая что на втором шаге одни из умножаемых мартиц - это матрица движения на матрицу поворота, его можно оптимизировать, выкинув ненужные умножения (в результате получим 36 умножений на 2м шаге).&lt;br /&gt;
&lt;br /&gt;
Для тех же объектов потребуется выполнить всего 36 + ((36 + 9*6) * 20) = 1836 умножений, то есть на 324 умножения меньше. Причём с ростом числа объектов и числа вершин в них, разница будет расти.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Quaternion&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Для управления кораблём задействуем ту же систему, что и в Elite - корабль можно вращать (roll) и поднимать/опускать (pitch).&lt;br /&gt;
Если пробовать его крутить по обычным осям (X/Y, X/Z, Y/Z) или даже по всем трём (что явно лишнее), через пару секунд управления становится непонятно что вообще происходит, и как нажатые кнопки влияют на ориентацию корабля в пространстве.&lt;br /&gt;
&lt;br /&gt;
Чтобы избежать таких проблем, использоют кватернионы&amp;nbsp;(&lt;a href=&quot;http://www.gamedev.ru/articles/?id=30129&quot;&gt;что это?&lt;/a&gt;, &lt;a href=&quot;http://ru.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D1%82%D0%B5%D1%80%D0%BD%D0%B8%D0%BE%D0%BD&quot;&gt;вики&lt;/a&gt;). Так как мне совершенно не нравилась перспектива преобразования кватерниона в матрицу поворота самостоятельно (тем более что раньше я такого никогда не делал), на просторах интернета была найдена &lt;a href=&quot;http://www.oolite.org/&quot;&gt;Oolite&lt;/a&gt; - open source реализация elite-подобной игры на Objective C.&lt;br /&gt;
Оттуда, кроме формул для матрицы поворота, я получил ещё и базисные вектора для нового пространства (или не пространства? в универе я совсем забивал на матан), которые помогут сделать движение вперёд/назад.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Hacks&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Как сделать чтоб звёздное небо крутилось и двигалось вместе с планетами и объектами, но чтоб не генерить его на всю вселенную?&lt;br /&gt;
Сначала подвинем его относительно камеры, затем вернём вылетевшие точки внутрь блока и только потом повернём их.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkQPu77IGLYhyBIlaBe6eBitjepjNgdUs2BAyUAlZFhkIwjCWMyFQ0MaRsQzfBwaPa1NcHcSO88mxfam0rmcfRRm3Zw-X-TDInxHpecthYh5zv7K7Esbbuwi2Bx74ubvtg19wprl5YR5N2/s1600/illust2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkQPu77IGLYhyBIlaBe6eBitjepjNgdUs2BAyUAlZFhkIwjCWMyFQ0MaRsQzfBwaPa1NcHcSO88mxfam0rmcfRRm3Zw-X-TDInxHpecthYh5zv7K7Esbbuwi2Bx74ubvtg19wprl5YR5N2/s320/illust2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Code&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Несколько комментариев к коду (&lt;a href=&quot;http://nocanvas.zame-dev.org/0005/dangerous-engine.tar.gz&quot;&gt;скачайте его&lt;/a&gt;&amp;nbsp;прямо сейчас) в стиле javadoc:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;main&lt;/b&gt; - загрузчик&lt;br /&gt;
&lt;b&gt;common.* &lt;/b&gt;- разные полезняшки, привычные рубисту&lt;br /&gt;
&lt;b&gt;dg&lt;/b&gt; - игровой менеджер. клей для остальных частей&lt;br /&gt;
&lt;b&gt;dg.rotatematrix&lt;/b&gt; - матрица поворота и операции над ней&lt;br /&gt;
&lt;b&gt;dg.quat&lt;/b&gt; - квартернион и операции над ним&lt;br /&gt;
&lt;b&gt;dg.camera&lt;/b&gt; - по сути прокси к RotateMatrix и Quat&lt;br /&gt;
&lt;b&gt;dg.viewport&lt;/b&gt; - явный представитель антипаттерна God Object - отсекает невидимые точки, расчитывает коеффициенты для проецирования, рисует точки, круги и треугольники&lt;br /&gt;
&lt;b&gt;dg.point&lt;/b&gt; - точка в 3D либо вершина объекта&lt;br /&gt;
&lt;b&gt;dg.objectslist&lt;/b&gt; - позволяет производить операции над списком объектов (точки, планеты либо полигональные объекты)&lt;br /&gt;
&lt;b&gt;dg.starssky&lt;/b&gt; - звёздное небо&lt;br /&gt;
&lt;b&gt;dg.planet&lt;/b&gt; - планеты и связанные с ними формулы&lt;br /&gt;
&lt;b&gt;dg.planetslist&lt;/b&gt; - прокси к objectslist + некоторые кастомные функции&lt;br /&gt;
&lt;b&gt;dg.object3d&lt;/b&gt; - полигональные объекты&lt;br /&gt;
&lt;b&gt;dg.objects3dlist&lt;/b&gt; - операции над списком 3D объектов&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;P.S.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Радио &quot;Космический блюз&quot; желает вам удачных полётов и передаёт сводку последних новостей: на некоторое время (небольшое) изменяется переодичность постов - вместо двух постов в месяц (аки одного в две недели) будет один пост в месяц. У меня внезапно появились срочные и долговременные дела, и дабы не писать шило вместо нормальных постов я решил увеличить промежутки межну ними.&lt;br /&gt;
&lt;br /&gt;
Ещё раз - удачных полётов.</description><link>http://nocanvas.blogspot.com/2010/03/dangerous.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiTzkakgSH4PUMZj4y_I5Qrk0_ndYqydeGZeKQtXT5EuM2mOUZ3gu10pulPyLlz8VjHPyUmJh1qdQp2BB27_IxkAs8-bbyEZ9WsXCLeLPl7VvDBb6OUWaDb-66IlIZrdL94LQBq0GcsBeN/s72-c/illust.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-1202209812978915523</guid><pubDate>Wed, 10 Mar 2010 17:52:00 +0000</pubDate><atom:updated>2010-03-10T23:50:43.691+02:00</atom:updated><title>Sinclair ZX80 Emulator</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0004/&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJAfuUJx2M069er28xbW0uqKZFfPZ913_Dmnx8CbxtbD68t1O7MYhwyJgWHqU7IdJ7xvWHtENWXNwrGMjzekP70IxfcyYb7kNO-RPGOP7LZlH6N5AgLMWwRj3HewLvhpUANtpMXFjanekF/s320/illust.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Здравствуйте тчк маньяк ретрофил в лице меня телеграфирует о новом эффекте тчк&lt;br /&gt;
&lt;br /&gt;
Телеграмма&lt;br /&gt;
----------
&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
Сегодня я хочу рассказать, как с помощью самых современных техноголий можно создать маленькую машину времени, которая отправит нас обратно в 80-е.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Ведь именно в 80х, небезызвестной фирмой Sinclair Research (в то время ещё Science of Cambridge Ltd.) был произведён компьютер Sinclair ZX80 (фотография -&amp;nbsp;Daniel Ryde, Skövde 2004-08-31):&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/2/24/ZX80.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;252&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/2/24/ZX80.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
По сравнению с&amp;nbsp;ZX81 или&amp;nbsp;ZX-Spectrum, ZX80 не пользовался особой популярностью (что не помешало продать более 50 000 экземпляров).&amp;nbsp;Столь высокие (на то время) продажи, очевидно, обусловлены низкой ценой компьютера (менее $200).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
В ZX80 использовалось около 20 микросхем, 4 из корорых - ОЗУ (2 штуки), ПЗУ и процессор. В отличии от следующих моделей (ZX81 и Spectrum), не использовалось никаких ПЛМ (&lt;a href=&quot;http://en.wikipedia.org/wiki/Uncommitted_Logic_Array&quot;&gt;ULA&lt;/a&gt;), а только простые, доступные микросхемы.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
В компьютере, по сути, не было никакого видеоконтроллера, и изображение формировалось специальной подпрограммой в ПЗУ.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Благодаря этой &quot;особенности&quot;, изображение было не всё время, а только когда компьютер ничем не занят. Если же исполнялась программа, то изображение пропадало (да оно пропадало даже при наборе текста! Если бы у меня был реальный ZX80, меня бы это жутко бесило).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;JavaScript&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Javascript-а на ZX80 не было :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Вдохновлённый эмулятором &lt;a href=&quot;http://benfirshman.com/projects/jsnes/&quot;&gt;NES&lt;/a&gt; и &lt;a href=&quot;http://jsspeccy.zxdemo.org/&quot;&gt;ZX-Spectrum 48&lt;/a&gt; на javascript, я решил сделать &lt;a href=&quot;http://nocanvas.zame-dev.org/0004/&quot;&gt;эмулятор Sinclair ZX80&lt;/a&gt;.&amp;nbsp;Так как ZX80 предельно прост, то компонентов всего два - эмулятор Z80 и эмулятор компьютера.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;zame-js-z80&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
У меня уже было ядро Z80, написанное для моего нового эмулятора ZX-Spectrum. Правда, у него был один большой недостаток - оно написано на C :) , но через несколько часов беспрерывной работы, я получил вариант на javascript.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Так как javascript гораздо медленнее, чем компилированный код на C, пришлось узнать много нового о внутреннем представлении чисел в javascript, и освежить в памяти приоритеты операторов.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Я был очень рад тому, что [ -1 &amp;amp; 0xFF = 0xFF ]. Это позволило упростить выражения вида [ (a - b + &amp;nbsp;0x100) &amp;amp; 0xFF ] до [ (a - b) &amp;amp; 0xFF ]&lt;/div&gt;
&lt;div&gt;
(эх, а на C всего лишь [ (uint_8)(a - b) ])&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Не менее рад я был тому, что [ a + b &amp;amp; 0xFF = (a + b) &amp;amp; 0xFF ], это позволило убрать много ненужных скобочек (я не уверен, что все JS движки способны убирать лишние скобки на этапе компиляции)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Затем я прогнал код через пост-процессор, который используя всю мощь регэкспов, заменил всё что можно посчитать заранее, на готовые значения (например, 0x80 | 0x01 -&amp;gt; 0x81), ведь я ещё менее уверен, что все JS движки способны производить такие оптимизации.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
И наконец, я более чем уверен, что JS движки не будут оптимизировать код вида:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;var a = 2;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;alert(a + 1);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
до&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;alert(3)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
(хотя, кажется, Google closure compiler это умеет), так что в критичных местах все переменные, которые не меняют своего значения, были заменени просто цифрами.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;js-zx8x&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Эмулятор самого компьютера прост как топор. Единственное, что пришлось сделать, так это чтобы нажатая кнопка оставалась нажатой некоторое время, даже если её отпустили (o_O), так как обычный жалкий кусок мяса успевает отпустить кнопку быстрее, чем код в ПЗУ ZX80 на неё отреагировать.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;NoCanvas&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
И самое главное, как вывести изображение без канваса?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
На самом деле очень просто - экран в ZX80 текстовый, так что при большом желании, можно выводить изображение хоть в textarea :) , однако, технология CSS-Sprites позволяет достить гораздо &lt;a href=&quot;http://nocanvas.zame-dev.org/0004/zx80f.gif&quot;&gt;большего реализма&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;P.S.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
В хроме работает на отличненько, кушает от 30% до 50% процессора.&lt;/div&gt;
&lt;div&gt;
В опере тоже достаточно хорошо (а говорят, что в новой версии оперы совсем летать всё будет).&lt;/div&gt;
&lt;div&gt;
В файрфоксе заметно притормаживает.&lt;/div&gt;
&lt;div&gt;
В IE... работает.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Так как я никогда не видел ZX80 вживую, то не могу сказать насколько скорость эмуляции соответствует реальности. По сравнению с другими эмуляторами (теми что я смог найти под Linux), работает быстрее чем положено.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Manual&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
На случай если вы никогда не имели дела с ZX80, ZX81 или ZX-Spectrum, даю инструкцию по запуску единственной игры для ZX80, которую мне удалось найти (для ZX81 их гораздо больше, а уж под спектрум так совсем уйма);&lt;br /&gt;
&lt;br /&gt;
1) После загрузки страницы, дождитесь появления буквы K на чёрном фоне у углу эмулятора.&lt;br /&gt;
2) Нажмите кнопку &quot;Load game&quot; (справа от эмулятора), появится листинг&amp;nbsp;программы&lt;br /&gt;
3) Нажмите на кнопку R - должно напечататься RUN&lt;br /&gt;
4) Нажмите на ENTER и ожидайте инициализации игры&lt;br /&gt;
&lt;br /&gt;
В самой игре:&amp;nbsp;6 - влево, 8 - вправо, 0 - стрелять.&lt;br /&gt;
Удачного спасения земли от космических пришельцев :)&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Links&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Поностальгировать - &lt;a href=&quot;http://nocanvas.zame-dev.org/0004/&quot;&gt;http://nocanvas.zame-dev.org/0004/&lt;/a&gt;&lt;br /&gt;
Сорсы - &lt;a href=&quot;http://nocanvas.zame-dev.org/0004/js-zx8x-src.tar.gz&quot;&gt;http://nocanvas.zame-dev.org/0004/js-zx8x-src.tar.gz&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #cccccc;&quot;&gt;P.P.S.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #cccccc;&quot;&gt;Выверять текст и дописывать мелочи буду завтра.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</description><link>http://nocanvas.blogspot.com/2010/03/sinclair-zx80-emulator.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJAfuUJx2M069er28xbW0uqKZFfPZ913_Dmnx8CbxtbD68t1O7MYhwyJgWHqU7IdJ7xvWHtENWXNwrGMjzekP70IxfcyYb7kNO-RPGOP7LZlH6N5AgLMWwRj3HewLvhpUANtpMXFjanekF/s72-c/illust.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-5095877480535895018</guid><pubDate>Wed, 24 Feb 2010 08:37:00 +0000</pubDate><atom:updated>2010-02-24T22:58:34.298+02:00</atom:updated><title>NoCanvas Universe</title><description>Абсолютно бесполезные эффекты с выдуманными ограничениями? Это всё моё, родное :)&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0003/&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;246&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV-jC2h2j7Sw1TDq4FxM-7xMKFoEzz3VBYLBfKhCf9DBZ4xMTOD1r2l_ZxvP4z-PxTy2Md8N966Yta-z-62DY6dcQHxvR1Weyxr1xLKQQ_s5CrIM88v62rhan2lvbP5kGN0LK73iWPrtUN/s400/illust.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
Посмотрев на картинку для привлечения внимания, и, возможно, на &lt;a href=&quot;http://nocanvas.zame-dev.org/0003/&quot;&gt;эффект&lt;/a&gt;, вы наверняка захотите узнать, что вы должны были увидеть вместо этого, почему у меня не получилось реализовать задуманное, и как был найден выход из безвыходной ситуации.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Интро&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Увидев на хабре ссылку на &lt;a href=&quot;http://9elements.com/io/projects/html5/canvas/&quot;&gt;замечательный эффект&lt;/a&gt;, и посмотрев его, мне сразу захотелось повторить его без канваса, благо эффект достаточно простой, и очень красиво смотрится. Достаточно было найти как рисовать круги без канвы, и эффект, можно сказать, готов.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Решение&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Использование векторов отметалось как неспортивное (несмотря на полную кроссбраузерность); &lt;b&gt;border-radius&lt;/b&gt; очень многообещающая вещь, но, любимый всеми обозреватель интернета (любой версии), не поддерживает это свойство. Картинки с разноцветными кругами?&lt;br /&gt;
&lt;br /&gt;
Решение было случайно, когда мне на глаза попалась &lt;a href=&quot;http://en.wikipedia.org/wiki/Unicode_Geometric_Shapes&quot;&gt;статья о юникодных символах&lt;/a&gt; в википедии - можно рисовать круги символами ● (0x25CF) разных размеров (&lt;a href=&quot;http://nocanvas.zame-dev.org/0003/test.html&quot;&gt;прототип эффекта&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Облом&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Генерируем несколько десятков кругов, вешаем на них эффект изменения размера (радиус круга уменьшается до некоторого предела, потом увеличивается по рандому) и получаем самый настоящий облом. Даже попробовал всё это вставить в код 9elements — &lt;a href=&quot;http://nocanvas.zame-dev.org/0003/food.html&quot;&gt;всё равно ерунда получается&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
При небольшом изменении радиуса, круги начинают противно дрожать, убивая всю созерцательность эффекта напрочь. Я более двух дней пытался найти решение - ставил различные шрифты (желательно те, которые есть и под windows, и под linux), менял формулы, узнал о &quot;ex&quot; в css; ничего не помогало.&lt;br /&gt;
&lt;br /&gt;
Нужно было срочно искать другой эффект или...&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Решение&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Нужно было модифицировать это так, чтоб дрожание шло на пользу (или, хотя бы, не мешало).&lt;br /&gt;
&lt;br /&gt;
После небольшого брейнсторминга, эффект был переделан, и получилась вращающаяся вселенная.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Технические моменты&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Для придания большего &quot;реализма&quot;, планеты делятся на мелкие и крупные, а в центр добавлен оранжевый круг (видимо, символизирующий солнце).&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы вселенная оставалась одной и той же при каждом запуске, штатный Math.random был заменен на первый попавшийся в гугле (но, зато, позволяющий выставить начальный seed).&lt;br /&gt;
&lt;br /&gt;
В этом эффекте опера рвёт файрфокс (визуально), но всё равно, хром быстрее всех (IE6 в виртуалбоксе перестаёт двигаться уже при 20 планетах).&lt;/div&gt;</description><link>http://nocanvas.blogspot.com/2010/02/nocanvas-universe.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV-jC2h2j7Sw1TDq4FxM-7xMKFoEzz3VBYLBfKhCf9DBZ4xMTOD1r2l_ZxvP4z-PxTy2Md8N966Yta-z-62DY6dcQHxvR1Weyxr1xLKQQ_s5CrIM88v62rhan2lvbP5kGN0LK73iWPrtUN/s72-c/illust.png" height="72" width="72"/><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-175080457933819759</guid><pubDate>Wed, 10 Feb 2010 11:11:00 +0000</pubDate><atom:updated>2010-02-10T13:11:54.833+02:00</atom:updated><title>Gouraud shading без канваса</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0002/&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSx0s6shkO7CghJXB2ocVKjgJkFzgG5ZMgUvQmjMJoxZOPyCaV-MT2Z7vM0zlOpDjHfwIuTeznqB8133eNIbFj2PPqy3Uw4etUerUQvalMGsdH3MJQ-pkV13RZC7IB5Q5Ic5msCmx9QRgC/s1600/illust.png&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Начну
я, пожалуй, с картинки для привлечения
внимания.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;a href=&quot;http://nocanvas.zame-dev.org/0002/&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Смотреть&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;,
конечно же, лучше всего — в хроме. Fx, IE7
и IE8 ведут себя удовлетворительно, но
всё же медленнее хрома (поэтому
«квадратичность» эффекта увеличена);
в опере ощутимо подтормаживает;  ну а
про IE6 и говорить не приходится — странные
артефакты в течении секунд 10-15 и тормоза.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Сначала,
как обычно, немного теории.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;В
отличие от &lt;/span&gt;&lt;a href=&quot;http://nocanvas.blogspot.com/2010/01/nocanvas-introduction.html&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;нулевого эффекта&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt; (тот, который
с канвасом) тут я использовал честные
полигоны, а не треугольники — так как
интерполяция значения освещения по
грани происходит без учёта перспективы,
то эффект теряет немного «глянца» (такая
же проблема есть и с аффинным
текстурированием). С 4х-гранниками такого
не происходит.&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3ZgO_r6WnCjUkVtbeBSn1UD7BVmh8LQswhQf5hMP6gjtgFnJWs1gobNxGivQIFjopfKkAarahExOoYzwntLmQ2xA_lylEiuT8MvlsTmuSIGR8oQPVvWSaT8DcXX6L7_HF874Z4b6_Wdrn/s1600-h/illust2.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3ZgO_r6WnCjUkVtbeBSn1UD7BVmh8LQswhQf5hMP6gjtgFnJWs1gobNxGivQIFjopfKkAarahExOoYzwntLmQ2xA_lylEiuT8MvlsTmuSIGR8oQPVvWSaT8DcXX6L7_HF874Z4b6_Wdrn/s1600/illust2.png&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Отрисовка
полигона происходит с помощью технологии
&lt;/span&gt;&lt;span lang=&quot;en-US&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;scanlines&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;: цикл проходит от
самого верха до самого низа полигона,
рассчитывая горизонтальные координаты
отрезка и интерполируя значение
освещённости на его концах. Таким методом
можно рисовать только выпуклые полигоны,
однако я бы посмотрел на того, кто будет
использовать не выпуклые полигоны для
3D графики :)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Так
как без канваса теряется возможность
рисовать линии по точкам, то и возможность
использовать z-buffer тоже отсутствует.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Заведомо
невидимые полигоны отсекаются используя
нормаль (если нормаль смотрит от камеры,
то полигон заведомо не виден). Есть,
правда, один тонкий момент — так как
используется перспективная проекция,
то возможны случаи, когда нормаль у
полигона в порядке, но его будет
перекрывать другой полигон.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2xU75WZk1VVmgaIUBtrNk_cHJz0_TS_Bab9rcliLS_44GXEJ1MQcUgjJZFGaIXlwBjoEBZVSvc4Tw_KsjT1TPHTNxcg4_3gDbH8iBIjKFqeIbzcBPf6hZCN5lMAjJDD2fSeEs8YRoIE53/s1600-h/illust1.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2xU75WZk1VVmgaIUBtrNk_cHJz0_TS_Bab9rcliLS_44GXEJ1MQcUgjJZFGaIXlwBjoEBZVSvc4Tw_KsjT1TPHTNxcg4_3gDbH8iBIjKFqeIbzcBPf6hZCN5lMAjJDD2fSeEs8YRoIE53/s1600/illust1.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
В
этом случае, поможет алгоритм художника
— достаточно рисовать полигоны с самого
дальнего, а те что ближе, перекроют его
в случае необходимости. В общем случае, алгоритм художника даёт весьма
посредственные результаты, но для
вращающегося кубика его хватает за
глаза.&lt;/div&gt;
&lt;div style=&quot;clear: both;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Javascript
&amp;amp; no canvas&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Осталось
только научить браузер рисовать линии
с градиентом.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Была
у меня, честно говоря, крамольная мысль
использовать для этого SVG и VML, но я её
отверг — слишком просто. А потому я
модифицировал метод применённый в &lt;a href=&quot;http://nocanvas.blogspot.com/2010/02/wolf-3d.html&quot;&gt;Wolf 3D&lt;/a&gt; — картинка внутри дива.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuI-zORLQYT7-suE8w09CpKlTTdhNmkCy9-FdX_I5e_4hkz1G3IJSPOMyE7uh7UhyuLjQQeTEtnWe5W4gcSOxDKrmHdh0RrFoYncKNFT4VImqXJXaFjvU30XJ598oYRiXtKpA06MXCYPzt/s1600-h/illust3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuI-zORLQYT7-suE8w09CpKlTTdhNmkCy9-FdX_I5e_4hkz1G3IJSPOMyE7uh7UhyuLjQQeTEtnWe5W4gcSOxDKrmHdh0RrFoYncKNFT4VImqXJXaFjvU30XJ598oYRiXtKpA06MXCYPzt/s1600/illust3.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Используются
2 картинки — одна с красным градиентом,
вторая с синим. Градиент идёт сначала
от чёрного к максимуму цвета, затем
наоборот — это для случая, когда
освещённость на левом конце отрезка
выше, чем на правом.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Технические
моменты&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Код
находится в обычном для него месте:
&lt;a href=&quot;http://nocanvas.zame-dev.org/0002/main.js&quot;&gt;http://nocanvas.zame-dev.org/0002/main.js&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Чтобы
правильно выводить почти одноцветные
отрезки (освещённость левого и правого
края отрезка различается мало либо равна), максимальная ширина картинки
увеличена до 35000 пикселей (в &lt;a href=&quot;http://nocanvas.blogspot.com/2010/02/wolf-3d.html&quot;&gt;Wolf 3D&lt;/a&gt; — 2048).&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;Изначально
для каждого кадра генерировался html код
и вставлялся во вьюпорт через &lt;b&gt;innerHTML&lt;/b&gt;,
однако браузеры каждые секунд 5-10
подтормаживали — видимо происходила
сборка мусора; и метод пришлось изменить.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;При
старте заполняются два списка элементов
— с красными градиентами и с синими. В
процессе отрисовки линии, элементу
просто присваиваются новые стили
(памятуя статью на хабре про работу
браузеров с DOM деревом, обновление стилей
выполняется пачкой через &lt;b&gt;cssText&lt;/b&gt;, а не
классическим способом).&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;В
конце фрейма лишние элементы прячутся
(&lt;b&gt;display:none&lt;/b&gt;).&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;Жизненные
моменты&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;Я
теперь больше не пользуюсь Windows 7 дома,
и окончательно превратился в красноглазика
— на прошлой неделе, придя вечером домой, и желая начать писать новый пост, я
включил компьютер, и пошёл делать еду;
в принципе, я мог бы и не включать плиту,
так как готовить я мог прямо на радиаторе
чипсета :)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;Ноутбук
с gentoo пришёлся весьма кстати, но фотошопа
не хватает &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #eeeeee;&quot;&gt;(это мой open source ноут, где всё
ПО open source или на худой конец freeware)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: inherit;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: small;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: #999999;&quot;&gt;Гимп
он всё же написан программистами для
программистов — в нём есть почти всё
что есть в фотошопе (ну, наверное, кроме
векторных масок), только этим всем жутко
неудобно пользоваться.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-bottom: 0in;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;</description><link>http://nocanvas.blogspot.com/2010/02/gouraud-shading.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSx0s6shkO7CghJXB2ocVKjgJkFzgG5ZMgUvQmjMJoxZOPyCaV-MT2Z7vM0zlOpDjHfwIuTeznqB8133eNIbFj2PPqy3Uw4etUerUQvalMGsdH3MJQ-pkV13RZC7IB5Q5Ic5msCmx9QRgC/s72-c/illust.png" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-470385641609972564</guid><pubDate>Wed, 03 Feb 2010 12:32:00 +0000</pubDate><atom:updated>2010-02-08T19:39:00.864+02:00</atom:updated><title>Wolf 3D - не вовремя, но в тему</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://nocanvas.zame-dev.org/0001/&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwjZh6_91GbIggi-2600qGENhcJbswNVCplcXSfwujyE5Gv_eNsBEUol-d1Btn1YwSqvaAjSV19AUd27CWqpQupSLtVkI9nhpkapzrpsIWTl7I67nzEh0nVwZB8EIvd7KsBRW-3oemRXs3/s1600/illust.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Несмотря на то, что две недели ещё не прошло (а как вы помните, периодичность публикаций - раз в две недели), я всё же решил опубликовать эту запись сегодня. Причина этому ровно одна - на хабре я уже публиковал заметку про этот эффект, и не хочется дублировать статьи. Но как мне кажется, не все читали эту заметку двухлетней давности.&lt;br /&gt;
&lt;br /&gt;
После того, как вы посмотрите &lt;a href=&quot;http://nocanvas.zame-dev.org/0001/&quot;&gt;сам эффект&lt;/a&gt;, можно начинать разбор технологий.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Ray casting&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
В основе движка всемирно известной игры Wolfenstein 3D лежит оптимизированный Ray casting.&lt;br /&gt;
&lt;br /&gt;
Сейчас я поверхностно рассмотрю технологию, но знайте, что в гугле по словам &quot;ray casting&quot; находится целый кладезь информации.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPXlrxE9kEC4QQqX8gUnGTZxXAeyIXi5oknuUMdIjKhjcFeMUL2k34ZH1wLsE9fB23-iZHD7lwUZJX51f5tJdEnW-CwB-iiGXw5cZT0tbNQDYikWHYizKG_wLBdSXW3IEZj9xdB_kaLtS7/s1600-h/illust-1.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPXlrxE9kEC4QQqX8gUnGTZxXAeyIXi5oknuUMdIjKhjcFeMUL2k34ZH1wLsE9fB23-iZHD7lwUZJX51f5tJdEnW-CwB-iiGXw5cZT0tbNQDYikWHYizKG_wLBdSXW3IEZj9xdB_kaLtS7/s1600/illust-1.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Пусть есть карта, в каждой ячейке карты либо стоит блок (стена), либо не стоит. В некоторой свободной ячейке карты стоит игрок, и &quot;смотрит&quot; в определённую сторону. Изображение строится столбцами; испуская лучи от игрока к стенам, мы можем узнать расстояние до стен по всей протяжённости экрана, а высота каждого столбца будет обратно пропорциональна длине луча (чем длинее луч - тем меньше высота столбца).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUw-PU2XPma16570JzLCcATzN27RcBU_jgM_QqQ3sU9BY30XAuSa5gM68Wt6ZATtsw6lA3UbqGrPVZbTHJEoDY4dK4puaGiTfvOgxZmqgBa6_nJz4LE5c0QLR0sV8On68qlup5KJNTIitY/s1600-h/illust-2.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUw-PU2XPma16570JzLCcATzN27RcBU_jgM_QqQ3sU9BY30XAuSa5gM68Wt6ZATtsw6lA3UbqGrPVZbTHJEoDY4dK4puaGiTfvOgxZmqgBa6_nJz4LE5c0QLR0sV8On68qlup5KJNTIitY/s1600/illust-2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Но если реализовать этот алгоритм в лоб (использую для расчёта лучей, например, алгоритм Брезенхема), то можно изобрести машину времени, превращающую новый двухъядерный компьютер в 486 DX 100.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCypepHbhSSgXQWwK7ykYu0-DF5CXi0oHrUgQ536R4BtbFtU4qqLRSXFB9sbh6ws1Whs6gZrOprTwDFrqH26DFIlGSm8aEGmxQj0u2KUMeYyuRjBa-Qr2rX-K6F3Ao-HgA_VgUZn-joIma/s1600-h/illust-3.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCypepHbhSSgXQWwK7ykYu0-DF5CXi0oHrUgQ536R4BtbFtU4qqLRSXFB9sbh6ws1Whs6gZrOprTwDFrqH26DFIlGSm8aEGmxQj0u2KUMeYyuRjBa-Qr2rX-K6F3Ao-HgA_VgUZn-joIma/s1600/illust-3.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Однако можно заметить, что достаточно проверять на пересечение со стенкой только начало ячейки (потому что дальше в этой ячейке либо ничего нет, либо стена; инфа 100%). Достаточно найти первое пересечение (и по горизонтали, и по вертикали), и их приращения по X и Y.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-15YnJDgflCcfVLeTviXPwgpP1fk6xmANV4OhVuvbdTiJftUD2JDNhgzZgNoTT2t8oKqWxHhy92ZWSToCybmA4ODf-e4I75zq3DBfIo38dGb9FA7qo9pPz3n5CCKXKovO6vnkvjEYxK9M/s1600-h/illust-4.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;150&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-15YnJDgflCcfVLeTviXPwgpP1fk6xmANV4OhVuvbdTiJftUD2JDNhgzZgNoTT2t8oKqWxHhy92ZWSToCybmA4ODf-e4I75zq3DBfIo38dGb9FA7qo9pPz3n5CCKXKovO6vnkvjEYxK9M/s200/illust-4.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Тут правда есть один тонкий момент. Если вы сделаете всё в точности как написано, то, подойдя к прямой стене, вы увидите нечто, на прямую стену похожее лишь отдалённо.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK2jUvFkJefNVrvjVPKs7xixhnNhptQfXPKD-jWGJm4M2G-_-pXoGDPAnr9ZKqs6Wrv9yfZBuQkaSYPSpSdRuo6hsyddYOUs_P7mlRhMGAzACUHU00-xZjOYXSww3weE44WSfpTjt7UyyB/s1600-h/illust-5.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK2jUvFkJefNVrvjVPKs7xixhnNhptQfXPKD-jWGJm4M2G-_-pXoGDPAnr9ZKqs6Wrv9yfZBuQkaSYPSpSdRuo6hsyddYOUs_P7mlRhMGAzACUHU00-xZjOYXSww3weE44WSfpTjt7UyyB/s1600/illust-5.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Это происходит потому, что, несмотря на то, что игрок материальная точка, он всё-таки точка :), и лучи фокусируются на сфере (а экран плоский). Однако всё исправляется всего лишь одним умножением на корректирующее число (для каждого столбца своё).&lt;br /&gt;
&lt;div style=&quot;clear: both;&quot;&gt;
&lt;/div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Javascript &amp;amp; no canvas&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Для реализации wolf3d на джаваскрипте и без канваса, достаточно найти метод вывода столбцов (желательно с текстурой стены).&lt;br /&gt;
Отобразить один одноцветный столбец, можно используя DIV:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;div style=&quot;position:absolute; top:10px; left:5px; width:1px; height:80px; background-color:red;&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
Для того чтобы затекстурировать его, потребуется смешать технологию CSS-sprites и тэг IMG:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;div style=&quot;position:absolute; top:0px; left:5px; width:1px; height:256px; overflow:hidden;&quot;&amp;gt;
 &amp;lt;img src=&quot;wall.png&quot; style=&quot;position:absolute; top:10px; left:-32px; width:256px; height:80px;&quot; alt=&quot;&quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Браузер сам будет растягивать и сжимать столбец текстуры.&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;Технические моменты&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
В целом, для человека погуглившего по поводу Ray casting-а, код будет понятен, так что пройдусь сверху-вниз по исходнику (&lt;a href=&quot;http://nocanvas.zame-dev.org/0001/main.js&quot;&gt;http://nocanvas.zame-dev.org/0001/main.js&lt;/a&gt;), описывая общую картину и рассматривая неочевидные моменты.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;var CELL_SIZE = 64;
var MAX_IMAGE_HEIGHT = 2048;
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;CELL_SIZE&lt;/b&gt; - размер одного блока на карте.&lt;br /&gt;
&lt;b&gt;MAX_IMAGE_HEIGHT&lt;/b&gt; - ограничим максимальную высоту столбца, на всякий случай (чтоб какой-нибудь браузер не офигел от счастья растягивать картинку до 180263 пикселей в высоту).&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function create_view(width, height, mult) ...&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Создать необходимые DOM элементы для окна размером &lt;b&gt;width&lt;/b&gt; x &lt;b&gt;height&lt;/b&gt;. &lt;b&gt;mult&lt;/b&gt; - ширина одного столбца.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function cast(sx, sy, x, y, dx, dy) ...
function render_column(col, x, y, a, corr) ...&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
Эти две функции используются для рассчёта длины луча &lt;b&gt;col&lt;/b&gt;, направленного из точки &lt;b&gt;x&lt;/b&gt;,&lt;b&gt;y&lt;/b&gt; с углом a и корректирующим значением &lt;b&gt;corr&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function render_it() ...&lt;/pre&gt;
&lt;br /&gt;
Самая Главная Функция™&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function inner_loop() ...

function main_process()
{
 var old_x = hero_x; var old_y = hero_y; var old_a = hero_a;

 var time = (new Date()).valueOf();
 var loop_cnt = Math.round((time - prev_time) / MOVE_FREQ);

 if (loop_cnt &amp;gt; 0)
 {
  prev_time = time - ((time - prev_time) - (loop_cnt * MOVE_FREQ));

  while (loop_cnt &amp;gt; 0)
  {
   inner_loop();
   loop_cnt--;
  }
 }

 if (hero_x!=old_x || hero_y!=old_y || hero_a!=old_a) {
  render_it();
 }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Отдельно стоит рассмотреть функции &lt;b&gt;main_process&lt;/b&gt; и &lt;b&gt;inner_loop&lt;/b&gt;; разные браузеры обладают различным быстродействием, и то, что летает в хроме, необычайно тупит в IE8.&lt;br /&gt;
&lt;br /&gt;
Классический подход для проблем быстродействия - пересчитывать важные игровые моменты (координаты игрока, монстров, и т.д.) с точной определённой частотой, а рендерить изображение - как получится.&lt;br /&gt;
&lt;br /&gt;
К сожалению (или к счастью :) ), исполнение куска джаваскрипта (например, функции вызванной через &lt;b&gt;setTimeout&lt;/b&gt; или &lt;b&gt;setInterval&lt;/b&gt;) атомарно, и тупящий рендер не даст отработать функции пересчёта координат в нужный момент времени.&lt;br /&gt;
&lt;br /&gt;
Поэтому, поступим по-другому. Повесим рендер на &lt;b&gt;setInterval&lt;/b&gt;, а внутри рендера будем замерять, сколько времени прошло с предыдущего рендера, и вызывать пересчёт координат (функция &lt;b&gt;inner_loop&lt;/b&gt;) необходимое число раз.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;var MOVE_FREQ = (is_ie ? 50 : 20);

...

 if (is_ie) {
  create_view(120, 90, 4);
 } else {
  create_view(160, 120, 3);
 }
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Осталось только немного &quot;пропатчить&quot; скрипт для IE - меньшее поле обзора (но больший множитель, так что визуально оно такое же) и большее значение &lt;b&gt;MOVE_FREQ&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-large;&quot;&gt;А кроме того&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Данный эффект работает в IE6+, Chrome 1+, Fx 2.6+, Safari 4+, Opera 9+.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Интересно заметить, что в IE6 он работает значительно быстрее, нежели в IE8 и IE7 (за неимением реального IE7, тестировалось в IE8 в режиме IE7).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Не менее интересно то, что FireFox значительно быстрее работает с .gif, нежели с .png (пусть даже и 8-битным).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</description><link>http://nocanvas.blogspot.com/2010/02/wolf-3d.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwjZh6_91GbIggi-2600qGENhcJbswNVCplcXSfwujyE5Gv_eNsBEUol-d1Btn1YwSqvaAjSV19AUd27CWqpQupSLtVkI9nhpkapzrpsIWTl7I67nzEh0nVwZB8EIvd7KsBRW-3oemRXs3/s72-c/illust.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-244194832140162947.post-4844697515638580017</guid><pubDate>Wed, 27 Jan 2010 07:14:00 +0000</pubDate><atom:updated>2010-02-08T19:37:29.410+02:00</atom:updated><title>NoCanvas Introduction</title><description>&lt;a href=&quot;http://nocanvas.zame-dev.org/0000/&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKpUcoRryeKxh2lSYxchT0Ox9-fpNQiMYl678b0BzoUfZ2JDDswPGL2HgZpS8Wr6tgXOoFtIe_WCXypfUYGALwlUN0ymIjgHAArOeF5cGO7gv0iID3u47KpNGYstgat4TSwRDghZ8U_lZY/s320/illust.png&quot; /&gt;&lt;/a&gt; 3D с z-buffer-ом, субпиксельной точностью и освещением по Гуро на javascript? Да кто угодно сможет это сделать, &lt;a href=&quot;http://nocanvas.zame-dev.org/0000/&quot;&gt;используя canvas&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
Можно долго и вкусно описывать преимущества канваса, но статья не про это; не менее интересно&lt;br /&gt;
посмотреть, чем же канвас плох.&lt;br /&gt;
&lt;div style=&quot;clear: both;&quot;&gt;
&lt;/div&gt;
&lt;h4&gt;
Так чем же?&lt;/h4&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;Он ни в какую не работает в Обозревателе Интернета одной большой известной корпорации: эмулируя канвас через VML мы отрезаем самые вкусные пиксельные манипуцляции, а эмуяция пиксельных вкусняшек на flash безбожно тормозит из-за того, что где-то в недрах ExternalInterface разработчики из Adobe вставили пару функций sleep :)&lt;/li&gt;
&lt;li&gt;Только Google Chrome (aka Chromium) может обеспечить достаточную скорость исполнения джаваскрипта. Во всех остальных браузерах вкусный и сексуальный эффект рискует превратиться в слайд-шоу.&lt;/li&gt;
&lt;li&gt;И, наконец, самое главное — это неспортивно! Я уверен, что пока есть люди пишущие сапёров на bat файлах, тетрисы на sed и боярские диалекты C++, программирование ради самого процесса программирования будет интересовать массы :)&lt;/li&gt;
&lt;/ul&gt;
Я &lt;strike&gt;ненормальный псих&lt;/strike&gt; завёл блог, в котором собираюсь регулярно писать о создании различных эффектов и игр на javascript, не использующих канвас:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;раз в две недели&lt;/b&gt; я буду писать о каком-либо новом эффекте;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;раз в два месяца&lt;/b&gt; я буду рассказывать делать playable demo какой-нибудь игры (как водится, не использующую canvas);&lt;/li&gt;
&lt;li&gt;и, наконец, &lt;b&gt;раз в полгода&lt;/b&gt; я буду делать по игре (ну, по крайней мере, я буду очень стараться не сорвать сроки)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
Небольшая еретическая статья на затравку — как сделать 3D + z-buffer + subpixel + gouraud shading &lt;em&gt;используя&lt;/em&gt; канвас&lt;/h4&gt;
&lt;h4&gt;
&lt;span style=&quot;font-size: 13px;&quot;&gt;Шаг 0&lt;/span&gt;&lt;/h4&gt;
Для начала, необходимо позаботится о пользователях IE, предложив им поддержку тэга canvas в виде Chrome Frame: прописываем &lt;strong&gt;meta&lt;/strong&gt;, подключаем гуглоскрипт, создаём блок &lt;strong&gt;no-canvas&lt;/strong&gt; и правим стили для гугловского iframe (по умолчанию он появляется в центре страницы)&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;&amp;lt;head&amp;gt;
  &amp;lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;chrome=1&quot; /&amp;gt;
  &amp;lt;style type=&quot;text/css&quot; media=&quot;screen&quot;&amp;gt;
.chrome-install {
  position: relative;
  margin: 0;
  padding: 0;
  top: 0;
  left: 0;
}
  &amp;lt;/style&amp;gt;
  &amp;lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body onload=&quot;main()&quot;&amp;gt;
  &amp;lt;div id=&quot;no-canvas&quot; style=&quot;display:none;&quot;&amp;gt;
    &amp;lt;h2&amp;gt;&amp;amp;lt;canvas&amp;amp;gt; support required.&amp;lt;/h2&amp;gt;
    &amp;lt;div id=&quot;chrome-install-placeholder&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div id=&quot;canvas-enabled&quot;&amp;gt;
    &amp;lt;canvas id=&quot;canvas&quot; width=&quot;384&quot; height=&quot;384&quot;&amp;gt;&amp;lt;/canvas&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/pre&gt;
Функция &lt;strong&gt;main&lt;/strong&gt; (init вызывается по таймауту, потому что иначе хром (dev версия) иногда не прорисовывает background у body до конца):&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function main()
{
  canvas = document.getElementById(&#39;canvas&#39;);

  if (typeof(canvas.getContext) == &#39;function&#39;)
  {
    ctx = canvas.getContext(&#39;2d&#39;);
    setTimeout(init, 100);
  }
  else
  {
    document.getElementById(&#39;canvas-enabled&#39;).style.display = &#39;none&#39;;
    document.getElementById(&#39;no-canvas&#39;).style.display = &#39;&#39;;

    CFInstall.check({
      node: &#39;chrome-install-placeholder&#39;,
      className: &#39;chrome-install&#39;,
      destination: window.location.href
    });
  }
}
&lt;/pre&gt;
&lt;h5&gt;
Шаг 1&lt;/h5&gt;
Всю отрисовку будем вести в буфере 128x128, а потом его выводить с 3-х кратным увеличением (используя &lt;strong&gt;putImageData&lt;/strong&gt;).&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;var scr = [];
var zbuf = [];
var WDT = 128;
var HGT = 128;

function blit()
{
  var cd = ctx.createImageData(canvas.width, canvas.height);
  var data = cd.data;
  var ind = 0;

  for (var y = 0; y &amp;lt; HGT; y++)
  {
    var line = scr[y];

    for (var x = 0; x &amp;lt; WDT; x++)
    {
      data[ind++] = line[x][0]; data[ind++] = line[x][1]; data[ind++] = line[x][2]; data[ind++] = 255;
....
  }

  ctx.putImageData(cd, 0, 0);
}
&lt;/pre&gt;
&lt;h5&gt;
Шаг 2&lt;/h5&gt;
Представим фигуру в виде объекта и напишем читерскую функцию &lt;b&gt;box&lt;/b&gt;, которая будет создавать кубы сразу с нормалями:&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;{
  points: [
    {x: point_x, y: point_y, z: point_z, n: { x: point_normal_x, y: point_normal_y, z: point_normal_z } },
    ....
  ],
  faces: [
    [point_1, point_2, point_3, { x: face_normal_x, y: face_normal_y, z: face_normal_z }],
    ....
  ],
  color: object_color,
  rot: [rot_x, rot_y, rot_z]
}

function box(size, cl, rot)
{
  var norm = 1 / Math.sqrt(3);

  return {
    points: [
      { x: -size, y: size, z: -size, n: { x: -norm, y: norm, z: -norm } },
      ....
    ],
    faces: [
      [ 0, 1, 2, { x: 0, y: 1, z: 0 } ],
      ....
    ],
    color: cl,
    rot: rot
  };
}
&lt;/pre&gt;
&lt;h5&gt;
Шаг 3&lt;/h5&gt;
Выполним всю чёрную работу — повернём объект (вместе с нормалями — это быстрее, чем считать нормали заново) и спроецируем его в 2D (мне было лень нормально считать уровень освещённости, по-этому я использовал &lt;em&gt;метод научного тыка&lt;/em&gt;&lt;sup&gt;tm&lt;/sup&gt; для нахождения магической формулы и магических коеффициентов 0.7 и 3)&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function project(pt, rm)
{
  var rot = {
    x: (pt.x*rm.oxx + pt.y*rm.oxy + pt.z*rm.oxz),
    y: (pt.x*rm.oyx + pt.y*rm.oyy + pt.z*rm.oyz),
    z: (pt.x*rm.ozx + pt.y*rm.ozy + pt.z*rm.ozz + ZPOS)
  };

  var l = 1 - (Math.cos(pt.n.x*rm.ozx + pt.n.y*rm.ozy + pt.n.z*rm.ozz) - 0.7) * 3;
  l = Math.max(0, Math.min(1, l));

  return {
    x: ((WDT / 2) + rot.x * (WDT / 2 - 1) / rot.z),
    y: ((HGT / 2) + rot.y * (HGT / 2 - 1) / rot.z),
    z: rot.z,
    l: l
  };
}

function draw_object(obj)
{
  var ax = (tm * obj.rot[0]);
  var ay = (tm * obj.rot[1]);
  var az = (tm * obj.rot[2]);

  var s1 = Math.sin(ax); var s2 = Math.sin(ay); var s3 = Math.sin(az);
  var c1 = Math.cos(ax); var c2 = Math.cos(ay); var c3 = Math.cos(az);

  var rm = {
    oxx: (c2 * c1),
    oxy: (c2 * s1),
    ....
  };

  var pr = [];

  for (var i = 0; i &amp;lt; obj.points.length; i++) {
    pr.push(project(obj.points[i], rm));
  }

  for (var i = 0; i &amp;lt; obj.faces.length; i++)
  {
    var face = obj.faces[i];
    var fz = (face[3].x*rm.ozx + face[3].y*rm.ozy + face[3].z*rm.ozz);

    if (fz &amp;lt;= 0) {
      triangle(pr[face[0]], pr[face[1]], pr[face[2]], obj.color);
    }
  }
}
&lt;/pre&gt;
&lt;h5&gt;
Шаг 4&lt;/h5&gt;
Напишем процедуру рисования горизонтальных линий (не самую оптимальную) и треугольников (тоже не чемпион по скорости):&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function hline(y, xl, xr, cl, ll, lr, zl, zr)
{
  // Растянем линию горизонтально — так как мы используем треугольники,
  // а не честные полигоны, то при субпиксельной отрисовке без этого хака
  // иногда проявляются артефакты
  xl -= 0.5;
  xr += 0.5;
  ....
}

// **в реальном коде используется изменённая функция**
function triangle(a, b, c, cl)
{
  .... сортировка вершин ....

  var dxl = (c.x - a.x) / (c.y - a.y);
  var dxr = (b.x - a.x) / (b.y - a.y);
  ....
  var y = a.y;

  while (y &amp;lt; b.y)
  {
    // (y - a.y) - не обязательно целочисленное
    // за счёт этого достигается субпиксельная точность
    xl = sx + dxl * (y - a.y);
    xr = sx + dxr * (y - a.y);
    ....
    hline(y, xl, xr, cl, ll, lr, zl, zr);
    y++;
   }

   ....
}
&lt;/pre&gt;
&lt;h5&gt;
Шаг 5&lt;/h5&gt;
Остаётся написать функцию loop и запустить её через setInterval.&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; name=&quot;code&quot;&gt;function loop()
{
  tm = ((new Date()).valueOf() - st) / 1.5;

  draw_scene();
  blit();
}
&lt;/pre&gt;
&lt;h5&gt;
Эпилог&lt;/h5&gt;
Полный текст скрипта доступен по адресу &lt;a href=&quot;http://nocanvas.zame-dev.org/0000/index.html&quot;&gt;http://nocanvas.zame-dev.org/0000/index.html&lt;/a&gt; (просто загляните в исходный код страницы)</description><link>http://nocanvas.blogspot.com/2010/01/nocanvas-introduction.html</link><author>noreply@blogger.com (Restorer)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKpUcoRryeKxh2lSYxchT0Ox9-fpNQiMYl678b0BzoUfZ2JDDswPGL2HgZpS8Wr6tgXOoFtIe_WCXypfUYGALwlUN0ymIjgHAArOeF5cGO7gv0iID3u47KpNGYstgat4TSwRDghZ8U_lZY/s72-c/illust.png" height="72" width="72"/><thr:total>1</thr:total></item></channel></rss>