<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="https://blog.cscazorla.es/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.cscazorla.es/" rel="alternate" type="text/html" /><updated>2019-05-03T09:42:55+00:00</updated><id>https://blog.cscazorla.es/feed.xml</id><title type="html">El blog de CScazorla</title><subtitle>Hablando de Tecnología, Software, Videojuegos e Ingeniería.</subtitle><author><name>Carlos Sánchez Cazorla</name></author><entry><title type="html">Un quine que juega a la serpiente en su código fuente</title><link href="https://blog.cscazorla.es/desarrollo/2019/05/03/quinesnake.html" rel="alternate" type="text/html" title="Un quine que juega a la serpiente en su código fuente" /><published>2019-05-03T00:00:00+00:00</published><updated>2019-05-03T00:00:00+00:00</updated><id>https://blog.cscazorla.es/desarrollo/2019/05/03/quinesnake</id><content type="html" xml:base="https://blog.cscazorla.es/desarrollo/2019/05/03/quinesnake.html">&lt;p&gt;&lt;img src=&quot;https://github.com/taylorconor/quinesnake/raw/master/animation.gif&quot; alt=&quot;quinesnake&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Un &lt;a href=&quot;https://es.wikipedia.org/wiki/Quine_(programa)&quot;&gt;quine&lt;/a&gt; es un programa que produce su propio código fuente como salida. Un ejemplo en código C sería el siguiente:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main() { char *s=%c%s%c; printf(s,34,s,34); }&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;El quine que os presento hoy se llama &lt;a href=&quot;https://github.com/taylorconor/quinesnake&quot;&gt;quinesnake&lt;/a&gt; y se trata de un programa para jugar al famoso juego de la serpiente sobre su propio código fuente. El programa se compila solo, por lo que sólo tendremos que hacer ejecutable el código fuente y ejecturlo (el programa invoca a &lt;code class=&quot;highlighter-rouge&quot;&gt;g++&lt;/code&gt; cuando arranca). Para controlar a la serpiente usaremos las teclas &lt;code class=&quot;highlighter-rouge&quot;&gt;w&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;s&lt;/code&gt; y &lt;code class=&quot;highlighter-rouge&quot;&gt;d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El código fuente lo encontráis en &lt;a href=&quot;https://github.com/taylorconor/quinesnake/blob/master/quinesnake.cpp&quot;&gt;Github&lt;/a&gt; y tiene una pinta tal que así:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;erase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;L&quot;%d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;L&quot;(&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;L&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initscr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;){&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noecho&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;win&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();})&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;;I G(I x,I y){K 3&amp;amp;s[y*w+x]&amp;gt;&amp;gt;8;}I C(I x,I y,I c){(s[y*w+x]&amp;amp;=~z)|=c&amp;lt;&amp;lt;8;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Si queréis una versión más legible del código, y que además esté comentada, podéis encontrarla &lt;a href=&quot;https://github.com/taylorconor/quinesnake/blob/master/quinesnake-commented.cpp&quot;&gt;aquí&lt;/a&gt;.&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html"></summary></entry><entry><title type="html">¿Cómo se creó la intro de Marvel’s Spider-Man?</title><link href="https://blog.cscazorla.es/videojuegos/desarrollo/2019/04/24/desarrollo-escena-inicial-marvel-spiderman.html" rel="alternate" type="text/html" title="¿Cómo se creó la intro de Marvel's Spider-Man?" /><published>2019-04-24T00:00:00+00:00</published><updated>2019-04-24T00:00:00+00:00</updated><id>https://blog.cscazorla.es/videojuegos/desarrollo/2019/04/24/desarrollo-escena-inicial-marvel-spiderman</id><content type="html" xml:base="https://blog.cscazorla.es/videojuegos/desarrollo/2019/04/24/desarrollo-escena-inicial-marvel-spiderman.html">&lt;p&gt;Tras la última &lt;a href=&quot;https://www.gdconf.com/&quot;&gt;Game Developer Conference&lt;/a&gt; de este año, &lt;a href=&quot;https://twitter.com/despair&quot;&gt;Elan Ruskin&lt;/a&gt; desarrollador técnico de Marvel’s Spider-Man para PS4 en Insomniac Games, nos explica cómo se desarrolló la espectacular escena inicial del juego.&lt;/p&gt;

&lt;p&gt;En el siguiente vídeo explica, usando una cámara de depuración, cómo iban desactivando diferentes elementos del videjuego conforme la cámara se movía, liberando así recursos del sistema para poder cargar en memoria el escenario de la Torre Fisk. Como resultado, el jugador no apreciaba ningún tiempo de carga, y apreciaba una transición perfecta desde la cinemática de Manhattan hasta la ventana de la torre donde comienza el juego.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;es&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Also from our &lt;a href=&quot;https://twitter.com/hashtag/GDC19?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#GDC19&lt;/a&gt; tech postmortem: the transition into Fisk Tower in &lt;a href=&quot;https://twitter.com/hashtag/SpiderManPS4?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#SpiderManPS4&lt;/a&gt;&amp;#39;s intro mission. The interior space is much larger than the exterior envelope, and too big to hold in memory at the same time as Manhattan. So we use some careful camerawork to hide the swap! &lt;a href=&quot;https://t.co/Ur53ZSVGr8&quot;&gt;pic.twitter.com/Ur53ZSVGr8&lt;/a&gt;&lt;/p&gt;&amp;mdash; Elan Ruskin (@despair) &lt;a href=&quot;https://twitter.com/despair/status/1120448811531427841?ref_src=twsrc%5Etfw&quot;&gt;22 de abril de 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;Podéis encontrar más información sobre este post-mortem técnico y otras charlas detrás-de-las-cámaras en https://www.gdcvault.com/search.php#&amp;amp;category=free&amp;amp;firstfocus=&amp;amp;keyword=spider-man&amp;amp;conference_id=&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html">Tras la última Game Developer Conference de este año, Elan Ruskin desarrollador técnico de Marvel’s Spider-Man para PS4 en Insomniac Games, nos explica cómo se desarrolló la espectacular escena inicial del juego.</summary></entry><entry><title type="html">Libros de programación de Usborne de los años 80</title><link href="https://blog.cscazorla.es/videojuegos/desarrollo/libros/2019/04/23/usborne-coding-books.html" rel="alternate" type="text/html" title="Libros de programación de Usborne de los años 80" /><published>2019-04-23T00:00:00+00:00</published><updated>2019-04-23T00:00:00+00:00</updated><id>https://blog.cscazorla.es/videojuegos/desarrollo/libros/2019/04/23/usborne-coding-books</id><content type="html" xml:base="https://blog.cscazorla.es/videojuegos/desarrollo/libros/2019/04/23/usborne-coding-books.html">&lt;p&gt;&lt;img src=&quot;/assets/img/usborne-coding-books.png&quot; alt=&quot;Usborne Coding Books&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Los que seáis padres seguramente conozcáis la editorial &lt;a href=&quot;https://www.usborne.es&quot;&gt;Usborne&lt;/a&gt;, famosa por la calidad de sus libros infantiles. Además de su serie de libros infantiles Usborne ha estado editando libros de programación desde la década de los 80s. Con motivo del lanzamiento de su último libro, &lt;strong&gt;Coding for beginners using Python&lt;/strong&gt;, Usborne a puesto a libre disposición algunos sus libros más clásicos de los años 80. Podéis descargarlos en la siguiente web:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://usborne.com/browse-books/features/computer-and-coding-books/&quot;&gt;https://usborne.com/browse-books/features/computer-and-coding-books/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Os lo recomiendo encarecidamente ya que están maravillosamente ilustrados:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/usborne-coding-books-3.png&quot; alt=&quot;Usborne Coding Books&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/usborne-coding-books-2.png&quot; alt=&quot;Usborne Coding Books&quot; /&gt;&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html"></summary></entry><entry><title type="html">Construye tu propia Game Boy con Raspberry Pi</title><link href="https://blog.cscazorla.es/videojuegos/raspberry/2019/04/22/construye-tu-propia-gameboy.html" rel="alternate" type="text/html" title="Construye tu propia Game Boy con Raspberry Pi" /><published>2019-04-22T00:00:00+00:00</published><updated>2019-04-22T00:00:00+00:00</updated><id>https://blog.cscazorla.es/videojuegos/raspberry/2019/04/22/construye-tu-propia-gameboy</id><content type="html" xml:base="https://blog.cscazorla.es/videojuegos/raspberry/2019/04/22/construye-tu-propia-gameboy.html">&lt;p&gt;&lt;img src=&quot;/assets/img/gpi-case-retroflag-1.png&quot; alt=&quot;GPi CASE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;El pasado 21 de abril se cumplieron 30 años desde que la primera Game Boy fue lanzada en el año 1989 por &lt;a href=&quot;https://es.wikipedia.org/wiki/Gunpei_Yokoi&quot;&gt;Gunpei Yokoi&lt;/a&gt;. Esta consola, que ha vendido más de 118 millones de unidades hasta la fecha, marcó un antes y un después en el mundo de las consolas.&lt;/p&gt;

&lt;p&gt;Si eres un nostálgico al que esta consola evoca recuerdos inolvidables, ¿qué mejor manera que homenajearle construyendo tú mismo tu propia Game Boy?&lt;/p&gt;

&lt;h2 id=&quot;construyendo-tu-propia-game-boy&quot;&gt;Construyendo tu propia Game Boy&lt;/h2&gt;

&lt;p&gt;Montar un emulador de Game Boy con Raspberry Pi es muy sencillo. Hay numerosos tutoriales en Internet con suficiente información. Personalmente os recomiendo la plataforma &lt;a href=&quot;https://retropie.org.uk/&quot;&gt;Retropie&lt;/a&gt;, que tiene soporte para una ingente cantidad de sistemas (NES, Mega Drive, Amstrad, MAME, etc.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/gpi-case-retroflag-2.png&quot; alt=&quot;GPi CASE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sin embargo, el punto crítico para construir tu propia Game Boy y que la experiencia sea lo más cercana a la realidad, es la carcasa. &lt;a href=&quot;http://retroflag.com&quot;&gt;Retroflag&lt;/a&gt; soluciona ese problema con &lt;a href=&quot;http://retroflag.com/GPi-CASE.html&quot;&gt;GPi CASE&lt;/a&gt;. Este paquete, compatible con Raspberry Pi ZERO y ZERO W, incluye todo lo que necesitas para montar tu consola: pantalla IPS de 2.8 pulgadas, LEDs, etc.&lt;/p&gt;

&lt;h2 id=&quot;interesado-en-crear-juegos-de-game-boy&quot;&gt;¿Interesado en crear juegos de Game Boy?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://www.gbstudio.dev/img/screenshot.png&quot; alt=&quot;GB Studio&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Si siempre has pensado en realizar un videojuego para la Game Boy tienes que echar un vistazo a &lt;a href=&quot;https://www.gbstudio.dev/&quot;&gt;GB Studio&lt;/a&gt;, una herramienta gratuita y muy intuitiva para crear ROMs de Game Boy. No es necesario que tengas ningún conocimiento previo para desarrollar tus propios juegos. Usando su interfaz gráfica podrás diseñar los diferentes niveles y conectarlos entre sí.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/9k3RPaziVcw&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html"></summary></entry><entry><title type="html">¿Por qué hay atasco en los autobuses?</title><link href="https://blog.cscazorla.es/videojuegos/2019/04/03/por-que-hay-atasco-en-los-autobuses.html" rel="alternate" type="text/html" title="¿Por qué hay atasco en los autobuses?" /><published>2019-04-03T00:00:00+00:00</published><updated>2019-04-03T00:00:00+00:00</updated><id>https://blog.cscazorla.es/videojuegos/2019/04/03/por-que-hay-atasco-en-los-autobuses</id><content type="html" xml:base="https://blog.cscazorla.es/videojuegos/2019/04/03/por-que-hay-atasco-en-los-autobuses.html">&lt;p&gt;&lt;img src=&quot;/assets/img/setosa.io.png&quot; alt=&quot;Sistema de partículas&quot; /&gt;&lt;/p&gt;

&lt;p&gt;En la web de &lt;a href=&quot;http://setosa.io/bus/&quot;&gt;http://setosa.io/bus/&lt;/a&gt; han construido un estupendo simulador de una línea de autobuses urbana. ¿Has esperado alguna vez en una parada de autobús y de repente has visto llegar a dos o tres autobuses juntos? Este simulador nos ayuda a comprender cómo un ligero retraso de cualquier autobús hace que toda la línea se colapse, repercutiendo en largas colas y en un sistema ineficiente.&lt;/p&gt;

&lt;p&gt;En cualquier momento podemos pulsar en un autobús para “retrasarlo” y ver cómo impacta al funcionamiento del servicio. Dejando el ratón encima de una parada de autobús podemos ver una gráfica con el tiempo acumulado de espera de los usuarios.&lt;/p&gt;

&lt;p&gt;Para construir esta animación han usado varias herramientas diferentes: &lt;a href=&quot;http://d3js.org/&quot;&gt;d3&lt;/a&gt;, &lt;a href=&quot;https://material.angularjs.org&quot;&gt;Angular Material&lt;/a&gt;, &lt;a href=&quot;http://coffeescript.org&quot;&gt;Coffescript&lt;/a&gt;, &lt;a href=&quot;http://browserify.org&quot;&gt;Browserify&lt;/a&gt; y &lt;a href=&quot;http://gulpjs.com&quot;&gt;Gulp&lt;/a&gt;.&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html"></summary></entry><entry><title type="html">SQL injection crítico en Magento</title><link href="https://blog.cscazorla.es/cyberseguridad/2019/04/01/SQL-injection-Magento.html" rel="alternate" type="text/html" title="SQL injection crítico en Magento" /><published>2019-04-01T00:00:00+00:00</published><updated>2019-04-01T00:00:00+00:00</updated><id>https://blog.cscazorla.es/cyberseguridad/2019/04/01/SQL-injection-Magento</id><content type="html" xml:base="https://blog.cscazorla.es/cyberseguridad/2019/04/01/SQL-injection-Magento.html">&lt;p&gt;&lt;img src=&quot;data:image/png;base64,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&quot; alt=&quot;Magento&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Si utilizas la herramienta de e-commerce &lt;a href=&quot;https://magento.com/&quot;&gt;Magento&lt;/a&gt; debes actualizarla lo antes posible. El &lt;a href=&quot;https://magento.com/security/patches/magento-2.3.1-2.2.8-and-2.1.17-security-update&quot;&gt;viernes publicaron una nueva actualización&lt;/a&gt; que corregía más de 35 fallos de seguridad &lt;em&gt;críticos&lt;/em&gt;. Entre estos fallos de seguridad se encuentra una inyección de código SQL crítico explotable por usuarios no autenticados del sistema.&lt;/p&gt;

&lt;p&gt;Las versiones de Magento afectadas son:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Magento Open Source prior to 1.9.4.1&lt;/li&gt;
  &lt;li&gt;Magento Commerce prior to 1.14.4.1&lt;/li&gt;
  &lt;li&gt;Magento Commerce 2.1 prior to 2.1.17&lt;/li&gt;
  &lt;li&gt;Magento Commerce 2.2 prior to 2.2.8&lt;/li&gt;
  &lt;li&gt;Magento Commerce 2.3 prior to 2.3.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todavía no hay un CVE ID asociado a este fallo pero internamente se le conoce como &lt;em&gt;PRODSECBUG-2198&lt;/em&gt;. Ya que Magento almacena información financiera y el histórico de pedidos de los clientes, esta vulnerabilidad resulta realmente grave.&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html"></summary></entry><entry><title type="html">Aprendiendo sobre salud con Juego de Tronos</title><link href="https://blog.cscazorla.es/ciencia/2019/04/01/yo-doctor-game-of-thrones.html" rel="alternate" type="text/html" title="Aprendiendo sobre salud con Juego de Tronos" /><published>2019-04-01T00:00:00+00:00</published><updated>2019-04-01T00:00:00+00:00</updated><id>https://blog.cscazorla.es/ciencia/2019/04/01/yo-doctor-game-of-thrones</id><content type="html" xml:base="https://blog.cscazorla.es/ciencia/2019/04/01/yo-doctor-game-of-thrones.html">&lt;p&gt;&lt;img src=&quot;https://pbs.twimg.com/media/D2gGz52WsAAV7pX.jpg&quot; alt=&quot;Hodor - Afasia&quot; /&gt;&lt;/p&gt;

&lt;p&gt;El equipo de &lt;a href=&quot;https://t.co/x2N3rRT1Yy&quot;&gt;Yo, doctor&lt;/a&gt; ha creado una serie de infografías ambientadas en Juego de Tronos para explicar algunos problemas de salud (i.e. Hodor y la afasia). Es un orgullo tener gente así en España :)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://pbs.twimg.com/media/D20jmjTWsAUj3uz.jpg:large&quot; alt=&quot;Ghost - Albinismo&quot; /&gt;&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html"></summary></entry><entry><title type="html">Creando un sistema de partículas</title><link href="https://blog.cscazorla.es/videojuegos/2019/03/27/creando-un-sistema-de-particulas.html" rel="alternate" type="text/html" title="Creando un sistema de partículas" /><published>2019-03-27T00:00:00+00:00</published><updated>2019-03-27T00:00:00+00:00</updated><id>https://blog.cscazorla.es/videojuegos/2019/03/27/creando-un-sistema-de-particulas</id><content type="html" xml:base="https://blog.cscazorla.es/videojuegos/2019/03/27/creando-un-sistema-de-particulas.html">&lt;p&gt;Hoy os quiero enseñar lo sencillo que es hacer un sistema de partículas que os permita hacer efectos de humo, explosiones, o cualquier otra idea que se os ocurra. Utlizaremos el lenguaje de programación &lt;em&gt;Javascript&lt;/em&gt;, para que todos podáis probarlo en vuestro navegador y no sea necesario instalar ningún software. No os preocupéis, no necesitamos ningún doctorado en matemáticas o física para generar este sistema :)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/sistema-particulas.png&quot; alt=&quot;Sistema de partículas&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Todo el &lt;a href=&quot;#código-fuente&quot;&gt;código lo podéis encontrar al final del artículo&lt;/a&gt;. Se trata únicamente de dos ficheros:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt; - HTML para situar el canvas en la pantalla.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;main.js&lt;/code&gt; - Código Javascript para generar el sistema de partículas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para ejecutar la animación sólo tenéis que abrir &lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt; con cualquier navegador. Este código está basado en las demos &lt;a href=&quot;https://github.com/hunterloftis/playfuljs-demos&quot;&gt;PlayfulJS de Hunter Loftis&lt;/a&gt; al que he añadido algunos cambios.&lt;/p&gt;

&lt;h2 id=&quot;objetivo&quot;&gt;Objetivo&lt;/h2&gt;

&lt;p&gt;Nuestro objetivo es crear un &lt;em&gt;motor&lt;/em&gt; que mueva partículas por la pantalla hacia un punto determinado. En nuestro caso, ese punto será el cursor del ratón. Al iniciar la simulación, cada una de las partículas (situadas inicialmente en puntos aleatorios de la pantalla) se verán empujadas hacia la posición donde esté el ratón. Por tanto, lo que tendremos que implementar es un bucle (&lt;em&gt;game loop&lt;/em&gt;) que en cada &lt;em&gt;frame&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;pinte puntos/partículas por la pantalla,&lt;/li&gt;
  &lt;li&gt;calcule el vector velocidad (dirección y módulo) de cada partícula,&lt;/li&gt;
  &lt;li&gt;y avance &lt;em&gt;frame&lt;/em&gt; a &lt;em&gt;frame&lt;/em&gt; la simulación.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Estos tres pasos se ejecutarán (para todo el array de partículas) en nuestro &lt;em&gt;game loop&lt;/em&gt; de la siguiente manera:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;integrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;En cada frame de nuestra simulación se llamarán a tres funciones:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;attract()&lt;/code&gt; - Calcula cuál es la dirección y módulo de velocidad necesaria para cada partícula para alcanzar el punto destino (posición del ratón.)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;integrate()&lt;/code&gt; - Conocidas las coordenadas actuales y las que se quiere desplazar, realiza los cálculos de integración (posición -&amp;gt; velocidad -&amp;gt; aceleración).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;draw()&lt;/code&gt; - Dibuja la partícula en su nueva posición en la pantalla.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;el-sistema-de-partículas&quot;&gt;El sistema de partículas&lt;/h2&gt;

&lt;p&gt;Lo primero es definir una entidad en Javascript que nos permita gestionar cada partícula. En este caso se ha definido un objeto &lt;em&gt;Particle&lt;/em&gt; con dos atributos: su coordenada X e Y en la pantalla.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Inicialmente, como las partículas no se mueven, la posición anterior y la actual (tras la ejecución de un frame), será la misma.&lt;/p&gt;

&lt;p&gt;Al arrancar la simulación podremos inicializar (en posiciones aleatorias de la pantalla) tantas partículas como queramos mediante el siguiente bucle:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NUMBER_OF_PARTICLES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;el-bucle-principal&quot;&gt;El bucle principal&lt;/h2&gt;

&lt;h3 id=&quot;1-seguimiento-del-ratón&quot;&gt;1. Seguimiento del ratón&lt;/h3&gt;

&lt;p&gt;En esta simulación las partículas siguen la posición del ratón en la pantalla en cada frame. El efecto conseguido es el de un &lt;em&gt;enjambre&lt;/em&gt; de partículas siguiendo a un punto.&lt;/p&gt;

&lt;p&gt;Como veíamos anteriormente en el bucle principal, a la función &lt;code class=&quot;highlighter-rouge&quot;&gt;attract()&lt;/code&gt; se le pasan como parámetros las coordenadas X e Y actuales del ratón. El código de esta función es el siguiente:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attract&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;La distancia desde el punto actual de la partícula, al punto que queremos dirigirnos (la posición del ratón), podremos calcularla mediante el módulo del vector que une dichos puntos&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.rasmus.is/uk/t/F/Su58k03_m02.gif&quot; alt=&quot;Distancia entre dos puntos&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Actualizamos las variables locales &lt;code class=&quot;highlighter-rouge&quot;&gt;this.x&lt;/code&gt; y &lt;code class=&quot;highlighter-rouge&quot;&gt;this.y&lt;/code&gt; (que representan la posición que queremos alcanzar en el siguiente frame) con los valores deseados. La división por &lt;code class=&quot;highlighter-rouge&quot;&gt;distance&lt;/code&gt; provoca que las partículas más cercanas al ratón se desplacen con mayor aceleración (podemos verlo como una fuerza de atracción mayor)&lt;/p&gt;

&lt;h3 id=&quot;2-mover-las-partículas&quot;&gt;2. Mover las partículas&lt;/h3&gt;

&lt;p&gt;Tenemos que enseñar a nuestras partículas a moverse por la pantalla. En cada frame hay que decir a cada partícula la nueva dirección y módulo de su velocidad. En el paso anterior calculamos en las variables locales &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; e &lt;code class=&quot;highlighter-rouge&quot;&gt;y&lt;/code&gt; de cada partícula la nueva coordenada a la que queremos que se desplace. Para poder conseguir una velocidad (variación de posición / variación de tiempo), necesitamos integrar.&lt;/p&gt;

&lt;p&gt;Un recurso sencillo, y que nos evita tener que integrar, es utilizar la &lt;a href=&quot;https://es.wikipedia.org/wiki/Integraci%C3%B3n_de_Verlet&quot;&gt;Integración de Verlet&lt;/a&gt;. Lo que hacemos es comparar la posición actual de la partícula (la que hemos calculado en el paso anterior y que queremos alcanzar) respecto a su posición en el &lt;em&gt;frame&lt;/em&gt; anterior (la que tiene actualmente).&lt;/p&gt;

&lt;p&gt;Nuestro proceso de integración de la posición de la partícula de un &lt;em&gt;frame&lt;/em&gt; a otro se realiza mediante la siguiente función:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;integrate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DAMPING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DAMPING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Las variables &lt;code class=&quot;highlighter-rouge&quot;&gt;velocityX&lt;/code&gt; y &lt;code class=&quot;highlighter-rouge&quot;&gt;velocityY&lt;/code&gt; almacenan la diferencia de posición en X e Y entre el frame actual y el frame anterior. Se multiplican por un coeficiente &lt;code class=&quot;highlighter-rouge&quot;&gt;DAMPING&lt;/code&gt; para darle cierto toque de rozamiento.&lt;/p&gt;

&lt;h3 id=&quot;3-pintar-la-partícula&quot;&gt;3. Pintar la partícula&lt;/h3&gt;

&lt;p&gt;El último paso es dibujar en pantalla la posición de la partícula. Para ello haremos uso de la siguiente función:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;COLOR_ENABLED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strokeStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1000000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xffffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strokeStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#ffffff'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lineWidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moveTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lineTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Esta función se encarga de pintar el pixel en la pantalla y moverlo de la posición anterior (&lt;code class=&quot;highlighter-rouge&quot;&gt;this.oldx&lt;/code&gt;,&lt;code class=&quot;highlighter-rouge&quot;&gt;this.oldy&lt;/code&gt;) a la nueva posición (&lt;code class=&quot;highlighter-rouge&quot;&gt;this.x&lt;/code&gt;,&lt;code class=&quot;highlighter-rouge&quot;&gt;this.y&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;COLOR_ENABLED&lt;/code&gt; es una variable de configuración para indicar si queremos pintar cada partícula de un color diferente. En caso contrario, todas se pintarán en blanco.&lt;/p&gt;

&lt;h2 id=&quot;código-fuente&quot;&gt;Código fuente&lt;/h2&gt;

&lt;h3 id=&quot;indexhtml&quot;&gt;index.html&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;viewport&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Sistema de Partículas&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'background: #000; margin: 0; padding: 0; width: 100%; height: 100%;'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'display'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'1'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'1'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'width: 100%; height: 100%;'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;mainjs&quot;&gt;main.js&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DAMPING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.99999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NUMBER_OF_PARTICLES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;COLOR_ENABLED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;integrate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DAMPING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DAMPING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;velocityY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attract&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;COLOR_ENABLED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strokeStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x1000000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xffffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;strokeStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'#ffffff'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lineWidth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;beginPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moveTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;oldY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lineTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'display'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2d'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NUMBER_OF_PARTICLES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Particle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'mousemove'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onMousemove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onMousemove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clientX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clientY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clearRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;integrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;particles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html">Hoy os quiero enseñar lo sencillo que es hacer un sistema de partículas que os permita hacer efectos de humo, explosiones, o cualquier otra idea que se os ocurra. Utlizaremos el lenguaje de programación Javascript, para que todos podáis probarlo en vuestro navegador y no sea necesario instalar ningún software. No os preocupéis, no necesitamos ningún doctorado en matemáticas o física para generar este sistema :)</summary></entry><entry><title type="html">Markdown2PDF</title><link href="https://blog.cscazorla.es/herramientas/2019/03/26/Markdown2PDF.html" rel="alternate" type="text/html" title="Markdown2PDF" /><published>2019-03-26T00:00:00+00:00</published><updated>2019-03-26T00:00:00+00:00</updated><id>https://blog.cscazorla.es/herramientas/2019/03/26/Markdown2PDF</id><content type="html" xml:base="https://blog.cscazorla.es/herramientas/2019/03/26/Markdown2PDF.html">&lt;p&gt;Hoy os quiero enseñar la aplicación &lt;a href=&quot;https://md2pdf.netlify.com/&quot;&gt;Markdown2PDF&lt;/a&gt;. Se trata de una página web que nos permite escribir texto en formato &lt;em&gt;markdown&lt;/em&gt; y convertirlo en PDF directamente desde el navegador.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/md2pdf.netlify.com.png&quot; alt=&quot;Markdown2PDF&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Podemos escribir nuestro texto &lt;em&gt;markdown&lt;/em&gt; en el navegador o podemos subir un fichero .md desde nuestro ordenador. Automáticamente el texto se renderizará en la pantalla mostrando enlaces, bloques de código, emojis, etc.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/md2pdf.netlify.com2.png&quot; alt=&quot;Markdown2PDF&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pulsando en el botón &lt;em&gt;Transform&lt;/em&gt; podremos generar el fichero PDF.&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html">Hoy os quiero enseñar la aplicación Markdown2PDF. Se trata de una página web que nos permite escribir texto en formato markdown y convertirlo en PDF directamente desde el navegador.</summary></entry><entry><title type="html">Aventuras conversacionales con Microsoft TextWorld</title><link href="https://blog.cscazorla.es/videojuegos/2019/03/25/Aventuras-conversacionales-text-world.html" rel="alternate" type="text/html" title="Aventuras conversacionales con Microsoft TextWorld" /><published>2019-03-25T00:00:00+00:00</published><updated>2019-03-25T00:00:00+00:00</updated><id>https://blog.cscazorla.es/videojuegos/2019/03/25/Aventuras-conversacionales-text-world</id><content type="html" xml:base="https://blog.cscazorla.es/videojuegos/2019/03/25/Aventuras-conversacionales-text-world.html">&lt;p&gt;¿Sois del selecto grupo de personas que crecísteis con las aventuras conversacionales? ¿Disfrutásteis durante horas y horas tecleando comandos en &lt;a href=&quot;http://wiki.caad.es/La_Aventura_Original&quot;&gt;La Aventura Original&lt;/a&gt;, &lt;a href=&quot;https://www.caad.es/fichas/zork-en-espanol.html&quot;&gt;Zork&lt;/a&gt;, &lt;a href=&quot;https://tabernadegrog.blogspot.com/2019/02/don-quijote-aventura-conversacional.html&quot;&gt;El Quijote&lt;/a&gt; o &lt;a href=&quot;http://computeremuzone.com/ficha.php?id=136&quot;&gt;Megacorp&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/aventura-original.jpg&quot; alt=&quot;La Aventura Original&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Si habéis respondido &lt;em&gt;sí&lt;/em&gt;, y además siempre habéis soñado con poder desarrollar vosotros mismos una aventura conversacional, tenéis que probar &lt;a href=&quot;https://textworld.readthedocs.io/en/latest/index.html&quot;&gt;TextWorld&lt;/a&gt;. Esta herramienta Open-Source desarrollada en Python por &lt;a href=&quot;https://www.microsoft.com/en-us/research/project/textworld/&quot;&gt;Microsoft&lt;/a&gt; permite generar y simular aventuras conversacionales.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://textworld.readthedocs.io/en/latest/_images/TextWorld.png&quot; alt=&quot;La Aventura Original&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A partir de una serie de parámetros como el tamaño del mapa, número de objetos, extensión de la aventura, complejidad, etc. permite generar aventuras y jugarlas. Por ejemplo, para generar un mapa y en la carpeta &lt;code class=&quot;highlighter-rouge&quot;&gt;tw_games&lt;/code&gt; sólo tendríamos que ejecutar en la consola:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;tw&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;custom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;objects&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;quest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;seed&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tw_games&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;custom_game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ulx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Para jugar a este juego sólo tendríamos que ejecutarlo mediante:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tw-play tw_games/custom_game.ulx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Por cierto, si os interesa este mundillo no dejéis de leer este fabuloso &lt;a href=&quot;https://www.xataka.com/literatura-comics-y-juegos/en-el-principio-fue-la-aventura-conversacional&quot;&gt;artículo de John Tones en Xataka&lt;/a&gt;&lt;/p&gt;</content><author><name>Carlos Sánchez Cazorla</name></author><summary type="html">¿Sois del selecto grupo de personas que crecísteis con las aventuras conversacionales? ¿Disfrutásteis durante horas y horas tecleando comandos en La Aventura Original, Zork, El Quijote o Megacorp?</summary></entry></feed>